@poe-platform/safe-bash 0.1.800 → 0.1.801

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 (459) hide show
  1. package/README.md +16 -5
  2. package/dist/image-ast/index.browser.js +119 -75
  3. package/dist/image-ast/index.js +119 -75
  4. package/dist/pdf-ast/index.js +4 -3
  5. package/dist/safe-bash/chunks/{chunk-LUOFIVNI.js → chunk-3NDIFSNM.js} +3 -3
  6. package/dist/safe-bash/chunks/{chunk-4SEW2Q6H.js → chunk-3R3AANOR.js} +1 -1
  7. package/dist/safe-bash/chunks/{chunk-HHW7MGS2.js → chunk-45PK3NWI.js} +4 -4
  8. package/dist/safe-bash/chunks/{chunk-KHMGTPD6.js → chunk-46Z5E5EV.js} +2 -2
  9. package/dist/safe-bash/chunks/{chunk-XB3B7KMM.js → chunk-6O77NL2S.js} +1 -1
  10. package/dist/safe-bash/chunks/{chunk-T3JTVIEP.js → chunk-6PAVEFT3.js} +1 -1
  11. package/dist/safe-bash/chunks/{chunk-PYVEAFJM.js → chunk-74GHTNJA.js} +3 -2
  12. package/dist/safe-bash/chunks/{chunk-LQHGH25W.js → chunk-7R5BDCG7.js} +1 -1
  13. package/dist/safe-bash/chunks/{chunk-RMWLWH7Q.js → chunk-7VNF5BFF.js} +300 -737
  14. package/dist/safe-bash/chunks/{chunk-QVSRRNZT.js → chunk-A7XEHALN.js} +4 -4
  15. package/dist/safe-bash/chunks/{chunk-MHZ24KEI.js → chunk-AM5ESLPH.js} +1 -1
  16. package/dist/safe-bash/chunks/{chunk-3L3T6LYV.js → chunk-AUSNDQTJ.js} +1 -1
  17. package/dist/safe-bash/chunks/{chunk-YG5WAHK7.js → chunk-B7TAL7S5.js} +1 -3
  18. package/dist/safe-bash/chunks/{chunk-K7IQZE7D.js → chunk-C5OWC2TL.js} +1 -1
  19. package/dist/safe-bash/chunks/{chunk-F3RV2F72.js → chunk-CHYGPFVM.js} +1 -1
  20. package/dist/safe-bash/chunks/{chunk-M4CFCXHN.js → chunk-CS4MNM6I.js} +1 -1
  21. package/dist/safe-bash/chunks/{chunk-H6JW3E4F.js → chunk-CTVWDACF.js} +1 -1
  22. package/dist/safe-bash/chunks/{chunk-BHJE5LPZ.js → chunk-D3ANYGMC.js} +1 -1
  23. package/dist/safe-bash/chunks/{chunk-NLAW7KDI.js → chunk-E7OYNDGL.js} +1 -1
  24. package/dist/safe-bash/chunks/{chunk-SOZK5JVX.js → chunk-FBUCWVTE.js} +1 -1
  25. package/dist/safe-bash/chunks/{chunk-RKKRJ54E.js → chunk-FNDNHAGE.js} +30 -23
  26. package/dist/safe-bash/chunks/{chunk-KCVSVD65.js → chunk-I5HZ4FGE.js} +1 -1
  27. package/dist/safe-bash/chunks/{chunk-JJSTTIEZ.js → chunk-ICFDYV64.js} +1 -1
  28. package/dist/safe-bash/chunks/{chunk-TYD7EVUJ.js → chunk-IVRQ4BXL.js} +1 -1
  29. package/dist/safe-bash/chunks/{chunk-KV7PKOHV.js → chunk-IWDICZVK.js} +1 -1
  30. package/dist/safe-bash/chunks/{chunk-I4OAEOP6.js → chunk-J42RIHHJ.js} +1 -1
  31. package/dist/safe-bash/chunks/{chunk-K2VCOJ2B.js → chunk-K6VCD7IY.js} +7 -12
  32. package/dist/safe-bash/chunks/{chunk-63FXVDGF.js → chunk-LVOBFF4D.js} +1 -1
  33. package/dist/safe-bash/chunks/{chunk-U5NUZPCC.js → chunk-MHMMRCYC.js} +1 -1
  34. package/dist/safe-bash/chunks/{chunk-6HZYFL3H.js → chunk-NR3EM4LS.js} +1 -1
  35. package/dist/safe-bash/chunks/{chunk-VYZTG3GV.js → chunk-NZQXYWA3.js} +1 -1
  36. package/dist/safe-bash/chunks/{chunk-TFGRKY43.js → chunk-OQRVVGR6.js} +1 -1
  37. package/dist/safe-bash/chunks/{chunk-PPYM75Z3.js → chunk-OV6IHKO6.js} +2 -2
  38. package/dist/safe-bash/chunks/{chunk-KW24TAIU.js → chunk-PQRAK7HU.js} +920 -432
  39. package/dist/safe-bash/chunks/{chunk-K4YMYFRJ.js → chunk-SZH7EJLD.js} +116 -697
  40. package/dist/safe-bash/chunks/{chunk-7YSRXFEG.js → chunk-TFIBK2GI.js} +1 -1
  41. package/dist/safe-bash/chunks/{chunk-I7L3G3NX.js → chunk-UE5KZDEK.js} +2 -2
  42. package/dist/safe-bash/chunks/{chunk-QU3BVQ53.js → chunk-UTBUUFDM.js} +1 -1
  43. package/dist/safe-bash/chunks/{chunk-JTLSUJ7V.js → chunk-VQDD3G76.js} +42 -25
  44. package/dist/safe-bash/chunks/{chunk-46UISJCK.js → chunk-VTH3MLDU.js} +1 -1
  45. package/dist/safe-bash/chunks/{chunk-LLZCZ24K.js → chunk-XVOSKJE2.js} +1 -1
  46. package/dist/safe-bash/chunks/{csvkit-QGP3GAOB.js → csvkit-TACDU7FC.js} +3 -3
  47. package/dist/safe-bash/chunks/{ffmpeg-JTVH26MK.js → ffmpeg-WTC3TEFI.js} +2 -2
  48. package/dist/safe-bash/chunks/{gh-I7QX7N5C.js → gh-6WU6PXL4.js} +2 -2
  49. package/dist/safe-bash/chunks/{git-MA7NKYVP.js → git-EFZIGJW4.js} +2 -2
  50. package/dist/safe-bash/chunks/{imagemagick-Y4NPWX2Q.js → imagemagick-EIEYGWPF.js} +2 -2
  51. package/dist/safe-bash/chunks/{implementation-BWDKOVQJ.js → implementation-MLFHUQ5M.js} +2 -2
  52. package/dist/safe-bash/chunks/{mmdc-44PELHDG.js → mmdc-ROQJT5HQ.js} +2 -2
  53. package/dist/safe-bash/chunks/{pdfimages-635TRW4Q.js → pdfimages-DW7LWXFI.js} +2 -2
  54. package/dist/safe-bash/chunks/{pdfinfo-FSDAA2KY.js → pdfinfo-TIP6XLUQ.js} +2 -2
  55. package/dist/safe-bash/chunks/{pdftk-GQ5UH3VG.js → pdftk-DMG22ITZ.js} +2 -2
  56. package/dist/safe-bash/chunks/{pdftoppm-YTXQCAYT.js → pdftoppm-WNDYR72T.js} +2 -2
  57. package/dist/safe-bash/chunks/{pdftotext-CVA2G7FY.js → pdftotext-5IPZ4NI7.js} +2 -2
  58. package/dist/safe-bash/chunks/{qpdf-HZMIFG4A.js → qpdf-TTX2DIUA.js} +2 -2
  59. package/dist/safe-bash/chunks/{sips-E7UBDP33.js → sips-XYS46JPJ.js} +2 -2
  60. package/dist/safe-bash/chunks/{soffice-ELASUWUK.js → soffice-TU73E5KL.js} +2 -2
  61. package/dist/safe-bash/chunks/{wkhtmltopdf-EPO6YCMG.js → wkhtmltopdf-FSZ2CHGE.js} +2 -2
  62. package/dist/safe-bash/command-chunks/{chunk-QBGA56UH.js → chunk-2ELYGJDD.js} +7 -7
  63. package/dist/safe-bash/command-chunks/{chunk-52PCQXD2.js → chunk-2NHI5F5S.js} +2 -1
  64. package/dist/safe-bash/command-chunks/{chunk-HDKVO47G.js → chunk-2SQEIUGJ.js} +3 -3
  65. package/dist/safe-bash/command-chunks/{chunk-5LSGEIZY.js → chunk-3HHCU5YU.js} +4 -3
  66. package/dist/safe-bash/command-chunks/{chunk-TF6OA2GK.js → chunk-3NV3HYT2.js} +1 -1
  67. package/dist/safe-bash/command-chunks/{chunk-2QHG43WJ.js → chunk-4BB2SWJ5.js} +1 -1
  68. package/dist/safe-bash/command-chunks/{chunk-IEXHHNOF.js → chunk-4J5CZ2DP.js} +2 -7
  69. package/dist/safe-bash/command-chunks/{chunk-WDHI3S6Y.js → chunk-4OOUQTQO.js} +1 -1
  70. package/dist/safe-bash/command-chunks/{chunk-YMONDXET.js → chunk-4ZQWGOZB.js} +2 -2
  71. package/dist/safe-bash/command-chunks/{chunk-L6DVEBW3.js → chunk-5BSTFCXG.js} +2 -2
  72. package/dist/safe-bash/command-chunks/{chunk-Q3DII3Q7.js → chunk-5PWJG2UK.js} +1 -1
  73. package/dist/safe-bash/command-chunks/{chunk-JMPP4TCW.js → chunk-5UBXNSFZ.js} +3 -2
  74. package/dist/safe-bash/command-chunks/{chunk-3NG75MOB.js → chunk-67GQA75T.js} +1 -1
  75. package/dist/safe-bash/command-chunks/{chunk-L6SU4S26.js → chunk-6B7WQIKB.js} +0 -7
  76. package/dist/safe-bash/command-chunks/{chunk-V6MSPQLA.js → chunk-6BNTBWIK.js} +4 -39
  77. package/dist/safe-bash/command-chunks/{chunk-JN7WIP6S.js → chunk-6KJ3LPI2.js} +2 -2
  78. package/dist/safe-bash/command-chunks/{chunk-HLDTOR7M.js → chunk-6ZVI7LUY.js} +1 -1
  79. package/dist/safe-bash/command-chunks/{chunk-X6NJC3IC.js → chunk-75OFBY5R.js} +1 -1
  80. package/dist/safe-bash/command-chunks/{chunk-MRW5HD2D.js → chunk-7O3E4LPT.js} +4 -22
  81. package/dist/safe-bash/command-chunks/{chunk-TEVJJPTC.js → chunk-7U7EXOXX.js} +1 -1
  82. package/dist/safe-bash/command-chunks/{chunk-6CYTRQ24.js → chunk-7VTKQUA5.js} +20 -17
  83. package/dist/safe-bash/command-chunks/{chunk-BZPAWTUL.js → chunk-AEF5BA3D.js} +1 -1
  84. package/dist/safe-bash/command-chunks/{chunk-63R3FEZJ.js → chunk-AIV5BF5W.js} +1 -1
  85. package/dist/safe-bash/command-chunks/{chunk-AYUTO323.js → chunk-AKJG2XD3.js} +2 -18
  86. package/dist/safe-bash/command-chunks/{chunk-J34TZVMW.js → chunk-ALDC4XP4.js} +0 -5
  87. package/dist/safe-bash/command-chunks/{chunk-CKXV2CLD.js → chunk-ARBYOQUZ.js} +1 -1
  88. package/dist/safe-bash/command-chunks/{chunk-44AHAB5O.js → chunk-BDSMROQZ.js} +1 -4
  89. package/dist/safe-bash/command-chunks/{chunk-53P53XFM.js → chunk-BPE5INLI.js} +1 -1
  90. package/dist/safe-bash/command-chunks/{chunk-OT4LZMLB.js → chunk-BR73BIOW.js} +1 -1
  91. package/dist/safe-bash/command-chunks/{chunk-WB5SVIG7.js → chunk-C5YYCQHW.js} +498 -88
  92. package/dist/safe-bash/command-chunks/{chunk-EUSPTFAX.js → chunk-CAP7ZJSY.js} +7 -7
  93. package/dist/safe-bash/command-chunks/{chunk-DWFLVJC6.js → chunk-CCRHMAU5.js} +2 -1
  94. package/dist/safe-bash/command-chunks/{chunk-GI4CJED2.js → chunk-CQTRW45K.js} +1 -1
  95. package/dist/safe-bash/command-chunks/{chunk-N2F74VRO.js → chunk-CZ7EN3JG.js} +1 -1
  96. package/dist/safe-bash/command-chunks/{chunk-KKG4BAFZ.js → chunk-DIEPXUM4.js} +6 -0
  97. package/dist/safe-bash/command-chunks/{chunk-QJAFJP2G.js → chunk-DZCY63VJ.js} +12 -10
  98. package/dist/safe-bash/command-chunks/{chunk-QUENU6GM.js → chunk-E55UKBIE.js} +3 -3
  99. package/dist/safe-bash/command-chunks/{chunk-HLGKIZ25.js → chunk-F6OYH562.js} +2 -0
  100. package/dist/safe-bash/command-chunks/{chunk-MC3VWLIZ.js → chunk-FDBUV4HJ.js} +28 -19
  101. package/dist/safe-bash/command-chunks/{chunk-7FKUC34S.js → chunk-FPVUD6TH.js} +6 -3
  102. package/dist/safe-bash/command-chunks/{chunk-E2LB7FRT.js → chunk-FXOA7RBK.js} +1 -1
  103. package/dist/safe-bash/command-chunks/{chunk-QWIDNAAK.js → chunk-FZTK4MFI.js} +3 -3
  104. package/dist/safe-bash/command-chunks/{chunk-K543PB3I.js → chunk-G66QUHIZ.js} +6 -35
  105. package/dist/safe-bash/command-chunks/{chunk-YJDV76GL.js → chunk-GFQZCKO6.js} +29 -19
  106. package/dist/safe-bash/command-chunks/{chunk-FKKB5X5V.js → chunk-GOB777HR.js} +1 -1
  107. package/dist/safe-bash/command-chunks/{chunk-IYPAQ7PH.js → chunk-GRBWW4SG.js} +6 -0
  108. package/dist/safe-bash/command-chunks/{chunk-PPNBNFAU.js → chunk-GYQ2HAKQ.js} +8 -8
  109. package/dist/safe-bash/command-chunks/{chunk-PJJUYO3R.js → chunk-II77KPZN.js} +2 -2
  110. package/dist/safe-bash/command-chunks/{chunk-VL67NWNS.js → chunk-JDYXY44P.js} +2 -2
  111. package/dist/safe-bash/command-chunks/{chunk-4QJOYXVB.js → chunk-JV7LBUTP.js} +1 -1
  112. package/dist/safe-bash/command-chunks/{chunk-IKS2YXZQ.js → chunk-K67MWWWH.js} +3 -3
  113. package/dist/safe-bash/command-chunks/{chunk-BKCNF5U3.js → chunk-KQLD3AED.js} +2 -2
  114. package/dist/safe-bash/command-chunks/{chunk-UMDIOL3O.js → chunk-KXU3IRUO.js} +1 -1
  115. package/dist/safe-bash/command-chunks/{chunk-QZF3SINC.js → chunk-LAOM65EE.js} +2 -2
  116. package/dist/safe-bash/command-chunks/{chunk-HFII3QYO.js → chunk-LWS62ISU.js} +46 -32
  117. package/dist/safe-bash/command-chunks/{chunk-BZDDAPSV.js → chunk-LWSBAWLT.js} +1 -1
  118. package/dist/safe-bash/command-chunks/{chunk-U6G67N23.js → chunk-MIXBO6U7.js} +18 -5
  119. package/dist/safe-bash/command-chunks/{chunk-JQ74HC37.js → chunk-MQFIPHIQ.js} +23 -50
  120. package/dist/safe-bash/command-chunks/{chunk-ZJBR5Q5I.js → chunk-MSFXC3OC.js} +4 -4
  121. package/dist/safe-bash/command-chunks/{chunk-NI7MKJPN.js → chunk-MTQH74CF.js} +3 -55
  122. package/dist/safe-bash/command-chunks/chunk-MWUZZWXK.js +354 -0
  123. package/dist/safe-bash/command-chunks/{chunk-RVLO4DYT.js → chunk-N4PFUSRM.js} +1 -1
  124. package/dist/safe-bash/command-chunks/{chunk-D4OP2BR3.js → chunk-NKFYQSES.js} +1 -2
  125. package/dist/safe-bash/command-chunks/{chunk-NGWB2YBL.js → chunk-O4JQSB7O.js} +1 -1
  126. package/dist/safe-bash/command-chunks/{chunk-7L24L4UO.js → chunk-OQU6UT6X.js} +2 -20
  127. package/dist/safe-bash/command-chunks/{chunk-TYCGMRLM.js → chunk-OYYV7ZAF.js} +1 -1
  128. package/dist/safe-bash/command-chunks/{chunk-SVULUDOP.js → chunk-P2N33UMN.js} +20 -81
  129. package/dist/safe-bash/command-chunks/{chunk-Q7Q5GM5S.js → chunk-P5APDEFB.js} +2 -2
  130. package/dist/safe-bash/command-chunks/{chunk-SAMH7SQE.js → chunk-PCEFOYA3.js} +237 -145
  131. package/dist/safe-bash/command-chunks/{chunk-3HXDA5PT.js → chunk-PMBFZXTK.js} +1 -1
  132. package/dist/safe-bash/command-chunks/{chunk-4Y3WVMK4.js → chunk-PV66YWHB.js} +1 -0
  133. package/dist/safe-bash/command-chunks/{chunk-AXK3H4PX.js → chunk-QJ33BHI4.js} +1 -1
  134. package/dist/safe-bash/command-chunks/{chunk-3LSOYLNV.js → chunk-QKFSRZGQ.js} +2 -2
  135. package/dist/safe-bash/command-chunks/{chunk-JZSNU2MY.js → chunk-QKJLP53H.js} +2 -2
  136. package/dist/safe-bash/command-chunks/{chunk-LC2MFKT4.js → chunk-RMWQAAO5.js} +24 -25
  137. package/dist/safe-bash/command-chunks/{chunk-QDTBMSBE.js → chunk-RO62EWX6.js} +2 -2
  138. package/dist/safe-bash/command-chunks/{chunk-4C6QI5BQ.js → chunk-RZZI24ZE.js} +4 -4
  139. package/dist/safe-bash/command-chunks/{chunk-PFAADCB5.js → chunk-SDNBCQ3X.js} +10 -24
  140. package/dist/safe-bash/command-chunks/{chunk-36O5OT7E.js → chunk-T35Y7YQD.js} +1 -1
  141. package/dist/safe-bash/command-chunks/{chunk-6HMX4CQS.js → chunk-TGSNCQSR.js} +44 -16
  142. package/dist/safe-bash/command-chunks/{chunk-5T7CRJHW.js → chunk-TIOCQVUQ.js} +4 -7
  143. package/dist/safe-bash/command-chunks/{chunk-T5H5UJQ3.js → chunk-TNOA7FCQ.js} +1 -1
  144. package/dist/safe-bash/command-chunks/{chunk-GN2TKLE7.js → chunk-TS65BJHG.js} +5 -5
  145. package/dist/safe-bash/command-chunks/{chunk-7RGB363W.js → chunk-TSCGT46G.js} +3 -2
  146. package/dist/safe-bash/command-chunks/{chunk-KBEURXFF.js → chunk-UN6WS55J.js} +3 -3
  147. package/dist/safe-bash/command-chunks/{chunk-SX2X3IH4.js → chunk-V2V5OCL3.js} +1 -1
  148. package/dist/safe-bash/command-chunks/{chunk-ERYJLO6G.js → chunk-V7A7DRTU.js} +1 -1
  149. package/dist/safe-bash/command-chunks/{chunk-5SHGJ7NO.js → chunk-VA5ZHYYA.js} +73 -33
  150. package/dist/safe-bash/command-chunks/{chunk-XETLEHZP.js → chunk-VPR5LQYX.js} +3 -2
  151. package/dist/safe-bash/command-chunks/{chunk-3DT2YOGW.js → chunk-VSRGNQCP.js} +3 -3
  152. package/dist/safe-bash/command-chunks/{chunk-J5SN3PZ3.js → chunk-VXSLJH7G.js} +53 -3
  153. package/dist/safe-bash/command-chunks/{chunk-PXYOWWMV.js → chunk-W7RAD4EW.js} +4 -3
  154. package/dist/safe-bash/command-chunks/{chunk-YGC6OS5O.js → chunk-WECIOOQB.js} +5 -8
  155. package/dist/safe-bash/command-chunks/{chunk-HHP343KT.js → chunk-WTECBRU4.js} +1 -1
  156. package/dist/safe-bash/command-chunks/{chunk-AO6Z5EQ7.js → chunk-WVE64WM2.js} +6 -5
  157. package/dist/safe-bash/command-chunks/{chunk-Z7RVSD5K.js → chunk-WVHONVZ4.js} +1 -1
  158. package/dist/safe-bash/command-chunks/{chunk-QNIMV57G.js → chunk-XNLFHHOC.js} +1 -1
  159. package/dist/safe-bash/command-chunks/{chunk-XAFSZDY2.js → chunk-XS72HTMA.js} +11 -0
  160. package/dist/safe-bash/command-chunks/{chunk-KYSPGS33.js → chunk-YIQACGEW.js} +2 -0
  161. package/dist/safe-bash/command-chunks/{chunk-NAY27PXB.js → chunk-YOFC45RK.js} +1 -1
  162. package/dist/safe-bash/command-chunks/{chunk-QI7LGHJJ.js → chunk-Z45N42QC.js} +21 -6
  163. package/dist/safe-bash/command-chunks/{chunk-67IQF5GC.js → chunk-ZYHTWNAE.js} +23 -9
  164. package/dist/safe-bash/command-chunks/{chunk-STC3LEWJ.js → chunk-ZYXH3B66.js} +5 -3
  165. package/dist/safe-bash/commands/bytes/compression/index.js +3 -2
  166. package/dist/safe-bash/commands/copy-preserve.d.ts +1 -0
  167. package/dist/safe-bash/commands/csplit/index.browser.js +2 -2
  168. package/dist/safe-bash/commands/docx/index.browser.js +1 -1
  169. package/dist/safe-bash/commands/execution.js +19 -13
  170. package/dist/safe-bash/commands/factor/index.browser.js +2 -2
  171. package/dist/safe-bash/commands/filesystem.d.ts +1 -1
  172. package/dist/safe-bash/commands/filesystem.js +17 -13
  173. package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
  174. package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
  175. package/dist/safe-bash/commands/htmlq/index.d.ts +1 -1
  176. package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
  177. package/dist/safe-bash/commands/line-endings/index.browser.js +2 -2
  178. package/dist/safe-bash/commands/llm/index.browser.js +2 -2
  179. package/dist/safe-bash/commands/llm/providers/index.browser.js +1 -1
  180. package/dist/safe-bash/commands/mdq/index.browser.js +3 -3
  181. package/dist/safe-bash/commands/media/index.browser.js +1 -1
  182. package/dist/safe-bash/commands/network/curl.d.ts +1 -1
  183. package/dist/safe-bash/commands/network/curl.js +1 -3
  184. package/dist/safe-bash/commands/network/index.browser.js +4 -4
  185. package/dist/safe-bash/commands/network/platform-portable.d.ts +1 -5
  186. package/dist/safe-bash/commands/network/platform-portable.js +1 -26
  187. package/dist/safe-bash/commands/network/public.d.ts +2 -2
  188. package/dist/safe-bash/commands/network/public.js +2 -2
  189. package/dist/safe-bash/commands/network/transport.js +2 -2
  190. package/dist/safe-bash/commands/network/wget.d.ts +1 -1
  191. package/dist/safe-bash/commands/network/wget.js +1 -3
  192. package/dist/safe-bash/commands/node/filesystem.js +3 -2
  193. package/dist/safe-bash/commands/node/index.browser.js +8 -8
  194. package/dist/safe-bash/commands/node/types.js +1 -1
  195. package/dist/safe-bash/commands/op/index.browser.js +3 -3
  196. package/dist/safe-bash/commands/pr/index.browser.js +2 -2
  197. package/dist/safe-bash/commands/python/host-capabilities.js +31 -14
  198. package/dist/safe-bash/commands/python/index.browser.js +11 -11
  199. package/dist/safe-bash/commands/python/manifest.d.ts +1 -0
  200. package/dist/safe-bash/commands/python/manifest.js +6 -3
  201. package/dist/safe-bash/commands/python/shell-capability.d.ts +1 -0
  202. package/dist/safe-bash/commands/python/shell-capability.js +3 -2
  203. package/dist/safe-bash/commands/python/worker.browser.js +3 -3
  204. package/dist/safe-bash/commands/regex-execution/public.browser.js +4 -4
  205. package/dist/safe-bash/commands/safejs/runtime.js +16 -7
  206. package/dist/safe-bash/commands/standard.d.ts +1 -0
  207. package/dist/safe-bash/commands/standard.js +2 -1
  208. package/dist/safe-bash/commands/streams.js +6 -24
  209. package/dist/safe-bash/commands/text.js +268 -364
  210. package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
  211. package/dist/safe-bash/commands/xml/index.browser.js +2 -2
  212. package/dist/safe-bash/commands/yq/index.browser.js +2 -2
  213. package/dist/safe-bash/core.browser.js +1 -1
  214. package/dist/safe-bash/core.d.ts +6 -1
  215. package/dist/safe-bash/core.js +1 -1
  216. package/dist/safe-bash/full-core.browser.js +108 -104
  217. package/dist/safe-bash/jobs.browser.js +5 -5
  218. package/dist/safe-bash/opt-in/commands/dd/index.js +2 -0
  219. package/dist/safe-bash/opt-in/optional/commands/shuf/options.d.ts +1 -0
  220. package/dist/safe-bash/opt-in/optional/commands/shuf/options.js +2 -4
  221. package/dist/safe-bash/opt-in/optional/commands/shuf/shuf.js +2 -1
  222. package/dist/safe-bash/optional-host.browser.js +11 -11
  223. package/dist/safe-bash/plugins/composition.d.ts +1 -0
  224. package/dist/safe-bash/plugins/composition.js +3 -8
  225. package/dist/safe-bash/plugins/index.browser.js +27 -27
  226. package/dist/safe-bash/registry-entry.browser.js +28 -28
  227. package/dist/safe-bash/shell/arrays/bindings.js +1 -1
  228. package/dist/safe-bash/shell/arrays/state.js +4 -0
  229. package/dist/safe-bash/shell/brace-expansion.js +1 -1
  230. package/dist/safe-bash/shell/dynamic-variables.d.ts +10 -0
  231. package/dist/safe-bash/shell/dynamic-variables.js +25 -0
  232. package/dist/safe-bash/shell/parser.js +8 -1
  233. package/dist/safe-bash/shell/runtime.d.ts +4 -4
  234. package/dist/safe-bash/shell/runtime.js +291 -741
  235. package/dist/safe-bash/shell/shell.js +2 -31
  236. package/dist/safe-bash/shell-entry.browser.js +25 -25
  237. package/dist/safe-bash/trap.browser.js +4 -4
  238. package/dist/safe-bash/yq-browser/index.js +1 -1
  239. package/dist/safe-bash-base-encoding-engine/base.js +2 -2
  240. package/dist/safe-bash-base-encoding-engine/shared.js +1 -1
  241. package/dist/safe-bash-byte-input-engine/index.d.ts +3 -2
  242. package/dist/safe-bash-byte-input-engine/index.js +4 -1
  243. package/dist/safe-bash-checksum-engine/index.js +13 -6
  244. package/dist/safe-bash-command-apply-patch/apply.d.ts +1 -1
  245. package/dist/safe-bash-command-apply-patch/apply.js +4 -3
  246. package/dist/safe-bash-command-apply-patch/index.js +3 -3
  247. package/dist/safe-bash-command-apply-patch/matcher.js +1 -1
  248. package/dist/safe-bash-command-apply-patch/parser.js +1 -1
  249. package/dist/safe-bash-command-awk/awk-inspection.js +2 -2
  250. package/dist/safe-bash-command-awk/awk-runtime.js +3 -3
  251. package/dist/safe-bash-command-awk/awk-syntax.d.ts +1 -1
  252. package/dist/safe-bash-command-awk/awk-syntax.js +2 -2
  253. package/dist/safe-bash-command-awk/awk-values.js +1 -1
  254. package/dist/safe-bash-command-awk/awk.js +5 -5
  255. package/dist/safe-bash-command-awk/index.js +5 -5
  256. package/dist/safe-bash-command-bc/index.d.ts +2 -0
  257. package/dist/safe-bash-command-bc/index.js +123 -92
  258. package/dist/safe-bash-command-column/column.js +5 -5
  259. package/dist/safe-bash-command-column/display.d.ts +1 -1
  260. package/dist/safe-bash-command-column/display.js +1 -1
  261. package/dist/safe-bash-command-column/index.js +5 -5
  262. package/dist/safe-bash-command-column/internal.d.ts +0 -2
  263. package/dist/safe-bash-command-column/internal.js +1 -1
  264. package/dist/safe-bash-command-column/layout.js +4 -4
  265. package/dist/safe-bash-command-column/table.js +2 -2
  266. package/dist/safe-bash-command-comm/comm.js +1 -1
  267. package/dist/safe-bash-command-comm/index.js +1 -1
  268. package/dist/safe-bash-command-csvcut/index.d.ts +1 -0
  269. package/dist/safe-bash-command-csvcut/index.js +1 -0
  270. package/dist/safe-bash-command-csvgrep/index.d.ts +1 -0
  271. package/dist/safe-bash-command-csvgrep/index.js +2 -2
  272. package/dist/safe-bash-command-csvkit/index.js +9 -9
  273. package/dist/safe-bash-command-csvkit/sync-support.js +1 -1
  274. package/dist/safe-bash-command-curl/curl.js +1 -1
  275. package/dist/safe-bash-command-curl/index.js +1 -1
  276. package/dist/safe-bash-command-dd/index.js +2 -0
  277. package/dist/safe-bash-command-diff/diff.js +1 -1
  278. package/dist/safe-bash-command-diff/index.js +1 -1
  279. package/dist/safe-bash-command-exiftool/index.d.ts +1 -0
  280. package/dist/safe-bash-command-fd/index.js +9 -9
  281. package/dist/safe-bash-command-ffmpeg/index.js +31 -8
  282. package/dist/safe-bash-command-file/index.js +1 -1
  283. package/dist/safe-bash-command-file/shared.js +1 -1
  284. package/dist/safe-bash-command-find/find.js +1 -1
  285. package/dist/safe-bash-command-find/index.js +1 -1
  286. package/dist/safe-bash-command-gzip/index.js +3 -2
  287. package/dist/safe-bash-command-hexdump/command.js +4 -4
  288. package/dist/safe-bash-command-hexdump/custom.d.ts +24 -0
  289. package/dist/safe-bash-command-hexdump/index.js +4 -4
  290. package/dist/safe-bash-command-hexdump/internal.d.ts +2 -0
  291. package/dist/safe-bash-command-hexdump/internal.js +1 -1
  292. package/dist/safe-bash-command-hexdump/io.js +2 -2
  293. package/dist/safe-bash-command-hexdump/options.d.ts +3 -0
  294. package/dist/safe-bash-command-hexdump/options.js +2 -2
  295. package/dist/safe-bash-command-hostname/index.js +1 -1
  296. package/dist/safe-bash-command-html-to-markdown/budget.js +1 -1
  297. package/dist/safe-bash-command-html-to-markdown/entities.js +3 -3
  298. package/dist/safe-bash-command-html-to-markdown/index.js +6 -6
  299. package/dist/safe-bash-command-html-to-markdown/input.js +5 -5
  300. package/dist/safe-bash-command-html-to-markdown/parser.d.ts +1 -0
  301. package/dist/safe-bash-command-html-to-markdown/parser.js +4 -4
  302. package/dist/safe-bash-command-html-to-markdown/render.js +5 -5
  303. package/dist/safe-bash-command-html-to-markdown/text.js +2 -2
  304. package/dist/safe-bash-command-htmlq/index.d.ts +1 -0
  305. package/dist/safe-bash-command-htmlq/index.js +27 -9
  306. package/dist/safe-bash-command-iconv/codec.js +1 -1
  307. package/dist/safe-bash-command-iconv/command.js +2 -2
  308. package/dist/safe-bash-command-iconv/index.js +2 -2
  309. package/dist/safe-bash-command-imagemagick/index.js +24 -6
  310. package/dist/safe-bash-command-join/index.js +1 -1
  311. package/dist/safe-bash-command-join/join.js +1 -1
  312. package/dist/safe-bash-command-jq/index.js +1 -1
  313. package/dist/safe-bash-command-jq/jq.js +1 -1
  314. package/dist/safe-bash-command-less/index.js +43 -28
  315. package/dist/safe-bash-command-mmdc/index.d.ts +1 -0
  316. package/dist/safe-bash-command-numfmt/index.js +0 -11
  317. package/dist/safe-bash-command-od/index.js +101 -68
  318. package/dist/safe-bash-command-pandoc/command.js +1 -1
  319. package/dist/safe-bash-command-pandoc/index.js +1 -1
  320. package/dist/safe-bash-command-paste/index.js +1 -1
  321. package/dist/safe-bash-command-paste/paste.js +1 -1
  322. package/dist/safe-bash-command-pathchk/index.js +3 -13
  323. package/dist/safe-bash-command-pdfimages/index.js +27 -11
  324. package/dist/safe-bash-command-pdfinfo/index.js +19 -10
  325. package/dist/safe-bash-command-pdftk/index.js +3 -3
  326. package/dist/safe-bash-command-pdftoppm/index.js +26 -10
  327. package/dist/safe-bash-command-pdftotext/index.js +27 -13
  328. package/dist/safe-bash-command-qpdf/index.js +5 -5
  329. package/dist/safe-bash-command-sed/index.js +1 -1
  330. package/dist/safe-bash-command-sed/sed.js +1 -1
  331. package/dist/safe-bash-command-shuf/options.d.ts +1 -0
  332. package/dist/safe-bash-command-shuf/options.js +2 -4
  333. package/dist/safe-bash-command-shuf/shuf.js +2 -1
  334. package/dist/safe-bash-command-soffice/index.js +20 -16
  335. package/dist/safe-bash-command-split/index.js +3 -3
  336. package/dist/safe-bash-command-split/io.js +1 -1
  337. package/dist/safe-bash-command-split/outputs.js +2 -2
  338. package/dist/safe-bash-command-split/split.js +3 -3
  339. package/dist/safe-bash-command-sqlite3/btree.d.ts +1 -0
  340. package/dist/safe-bash-command-sqlite3/engine.d.ts +6 -0
  341. package/dist/safe-bash-command-sqlite3/index.js +284 -85
  342. package/dist/safe-bash-command-ssconvert/commands.js +9 -9
  343. package/dist/safe-bash-command-ssconvert/core.js +8 -8
  344. package/dist/safe-bash-command-ssconvert/formats/csv.js +9 -9
  345. package/dist/safe-bash-command-ssconvert/formats/ods.js +8 -8
  346. package/dist/safe-bash-command-ssconvert/formats/spreadsheetml.js +2 -2
  347. package/dist/safe-bash-command-ssconvert/formats/xls.js +9 -9
  348. package/dist/safe-bash-command-ssconvert/formats/xlsx.js +8 -8
  349. package/dist/safe-bash-command-ssconvert/index.js +20 -20
  350. package/dist/safe-bash-command-tar/extract.js +1 -1
  351. package/dist/safe-bash-command-tar/index.js +5 -4
  352. package/dist/safe-bash-command-tar/modes.js +2 -2
  353. package/dist/safe-bash-command-tree/arguments.js +3 -3
  354. package/dist/safe-bash-command-tree/charset.js +1 -1
  355. package/dist/safe-bash-command-tree/index.js +4 -4
  356. package/dist/safe-bash-command-tree/io.js +1 -1
  357. package/dist/safe-bash-command-tree/pattern.js +2 -2
  358. package/dist/safe-bash-command-tree/tree.js +4 -4
  359. package/dist/safe-bash-command-unrtf/index.js +14 -7
  360. package/dist/safe-bash-command-unzip/index.js +1 -1
  361. package/dist/safe-bash-command-unzip/unzip.js +1 -1
  362. package/dist/safe-bash-command-wget/index.js +1 -1
  363. package/dist/safe-bash-command-wget/wget.js +1 -1
  364. package/dist/safe-bash-command-xan/argv.d.ts +1 -1
  365. package/dist/safe-bash-command-xan/argv.js +1 -1
  366. package/dist/safe-bash-command-xan/commands.js +5 -3
  367. package/dist/safe-bash-command-xan/csv.d.ts +1 -1
  368. package/dist/safe-bash-command-xan/csv.js +1 -1
  369. package/dist/safe-bash-command-xan/index.js +7 -7
  370. package/dist/safe-bash-command-xan/io.js +3 -3
  371. package/dist/safe-bash-command-xmllint/index.js +1 -1
  372. package/dist/safe-bash-command-xxd/index.js +105 -91
  373. package/dist/safe-bash-command-xz/command.d.ts +2 -0
  374. package/dist/safe-bash-command-xz/index.d.ts +1 -1
  375. package/dist/safe-bash-command-xz/index.js +8 -0
  376. package/dist/safe-bash-command-yq/query.js +1 -1
  377. package/dist/safe-bash-command-zip/index.js +1 -1
  378. package/dist/safe-bash-command-zip/zip.js +1 -1
  379. package/dist/safe-bash-contracts/escaping.js +3 -3
  380. package/dist/safe-bash-contracts/filesystem-output.js +2 -2
  381. package/dist/safe-bash-contracts/index.d.ts +1 -0
  382. package/dist/safe-bash-contracts/index.js +7 -3
  383. package/dist/safe-bash-contracts/io.d.ts +4 -1
  384. package/dist/safe-bash-contracts/io.js +3 -1
  385. package/dist/safe-bash-contracts/managed-abort.d.ts +10 -0
  386. package/dist/safe-bash-contracts/output.js +2 -2
  387. package/dist/safe-bash-diff-engine/index.js +1 -1
  388. package/dist/safe-bash-diff-engine/shared.d.ts +3 -2
  389. package/dist/safe-bash-diff-engine/shared.js +1 -1
  390. package/dist/safe-bash-io-engine/commands/archive/internal.js +5 -23
  391. package/dist/safe-bash-io-engine/commands/search/requirements.js +2 -2
  392. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +33 -44
  393. package/dist/safe-bash-io-engine/internal.js +1 -1
  394. package/dist/safe-bash-io-engine/shell/pattern.js +1 -1
  395. package/dist/safe-bash-io-engine/shell/string-operations.js +1 -1
  396. package/dist/safe-bash-mcp/index.browser.d.ts +155 -35
  397. package/dist/safe-bash-mcp/index.browser.js +416 -0
  398. package/dist/safe-bash-mcp/index.d.ts +54 -2
  399. package/dist/safe-bash-mcp/index.js +283 -89
  400. package/dist/safe-bash-network-engine/aggregate.js +2 -2
  401. package/dist/safe-bash-network-engine/args.js +4 -4
  402. package/dist/safe-bash-network-engine/authorizer.js +1 -1
  403. package/dist/safe-bash-network-engine/body.js +6 -6
  404. package/dist/safe-bash-network-engine/decode.d.ts +1 -1
  405. package/dist/safe-bash-network-engine/decode.js +3 -4
  406. package/dist/safe-bash-network-engine/fetch-transport.js +3 -3
  407. package/dist/safe-bash-network-engine/form-content-type.js +2 -2
  408. package/dist/safe-bash-network-engine/form-headers.js +2 -2
  409. package/dist/safe-bash-network-engine/glob.js +1 -1
  410. package/dist/safe-bash-network-engine/index.js +4 -4
  411. package/dist/safe-bash-network-engine/input.js +6 -6
  412. package/dist/safe-bash-network-engine/output.js +2 -2
  413. package/dist/safe-bash-network-engine/platform-portable.js +3 -3
  414. package/dist/safe-bash-network-engine/shared.js +2 -2
  415. package/dist/safe-bash-network-engine/types.d.ts +7 -2
  416. package/dist/safe-bash-network-engine/types.js +1 -1
  417. package/dist/safe-bash-network-engine/url.js +2 -2
  418. package/dist/safe-bash-query-engine/capture.js +3 -3
  419. package/dist/safe-bash-query-engine/delpaths.js +3 -3
  420. package/dist/safe-bash-query-engine/formats.js +2 -2
  421. package/dist/safe-bash-query-engine/index.js +11 -11
  422. package/dist/safe-bash-query-engine/indices.js +3 -3
  423. package/dist/safe-bash-query-engine/input.js +1 -1
  424. package/dist/safe-bash-query-engine/interpreter.js +9 -9
  425. package/dist/safe-bash-query-engine/parser.js +1 -1
  426. package/dist/safe-bash-query-engine/query-core.js +11 -11
  427. package/dist/safe-bash-query-engine/regex.js +4 -4
  428. package/dist/safe-bash-query-engine/splits.js +5 -5
  429. package/dist/safe-bash-query-engine/values.js +2 -2
  430. package/dist/safe-bash-regex-engine/ere/matcher.js +102 -30
  431. package/dist/safe-bash-regex-engine/execution/bounded-provider.js +55 -67
  432. package/dist/safe-bash-regex-engine/execution/portable.d.ts +0 -1
  433. package/dist/safe-bash-regex-engine/execution/portable.js +6 -10
  434. package/dist/safe-bash-regex-engine/execution/protocol.d.ts +0 -5
  435. package/dist/safe-bash-regex-engine/execution/protocol.js +1 -3
  436. package/dist/safe-bash-regex-engine/index.js +6 -4
  437. package/dist/safe-bash-regex-engine/text/budget.d.ts +1 -0
  438. package/dist/safe-bash-regex-engine/text/budget.js +1 -1
  439. package/dist/safe-bash-regex-engine/text/regex.d.ts +14 -0
  440. package/dist/safe-bash-regex-engine/text/regex.js +6 -4
  441. package/dist/safe-bash-regex-engine/text/replacement-buffer.js +2 -2
  442. package/dist/safe-bash-regex-engine/text/rust-syntax.js +2 -2
  443. package/dist/safe-bash-search-engine/grep.js +189 -227
  444. package/dist/safe-bash-table-text-engine/table-text/internal.d.ts +7 -5
  445. package/dist/safe-bash-table-text-engine/table-text/internal.js +39 -21
  446. package/dist/safe-playwright-cloudflare/browser-trace-budget.js +6 -2
  447. package/dist/spreadsheet-engine/codecs/odf-hyperlinks.js +8 -2
  448. package/dist/spreadsheet-engine/formulas/functions/captured-bessel-phase.js +2 -2
  449. package/dist/spreadsheet-engine/formulas/label-references.js +54 -33
  450. package/dist/spreadsheet-engine/formulas/parser.js +3 -1
  451. package/dist/spreadsheet-engine/formulas/rewriting.js +13 -3
  452. package/dist/spreadsheet-format-xls/biff-data-tables.js +4 -6
  453. package/dist/spreadsheet-format-xls/biff-formulas.js +3 -0
  454. package/dist/spreadsheet-format-xls/biff-label-ranges.js +9 -6
  455. package/dist/spreadsheet-format-xls/biff.js +1 -1
  456. package/dist/xlsx-ast/xlsx.js +8 -5
  457. package/package.json +9 -8
  458. package/dist/safe-bash/command-chunks/chunk-KAGBORIC.js +0 -88
  459. /package/dist/safe-bash/command-chunks/{chunk-BWNXWI33.js → chunk-2LMZVE3I.js} +0 -0
@@ -14,27 +14,6 @@ import { captureIgnoredTrapSignals } from "./trap.js";
14
14
  import { writeDiagnostic } from "../escaping.js";
15
15
  import { cancelTurn, hasYieldCheckpoint, inheritYieldCheckpoint, monotonicNow, registerInternalYieldCheckpoint, runYieldCheckpoint, scheduleTurn, yieldTurn } from "../contracts/yield.js";
16
16
  import { ACCESS_MODES, FsError, basename, composeMiddleware, createBytePipe, dirname, normalizePath, pipeBytes, resolvePath, validateExitCode, writeBytes, writeText, } from "../contracts/index.js";
17
- import { createBcCommands } from "../commands/bc/index.js";
18
- import { createStreamInspectionCommands } from "../commands/stream-inspection/index.js";
19
- import { createStreamFormatCommands } from "../commands/stream-format/index.js";
20
- import { createSpongeCommands } from "../commands/sponge/index.js";
21
- import { createFdCommands } from "../commands/fd/index.js";
22
- import { createLessCommands } from "../commands/less/index.js";
23
- import { createIdCommands } from "../commands/id/index.js";
24
- import { createWhoamiCommands } from "../commands/whoami/index.js";
25
- import { createUnameCommands } from "../commands/uname/index.js";
26
- import { createHostnameCommands } from "../commands/hostname/index.js";
27
- import { createNprocCommands } from "../commands/nproc/index.js";
28
- import { createShufCommands } from "../shuf.js";
29
- import { createDdCommands } from "../dd.js";
30
- import { createNumfmtCommands } from "../commands/numfmt/index.js";
31
- import { createEnvsubstCommands } from "../commands/envsubst/index.js";
32
- import { createCalCommands } from "../commands/cal/index.js";
33
- import { createPathchkCommands } from "../commands/pathchk/index.js";
34
- import { createGetconfCommands } from "../commands/getconf/index.js";
35
- import { createLocaleCommands } from "../commands/locale/index.js";
36
- import { createDfCommands } from "../commands/df/index.js";
37
- import { createSqlite3Commands } from "../commands/sqlite3/index.js";
38
17
  import { concatShellValues, shellValueByteLength, shellValueBytes, shellValueFromBytes, shellValueText } from "../contracts/value.js";
39
18
  import { createCommandArguments, getCommandArguments } from "../contracts/command.js";
40
19
  import { ValueArena, ValueScope } from "./value-state.js";
@@ -114,6 +93,7 @@ import { variablePresence } from "../commands/variable-presence.js";
114
93
  import { getArrayAssignment, getArraySelector, copyArraySelector, numericIndex, literalIndex, stringIndex, isQuoteMarker, prefixNameQuoteGroups, setArraySelector } from "./arrays/syntax.js";
115
94
  import { ArrayFailure, ArrayOwner, exactSum } from "./arrays/ledger.js";
116
95
  import { controlNames, IndexedBinding, textToken, valueToken } from "./arrays/bindings.js";
96
+ import { readDynamicVariable, writeDynamicVariable } from "./dynamic-variables.js";
117
97
  import { collectMapfile, mapfileOptions, MapfileUsageError } from "./mapfile.js";
118
98
  import { arrayStore, ensureStateMonitor, guestArrays, monitorSymbol, requireArrays, snapshotState, stateMonitor, trackState, trySnapshotStateSync } from "./arrays/state.js";
119
99
  import { pipelineStatusTarget, publishPipelineStatus } from "./pipestatus.js";
@@ -826,8 +806,6 @@ Object.assign(Budget.prototype, {
826
806
  onInternalError: undefined, _yieldCheckpoint: undefined, _values: undefined, _executionScope: undefined, _pathLookup: undefined, _pathLookupSuspensions: 0, _executionCleanup: undefined, globstarEntries: 0, globstarStates: 0, _cleanupChargeFs: undefined, _wallClockTimer: undefined, _aborted: false, _cpuStarted: 0, _hasExternalSignal: false,
827
807
  });
828
808
  const EMPTY_CAPTURE_BYTES = new Uint8Array(0);
829
- const sharedCaptureStdoutScratch = new Uint8Array(65536);
830
- const sharedCaptureStderrScratch = new Uint8Array(65536);
831
809
  export class Capture {
832
810
  constructor(budget, signal) {
833
811
  this._chunks = undefined;
@@ -841,8 +819,8 @@ export class Capture {
841
819
  this.signal = signal;
842
820
  this.file = undefined;
843
821
  }
844
- enableScratchBuffer(isStderr = false) {
845
- this._scratch4k ??= isStderr ? sharedCaptureStderrScratch : sharedCaptureStdoutScratch;
822
+ enableScratchBuffer() {
823
+ this._scratch4k ??= new Uint8Array(65536);
846
824
  }
847
825
  get self() {
848
826
  return this;
@@ -2206,6 +2184,7 @@ function publishVariable(state, name, value) {
2206
2184
  return;
2207
2185
  }
2208
2186
  state.variables[name] = shellValueText(value);
2187
+ writeDynamicVariable(state, name, shellValueText(value));
2209
2188
  }
2210
2189
  function tryRestoreVariableSync(state, name, saved) {
2211
2190
  if (typedSavedVariables.has(saved))
@@ -2991,11 +2970,6 @@ function hasGlobOrEscape(text, extglob = false) {
2991
2970
  return false;
2992
2971
  }
2993
2972
  let nextProcessSubstitutionId = 0;
2994
- let defaultRuntimeMuscleMemoryMap;
2995
- function getRuntimeMuscleMemoryCommand(name) {
2996
- defaultRuntimeMuscleMemoryMap ??= new Map([...createStreamFormatCommands(), ...createStreamInspectionCommands(), ...createBcCommands(), ...createSpongeCommands(), ...createFdCommands(), ...createLessCommands(), ...createIdCommands(), ...createWhoamiCommands(), ...createUnameCommands(), ...createHostnameCommands(), ...createNprocCommands(), ...createShufCommands(), ...createDdCommands(), ...createNumfmtCommands(), ...createEnvsubstCommands(), ...createCalCommands(), ...createPathchkCommands(), ...createGetconfCommands(), ...createLocaleCommands(), ...createDfCommands(), ...createSqlite3Commands()].map(cmd => [cmd.name, cmd]));
2997
- return defaultRuntimeMuscleMemoryMap.get(name);
2998
- }
2999
2973
  const fastSubScratchArgs = [];
3000
2974
  const defaultValueScopeReserve = ValueScope.prototype.reserve;
3001
2975
  const defaultStringCodePointAt = String.prototype.codePointAt;
@@ -3093,16 +3067,8 @@ const SYNC_UNIT_ZERO = Object.freeze({ exitCode: 0, terminated: false });
3093
3067
  const SYNC_UNIT_ONE = Object.freeze({ exitCode: 1, terminated: false });
3094
3068
  const EMPTY_BYTES = new Uint8Array(0);
3095
3069
  const SYNC_PIPE_DONE_RESULT = Object.freeze({ done: true, value: undefined });
3096
- const sharedSyncPipeBuf0 = new Uint8Array(65536);
3097
- const sharedSyncPipeBuf1 = new Uint8Array(65536);
3098
3070
  const sharedSyncPipeDecoder = new TextDecoder("utf-8", { ignoreBOM: true });
3099
3071
  let syncPurePipelineSlotInUse = false;
3100
- let lastPurePipeAst;
3101
- const lastPurePipeSrcRefs = new WeakSet();
3102
- let lastPurePipeSlice1 = "";
3103
- let lastPurePipeRegistry;
3104
- const lastPurePipeOutBuf = new Uint8Array(256);
3105
- let lastPurePipeOutLen = 0;
3106
3072
  function isSimpleAsciiGrepPattern(pat) {
3107
3073
  const start = pat.length >= 2 && pat.charCodeAt(0) === 94 ? 1 : 0;
3108
3074
  if (start >= pat.length)
@@ -4507,6 +4473,10 @@ export class Runtime {
4507
4473
  if (state.readonlyVariables?.has(name))
4508
4474
  throw new PublicDiagnostic(`${name}: readonly variable`);
4509
4475
  delete state.variables[name];
4476
+ if (name === "RANDOM")
4477
+ state.randomDisabled = true;
4478
+ if (name === "SECONDS")
4479
+ state.secondsDisabled = true;
4510
4480
  state.exported.delete(name);
4511
4481
  state.variableAttributes?.delete(name);
4512
4482
  if (name === "OPTIND" && !internal)
@@ -4733,7 +4703,7 @@ export class Runtime {
4733
4703
  case "literal": return true;
4734
4704
  case "name": {
4735
4705
  const effName = resolveSyncNameref(state, tree.name);
4736
- if (effName === "OPTIND" || effName === "PIPESTATUS")
4706
+ if (effName === "OPTIND" || effName === "PIPESTATUS" || effName === "RANDOM" || effName === "SECONDS")
4737
4707
  return false;
4738
4708
  const monitor = stateMonitor(state);
4739
4709
  if (monitor?.hasOverlay(effName) || monitor?.store?.watches.has(effName))
@@ -4832,6 +4802,8 @@ export class Runtime {
4832
4802
  return true;
4833
4803
  }
4834
4804
  tryBuildSyncPatternWord(word, rawState, io, diagnosticLine) {
4805
+ if (word.plain !== undefined)
4806
+ return word.plain.startsWith("~") ? undefined : word.plain;
4835
4807
  if (word.parts.length === 0)
4836
4808
  return undefined;
4837
4809
  let out = "";
@@ -5017,7 +4989,7 @@ export class Runtime {
5017
4989
  const name = typeof key === "string" ? this.referenceName(state, key) : key;
5018
4990
  if (arrayStore(state)?.get(String(name)))
5019
4991
  throw new ArrayFailure("indexed arithmetic is unsupported");
5020
- const value = Reflect.get(target, name)
4992
+ const value = (typeof name === "string" && (name === "RANDOM" || name === "SECONDS") ? this.variable(state, name) : Reflect.get(target, name))
5021
4993
  ?? (name === "LINENO" ? String(line ?? 1)
5022
4994
  : name === "_" ? state.lastArgument ?? ""
5023
4995
  : name === "FUNCNAME" ? state.functionNames?.[0]
@@ -5066,6 +5038,8 @@ export class Runtime {
5066
5038
  }
5067
5039
  variable(state, name) {
5068
5040
  name = this.referenceName(state, name);
5041
+ if (name === "RANDOM" || name === "SECONDS")
5042
+ return readDynamicVariable(stateMonitor(state)?.raw ?? state, name) ?? state.variables[name];
5069
5043
  const binding = arrayStore(state)?.get(name);
5070
5044
  if (binding)
5071
5045
  return binding.get(binding.associative ? binding.keys.get("30")?.index ?? -1 : 0);
@@ -5989,7 +5963,10 @@ export class Runtime {
5989
5963
  try {
5990
5964
  val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === undefined ? undefined : 0, diagnosticLine);
5991
5965
  }
5992
- catch {
5966
+ catch (error) {
5967
+ this.signal.throwIfAborted();
5968
+ if (error instanceof ShellLimitError)
5969
+ throw error;
5993
5970
  return false;
5994
5971
  }
5995
5972
  }
@@ -6079,7 +6056,10 @@ export class Runtime {
6079
6056
  try {
6080
6057
  unsplit = this.fastValueWord(entry.value, rawState, io, false, false, false, false, undefined, diagnosticLine);
6081
6058
  }
6082
- catch {
6059
+ catch (error) {
6060
+ this.signal.throwIfAborted();
6061
+ if (error instanceof ShellLimitError)
6062
+ throw error;
6083
6063
  return false;
6084
6064
  }
6085
6065
  if (typeof unsplit !== "string" || hasGlobOrEscape(unsplit, !!rawState.extglob))
@@ -6105,7 +6085,10 @@ export class Runtime {
6105
6085
  try {
6106
6086
  val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === undefined ? undefined : 0, diagnosticLine);
6107
6087
  }
6108
- catch {
6088
+ catch (error) {
6089
+ this.signal.throwIfAborted();
6090
+ if (error instanceof ShellLimitError)
6091
+ throw error;
6109
6092
  return false;
6110
6093
  }
6111
6094
  }
@@ -6201,7 +6184,10 @@ export class Runtime {
6201
6184
  try {
6202
6185
  val = this.fastValueWord(assignment.value, rawState, io, false, false, false, false, 0, diagnosticLine);
6203
6186
  }
6204
- catch {
6187
+ catch (error) {
6188
+ this.signal.throwIfAborted();
6189
+ if (error instanceof ShellLimitError)
6190
+ throw error;
6205
6191
  return false;
6206
6192
  }
6207
6193
  if (typeof val !== "string")
@@ -6236,7 +6222,10 @@ export class Runtime {
6236
6222
  return false;
6237
6223
  val = this.fastValueWord(assignment.value, rawState, io, false, false, false, false, 0, diagnosticLine);
6238
6224
  }
6239
- catch {
6225
+ catch (error) {
6226
+ this.signal.throwIfAborted();
6227
+ if (error instanceof ShellLimitError)
6228
+ throw error;
6240
6229
  return false;
6241
6230
  }
6242
6231
  if (typeof val !== "string")
@@ -6354,12 +6343,11 @@ export class Runtime {
6354
6343
  const holding = store.owner.hold();
6355
6344
  let staged;
6356
6345
  try {
6357
- const watch = await store.watch(name, operation, this.signal);
6358
- const current = store.get(name);
6346
+ let current = store.get(name);
6359
6347
  if (associative !== undefined && current && current.associative !== associative)
6360
6348
  throw new ArrayFailure("cannot convert array kind");
6361
6349
  const isAssociative = associative ?? current?.associative;
6362
- const initialMaximum = current?.maximum ?? (state.variables[name] === undefined ? -1 : 0);
6350
+ let initialMaximum = current?.maximum ?? (state.variables[name] === undefined ? -1 : 0);
6363
6351
  let selectedIndex;
6364
6352
  let planned = assignment.append && assignment.kind === "compound" ? initialMaximum + 1 : 0;
6365
6353
  if (assignment.kind === "element") {
@@ -6392,6 +6380,37 @@ export class Runtime {
6392
6380
  }
6393
6381
  await operation.ledger.checkpoint(this.signal, entry.value.parts.length + 2);
6394
6382
  }
6383
+ // Word expansion can mutate this binding. Finish it before taking the
6384
+ // publication snapshot, and choose the append cursor from the new maximum.
6385
+ const expandedEntries = [];
6386
+ let elementFields;
6387
+ if (assignment.kind === "element") {
6388
+ elementFields = await this.valueWord(assignment.value, state, io, false, false, false, false, undefined, false, false, 0);
6389
+ }
6390
+ else
6391
+ for (const entry of assignment.entries) {
6392
+ const original = compoundEntryWords.get(entry);
6393
+ let expandedEntry = false;
6394
+ if (entry.index && original && state.braceexpand !== false && original.parts.some(part => part.kind === "text" && !part.quoted && part.value.includes("{"))) {
6395
+ for await (const expanded of expandBraces(original, this.budget, this.signal)) {
6396
+ if (expanded === original)
6397
+ break;
6398
+ expandedEntry = true;
6399
+ const fields = await this.valueWord(expanded, state, io, true, false, false, false, undefined, false, false);
6400
+ operation.reserve({ metadata: 32, slots: 1, work: 1 });
6401
+ expandedEntries.push({ entry: { value: expanded }, fields });
6402
+ }
6403
+ }
6404
+ if (expandedEntry)
6405
+ continue;
6406
+ const fields = await this.valueWord(entry.value, state, io, entry.index === undefined, false, false, false, undefined, false, entry.index === undefined, entry.index === undefined ? undefined : 0);
6407
+ operation.reserve({ metadata: 32, slots: 1, work: 1 });
6408
+ expandedEntries.push({ entry, fields });
6409
+ }
6410
+ current = store.get(name);
6411
+ initialMaximum = current?.maximum ?? (state.variables[name] === undefined ? -1 : 0);
6412
+ this.assertArrayWritable(state, name, origin);
6413
+ const watch = await store.watch(name, operation, this.signal);
6395
6414
  const supersede = await stateMonitor(state).prepareTypedPublication(name, operation, this.signal);
6396
6415
  await this.prepareArrayObservers(state, operation);
6397
6416
  const tickets = operation.reserve({ generation: true, version: true, epoch: true, work: 8 });
@@ -6480,7 +6499,7 @@ export class Runtime {
6480
6499
  }
6481
6500
  else
6482
6501
  index = (await this.arrayIndex(targetBinding, assignment.index, state, io, operation, true));
6483
- const value = await join(await this.valueWord(assignment.value, state, io, false, false, false, false, undefined, false, false, 0));
6502
+ const value = await join(elementFields);
6484
6503
  // Expansion can initialize the unset target as a scalar. Preserve that
6485
6504
  // value when promoting it to an indexed binding.
6486
6505
  if (!current && state.variables[name] !== undefined && (index !== 0 || assignment.append)) {
@@ -6497,25 +6516,8 @@ export class Runtime {
6497
6516
  await insert(index, value, assignment.append);
6498
6517
  }
6499
6518
  else
6500
- for (const entry of assignment.entries) {
6501
- const original = compoundEntryWords.get(entry);
6502
- if (entry.index && original && state.braceexpand !== false && original.parts.some(part => part.kind === "text" && !part.quoted && part.value.includes("{"))) {
6503
- let expandedEntry = false;
6504
- for await (const expanded of expandBraces(original, this.budget, this.signal)) {
6505
- if (expanded === original)
6506
- break;
6507
- expandedEntry = true;
6508
- const values = await this.valueWord(expanded, state, io, true, false, false, false, undefined, false, false);
6509
- for (const value of values) {
6510
- await insert(cursor, value);
6511
- cursor++;
6512
- }
6513
- }
6514
- if (expandedEntry)
6515
- continue;
6516
- }
6519
+ for (const { entry, fields } of expandedEntries) {
6517
6520
  const index = entry.index ? (await this.arrayIndex(targetBinding, entry.index, state, io, operation, true)) : undefined;
6518
- const fields = await this.valueWord(entry.value, state, io, entry.index === undefined, false, false, false, undefined, false, entry.index === undefined, entry.index === undefined ? undefined : 0);
6519
6521
  if (index !== undefined) {
6520
6522
  const value = await join(fields);
6521
6523
  await insert(index, value, entry.append);
@@ -8058,7 +8060,7 @@ export class Runtime {
8058
8060
  const diagnosticLine = io.diagnosticCommandLines?.get(command) ?? (command.line ?? 1) + (io.diagnosticOffset ?? 0);
8059
8061
  if (cSingle !== undefined && !customRegisteredRegistries.has(this.commands) && !hasShellFunction(rawState, cSingle.w0Plain) && !rawState.extensions?.builtins.has(cSingle.w0Plain) && command.words.length <= this.budget.maxExpansionFieldsSmi && (this.budget.commands + 1 <= this.budget.maxCommandsSmi || this.budget.commands + 1 <= this.budget.limits.maxCommands)) {
8060
8062
  w0Plain = cSingle.w0Plain;
8061
- const extD = this.getExternalCommand(w0Plain);
8063
+ const extD = this.commands.get(w0Plain);
8062
8064
  if (!extD || !builtInDirectContextExecutors.has(extD.execute) || customRegisteredCommands.has(extD.execute))
8063
8065
  return undefined;
8064
8066
  externalDef = extD;
@@ -8079,7 +8081,7 @@ export class Runtime {
8079
8081
  return undefined;
8080
8082
  }
8081
8083
  w0Plain = w0P;
8082
- const extD = this.getExternalCommand(w0Plain);
8084
+ const extD = this.commands.get(w0Plain);
8083
8085
  if (!extD || !builtInDirectContextExecutors.has(extD.execute) || customRegisteredCommands.has(extD.execute) || customRegisteredRegistries.has(this.commands) || command.words.length > this.budget.maxExpansionFieldsSmi || (this.budget.commands + 1 > this.budget.maxCommandsSmi && this.budget.commands + 1 > this.budget.limits.maxCommands)) {
8084
8086
  return undefined;
8085
8087
  }
@@ -8131,14 +8133,12 @@ export class Runtime {
8131
8133
  let redirectSink;
8132
8134
  if (command.redirects.length === 1) {
8133
8135
  const r0 = command.redirects[0];
8134
- let targetVal = r0.target.plain;
8135
- if (targetVal === undefined) {
8136
- try {
8137
- targetVal = this.fastValueWord(r0.target, rawState, io, true, false, false, true, undefined, diagnosticLine);
8138
- }
8139
- catch {
8140
- return undefined;
8141
- }
8136
+ let targetVal;
8137
+ try {
8138
+ targetVal = this.fastValueWord(r0.target, rawState, io, true, false, false, true, undefined, diagnosticLine);
8139
+ }
8140
+ catch {
8141
+ return undefined;
8142
8142
  }
8143
8143
  if (typeof targetVal !== "string" || !targetVal || targetVal.includes("\0"))
8144
8144
  return undefined;
@@ -8208,26 +8208,6 @@ export class Runtime {
8208
8208
  const n = pipeline.commands.length;
8209
8209
  if ((this.budget.commands + n > this.budget.maxCommandsSmi && this.budget.commands + n > this.budget.limits.maxCommands))
8210
8210
  return undefined;
8211
- if (pipeline === lastPurePipeAst && !syncPurePipelineSlotInUse && this._isMemoryBackingFs && this.backingFs && this.backingFs.capabilitiesFor === undefined && this.commands === lastPurePipeRegistry && (!rawState.functions || rawState.functions.size === 0) && !rawState.extensions?.builtins.size && io.stdinIsDefault && !this.signal.aborted && !hasYieldCheckpoint(this.signal) && this.budget.canSyncPurePipe && Date.now === defaultDateNow && io.stdout instanceof Capture && io.stdout._scratch4k !== undefined && io.stdout.length === 0 && io.stdout.write === Capture.prototype.write && io.stderr instanceof Capture && io.stderr.length === 0 && io.stderr.write === Capture.prototype.write) {
8212
- const rootEntry = this.backingFs.root?.entries?.get(lastPurePipeSlice1);
8213
- if (rootEntry && rootEntry.type === "file" && rootEntry.revision === 0 && rootEntry.mode !== undefined && ((rootEntry.mode >> 6) & 4) === 4 && rootEntry.sourceRef && lastPurePipeSrcRefs.has(rootEntry.sourceRef)) {
8214
- this.budget.enterPipelineStages(n);
8215
- this.budget.commands += n;
8216
- try {
8217
- this.budget.fileSystemOperation();
8218
- io.stdout.writeRangeSync(lastPurePipeOutBuf, lastPurePipeOutLen);
8219
- }
8220
- finally {
8221
- this.budget.leavePipelineStages(n);
8222
- }
8223
- const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
8224
- monitor.lazyPipeStatus = ZERO_PIPE_STATUSES[n];
8225
- monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
8226
- rawState.status = 0;
8227
- monitor.epoch = restEpoch;
8228
- return SYNC_UNIT_ZERO;
8229
- }
8230
- }
8231
8211
  for (let i = 0; i < n; i++) {
8232
8212
  const cmd = pipeline.commands[i];
8233
8213
  if (cmd.kind !== "simple" || !this.isPureExternalStageCommand(cmd, rawState) || cmd.words.length > this.budget.maxExpansionFieldsSmi)
@@ -8355,11 +8335,10 @@ export class Runtime {
8355
8335
  return undefined;
8356
8336
  }
8357
8337
  const n = pipeline.commands.length;
8358
- let firstStageRootSourceRef;
8359
8338
  for (let i = 0; i < n; i++) {
8360
8339
  const cmd = pipeline.commands[i];
8361
8340
  const name = cmd.words[0].plain;
8362
- const extDef = this.getExternalCommand(name);
8341
+ const extDef = this.commands.get(name);
8363
8342
  if (!extDef || !builtInDirectContextExecutors.has(extDef.execute) || customRegisteredCommands.has(extDef.execute)) {
8364
8343
  return undefined;
8365
8344
  }
@@ -8387,8 +8366,6 @@ export class Runtime {
8387
8366
  const rootEntry = backing.root?.entries?.get(slice1);
8388
8367
  if (!rootEntry || rootEntry.type !== "file" || (rootEntry.data && rootEntry.data.byteLength > 65536))
8389
8368
  return undefined;
8390
- if (rootEntry.revision === 0 && rootEntry.mode !== undefined && ((rootEntry.mode >> 6) & 4) === 4 && rootEntry.data && rootEntry.data.byteLength >= 1024)
8391
- firstStageRootSourceRef = rootEntry.sourceRef;
8392
8369
  }
8393
8370
  }
8394
8371
  else if (name === "find") {
@@ -8436,23 +8413,8 @@ export class Runtime {
8436
8413
  return undefined;
8437
8414
  }
8438
8415
  }
8439
- if (n >= 3 && pipeline === lastPurePipeAst && firstStageRootSourceRef !== undefined && lastPurePipeSrcRefs.has(firstStageRootSourceRef) && Date.now === defaultDateNow) {
8440
- this.budget.enterPipelineStages(n);
8441
- this.budget.commands += n;
8442
- try {
8443
- this.budget.fileSystemOperation();
8444
- io.stdout.writeRangeSync(lastPurePipeOutBuf, lastPurePipeOutLen);
8445
- }
8446
- finally {
8447
- this.budget.leavePipelineStages(n);
8448
- }
8449
- const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
8450
- monitor.lazyPipeStatus = ZERO_PIPE_STATUSES[n] ?? new Array(n).fill(0);
8451
- monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
8452
- rawState.status = 0;
8453
- monitor.epoch = restEpoch;
8454
- return SYNC_UNIT_ZERO;
8455
- }
8416
+ const sharedSyncPipeBuf0 = new Uint8Array(65536);
8417
+ const sharedSyncPipeBuf1 = new Uint8Array(65536);
8456
8418
  syncPurePipelineSlotInUse = true;
8457
8419
  this.budget.enterPipelineStages(n);
8458
8420
  this.budget.commands += n;
@@ -8463,7 +8425,7 @@ export class Runtime {
8463
8425
  for (let index = start; index < n; index++) {
8464
8426
  const cmd = pipeline.commands[index];
8465
8427
  const firstName = cmd.words[0].plain;
8466
- const extDef = this.getExternalCommand(firstName);
8428
+ const extDef = this.commands.get(firstName);
8467
8429
  const stageArgs = cmd._cachedPlainArgs;
8468
8430
  const isFirst = index === 0;
8469
8431
  const isLast = index === n - 1;
@@ -8534,22 +8496,7 @@ export class Runtime {
8534
8496
  syncPurePipelineSlotInUse = false;
8535
8497
  this.budget.leavePipelineStages(n);
8536
8498
  };
8537
- const stdout = io.stdout;
8538
- const stderr = io.stderr;
8539
8499
  const finish = () => {
8540
- if (n >= 3 && !pipeline.negate && statuses === undefined && firstStageRootSourceRef !== undefined && stderr.length === 0 && stdout.length <= 256 && Date.now === defaultDateNow) {
8541
- const scratch = stdout._scratch4k;
8542
- if (scratch) {
8543
- const outLen = stdout.length;
8544
- for (let bi = 0; bi < outLen; bi++)
8545
- lastPurePipeOutBuf[bi] = scratch[bi];
8546
- lastPurePipeOutLen = outLen;
8547
- lastPurePipeAst = pipeline;
8548
- lastPurePipeSlice1 = (pipeline.commands[0]._cachedSlice1) ?? "";
8549
- lastPurePipeRegistry = this.commands;
8550
- lastPurePipeSrcRefs.add(firstStageRootSourceRef);
8551
- }
8552
- }
8553
8500
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
8554
8501
  const finalStatuses = statuses ?? ZERO_PIPE_STATUSES[n] ?? new Array(n).fill(0);
8555
8502
  monitor.lazyPipeStatus = finalStatuses;
@@ -8611,7 +8558,7 @@ export class Runtime {
8611
8558
  for (let index = 0; index < n; index++) {
8612
8559
  const cmd = pipeline.commands[index];
8613
8560
  const firstName = cmd.words[0].plain;
8614
- const extDef = this.getExternalCommand(firstName);
8561
+ const extDef = this.commands.get(firstName);
8615
8562
  let stageArgs = cmd._cachedPlainArgs;
8616
8563
  if (!stageArgs) {
8617
8564
  stageArgs = new Array(cmd.words.length - 1);
@@ -9915,7 +9862,7 @@ export class Runtime {
9915
9862
  // Loops and pure substitutions cannot replay after an unsupported result.
9916
9863
  // These operators depend on arithmetic, filesystem or collation state that
9917
9864
  // the speculative synchronous evaluator does not fully support.
9918
- if (requireTotal && ((expr.kind === "unary" && syncConditionalFileUnaryOps.has(expr.operator)) ||
9865
+ if (requireTotal && ((expr.kind === "unary" && (expr.operator === "-v" || syncConditionalFileUnaryOps.has(expr.operator))) ||
9919
9866
  (expr.kind === "binary" && expr.operator !== "==" && expr.operator !== "=" && expr.operator !== "!=" && expr.operator !== "=~")))
9920
9867
  return false;
9921
9868
  const okWord = (w) => !Runtime.wordMayMutate(w) || (rawState !== undefined && this.isPureSyncValueWord(w, rawState));
@@ -10518,7 +10465,7 @@ export class Runtime {
10518
10465
  const rhsOp = scalarMutMatch[4];
10519
10466
  const rhs2 = scalarMutMatch[5] !== undefined ? Number(scalarMutMatch[5]) : 0;
10520
10467
  const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
10521
- if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
10468
+ if (!controlNames.has(varName) && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
10522
10469
  const curVal = (this._syncArithRawWriteOnly && this._syncArithTouched?.has(varName))
10523
10470
  ? (rawState.variables[varName] ?? "0")
10524
10471
  : (monitor.values.get(varName, rawState.variables[varName] ?? "0") ?? rawState.variables[varName] ?? "0");
@@ -10787,7 +10734,7 @@ export class Runtime {
10787
10734
  const clause = command.clauses[cIdx];
10788
10735
  for (let pIdx = 0; pIdx < clause.patterns.length; pIdx++) {
10789
10736
  const pw = clause.patterns[pIdx];
10790
- const pStr = pw.plain ?? this.tryBuildSyncPatternWord(pw, rawState, io, diagnosticLine);
10737
+ const pStr = this.tryBuildSyncPatternWord(pw, rawState, io, diagnosticLine);
10791
10738
  if (pStr === undefined)
10792
10739
  return undefined;
10793
10740
  const matched = tryMatchesPatternSync(pStr, fastSubject, work, false, false);
@@ -12549,7 +12496,7 @@ export class Runtime {
12549
12496
  allArrOk = false;
12550
12497
  break;
12551
12498
  }
12552
- else if (rawState.locals.length === 0 && isShellIdentifier(tExpanded) && !tExpanded.startsWith("-") && !rawState.readonlyVariables?.has(tExpanded) && !arrStore.get(tExpanded) && !rawState.functions.has(tExpanded) && !monitor.hasOverlay(tExpanded) && tExpanded !== "OPTIND" && tExpanded !== "PIPESTATUS" && tExpanded !== "_" && tExpanded !== "IFS" && tExpanded !== "PATH") {
12499
+ else if (rawState.locals.length === 0 && isShellIdentifier(tExpanded) && !tExpanded.startsWith("-") && !rawState.readonlyVariables?.has(tExpanded) && !arrStore.get(tExpanded) && !rawState.functions.has(tExpanded) && !monitor.hasOverlay(tExpanded) && !controlNames.has(tExpanded) && tExpanded !== "PIPESTATUS" && tExpanded !== "_") {
12553
12500
  ops.push({ kind: "scalar", targetName: tExpanded });
12554
12501
  continue;
12555
12502
  }
@@ -12629,7 +12576,7 @@ export class Runtime {
12629
12576
  for (let ui = uStart; ui < command.words.length; ui++) {
12630
12577
  const targetName = command.words[ui].plain;
12631
12578
  const existingTargetArr = targetName ? store?.get(targetName) : undefined;
12632
- if (targetName && isShellIdentifier(targetName) && !targetName.startsWith("-") && !rawState.readonlyVariables?.has(targetName) && (!existingTargetArr || (existingTargetArr.references === 1 && !store.watches.has(targetName) && !hasUnpreparedLocal(rawState, targetName))) && !rawState.functions.has(targetName) && !monitor.hasOverlay(targetName) && targetName !== "OPTIND" && targetName !== "PIPESTATUS" && targetName !== "_" && targetName !== "IFS" && targetName !== "PATH") {
12579
+ if (targetName && isShellIdentifier(targetName) && !targetName.startsWith("-") && !rawState.readonlyVariables?.has(targetName) && (!existingTargetArr || (existingTargetArr.references === 1 && !store.watches.has(targetName) && !hasUnpreparedLocal(rawState, targetName))) && !rawState.functions.has(targetName) && !monitor.hasOverlay(targetName) && !controlNames.has(targetName) && targetName !== "PIPESTATUS" && targetName !== "_") {
12633
12580
  targets.push(targetName);
12634
12581
  }
12635
12582
  else {
@@ -14202,7 +14149,7 @@ export class Runtime {
14202
14149
  // Unsubscripted array references expand element zero through the normal
14203
14150
  // evaluator. fastValueWord cannot guarantee that expansion throughout
14204
14151
  // a loop, so reject it before executing any loop effects.
14205
- if (stateMonitor(rawState)?.store?.get(part.name))
14152
+ if (part.name === "RANDOM" || part.name === "SECONDS" || stateMonitor(rawState)?.store?.get(part.name))
14206
14153
  return false;
14207
14154
  // These expansions can require multiple fields or asynchronous quoting
14208
14155
  // as loop state changes. Decide before the loop produces any effects.
@@ -14330,125 +14277,8 @@ export class Runtime {
14330
14277
  return false;
14331
14278
  if (this.tryAdmitLoopInvariantSubstitution(part, rawState))
14332
14279
  continue;
14333
- if (customRegisteredRegistries.has(this.commands))
14334
- return false;
14335
- if (part.script.lists.length !== 1)
14336
- return false;
14337
- const list = part.script.lists[0];
14338
- if (list.terminator || list.pipelines.length !== 1)
14339
- return false;
14340
- const p = list.pipelines[0];
14341
- // Pipeline buffers can overflow after variable or stage expansion.
14342
- // A synchronous loop cannot resume after earlier body effects, so keep
14343
- // bounded pipelines on the normal substitution execution path.
14344
- if (p.negate || p.commands.length !== 1)
14345
- return false;
14346
- let cmd = p.commands[0];
14347
- // Loop substitutions require a real subshell: header admission can
14348
- // decline at runtime, and induction writes also change export attributes.
14349
- if (cmd.kind === "for" || cmd.kind === "arithmetic-for" || cmd.kind === "while")
14350
- return false;
14351
- if (p.commands.length === 1 && (cmd.kind === "if" || cmd.kind === "case") && this.isPureSyncSubIfOrCase(cmd, rawState)) {
14352
- continue;
14353
- }
14354
- if (cmd.kind !== "simple" || cmd.redirects.length > 0 || cmd.words.length === 0)
14355
- return false;
14356
- let w0Plain = cmd.words[0].plain;
14357
- // Range-aware tr and Buffer-free 76-col base64 are handled below.
14358
- if (p.commands.length === 1 && w0Plain !== undefined && rawState.functions.has(w0Plain) && this.firstInternalDiscovery(w0Plain, rawState, false) === "function" && !rawState.extensions?.builtins.has(w0Plain)) {
14359
- const fnBody = rawState.functions.get(w0Plain);
14360
- if (fnBody.kind === "group" &&
14361
- fnBody.redirects.length === 0 &&
14362
- fnBody.body.lists.length === 1 &&
14363
- !fnBody.body.lists[0].terminator &&
14364
- fnBody.body.lists[0].pipelines.length === 1 &&
14365
- !fnBody.body.lists[0].pipelines[0].negate &&
14366
- fnBody.body.lists[0].pipelines[0].commands.length === 1 &&
14367
- fnBody.body.lists[0].pipelines[0].commands[0].kind === "simple" &&
14368
- fnBody.body.lists[0].pipelines[0].commands[0].redirects.length === 0 &&
14369
- cmd.words.slice(1).every(w => this.isPureArgWord(w, rawState) && this.isPureSyncValueWord(w, rawState) && w.parts.length > 0 && w.parts.every(part => part.quoted || (part.kind === "text" && part.value.length > 0 && !part.value.includes(" ") && !part.value.includes("\t") && !part.value.includes("\n") && !part.value.includes("{") && !hasGlobOrEscape(part.value, true))))) {
14370
- const innerCmd = fnBody.body.lists[0].pipelines[0].commands[0];
14371
- const innerW0 = innerCmd.words[0]?.plain;
14372
- if (innerW0 && (innerW0 === "echo" || innerW0 === "printf" || innerW0 === "dirname" || innerW0 === "basename" || innerW0 === "pwd" || innerW0 === "command" || innerW0 === "type" || innerW0 === "seq") && !rawState.functions.has(innerW0) && !rawState.extensions?.builtins.has(innerW0)) {
14373
- cmd = innerCmd;
14374
- w0Plain = innerW0;
14375
- }
14376
- }
14377
- }
14378
- // These evaluators can decline based on runtime input. Loop execution
14379
- // has no continuation for a declined substitution after earlier effects.
14380
- if (w0Plain === "tac" || w0Plain === "nl" || (w0Plain === "base64" && cmd.words.length > 1))
14381
- return false;
14382
- if (w0Plain === "pwd") {
14383
- if (p.commands.length === 1 && (cmd.words.length === 1 || (cmd.words.length === 2 && (cmd.words[1]?.plain === "-L" || cmd.words[1]?.plain === "--logical"))) && !rawState.functions.has("pwd") && !rawState.extensions?.builtins.has("pwd"))
14384
- continue;
14385
- return false;
14386
- }
14387
- if ((w0Plain === "command" && cmd.words[1]?.plain === "-v") || (w0Plain === "type" && cmd.words[1]?.plain === "-t")) {
14388
- // PATH entries can change after admission, making discovery decline.
14389
- return false;
14390
- }
14391
- // File and here-string evaluators can decline on mutable input. Keep
14392
- // these on the normal path, which can handle arbitrary input sizes.
14393
- const def = w0Plain ? (w0Plain === "seq" ? this.getExternalCommand(w0Plain) : this.commands.get(w0Plain)) : undefined;
14394
- if (!w0Plain || (w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq") || !def || rawState.functions.has(w0Plain) || rawState.extensions?.builtins.has(w0Plain))
14395
- return false;
14396
- if (w0Plain === "printf" ? def.execute !== printfCommand.execute : w0Plain === "echo" ? !defaultEchoExecutors.has(def.execute) : w0Plain === "seq" ? (!builtInDirectContextExecutors.has(def.execute) && customRegisteredCommands.has(def.execute)) : !builtInDirectContextExecutors.has(def.execute))
14397
- return false;
14398
- // Admission must satisfy the substitution evaluator too: a loop cannot
14399
- // recover from a declined argument after executing earlier body effects.
14400
- if (!cmd.words.slice(1).every(w => this.isPureArgWord(w, rawState) && this.isPureSyncValueWord(w, rawState)))
14401
- return false;
14402
- // These substitutions consume one value per word. Unquoted expansions
14403
- // can split, glob, or disappear, including after loop admission.
14404
- if ((w0Plain === "echo" || w0Plain === "basename" || w0Plain === "dirname") &&
14405
- !cmd.words.slice(1).every(w => w.parts.length > 0 && w.parts.every(part => part.quoted || (part.kind === "text" && part.value.length > 0 && !part.value.includes(" ") && !part.value.includes("\t") && !part.value.includes("\n") && !part.value.includes("{") && !hasGlobOrEscape(part.value, true)))))
14406
- return false;
14407
- if (w0Plain === "printf") {
14408
- if (!this.isSyncPrintfCallOk(cmd, 1, rawState, this._activePrintfInductionName))
14409
- return false;
14410
- }
14411
- else if (w0Plain === "echo") {
14412
- if (!this.isSyncSubEchoCallOk(cmd, rawState))
14413
- return false;
14414
- }
14415
- else if (w0Plain === "dirname" || w0Plain === "basename") {
14416
- const simArgs = [];
14417
- let seenDoubleDash = false;
14418
- for (let wi = 1; wi < cmd.words.length; wi++) {
14419
- const w = cmd.words[wi];
14420
- // Tilde prefixes depend on mutable HOME/PWD/OLDPWD; use normal expansion.
14421
- if (w.parts[0]?.kind === "text" && !w.parts[0].quoted && w.parts[0].value.startsWith("~"))
14422
- return false;
14423
- const st = w.plain ?? (w.parts.length > 0 && w.parts.every(pt => pt.kind === "text") ? w.parts.map(pt => pt.value).join("") : undefined);
14424
- if (st !== undefined) {
14425
- if (st === "--")
14426
- seenDoubleDash = true;
14427
- simArgs.push(st);
14428
- }
14429
- else {
14430
- // A loop operand can become an option after admission.
14431
- if (!seenDoubleDash)
14432
- return false;
14433
- simArgs.push("x");
14434
- }
14435
- }
14436
- if ((w0Plain === "dirname" ? this.evalSyncDirname(simArgs) : this.evalSyncBasename(simArgs)) === undefined)
14437
- return false;
14438
- }
14439
- else if (w0Plain === "seq") {
14440
- const simArgs = [];
14441
- for (let wi = 1; wi < cmd.words.length; wi++) {
14442
- const w = cmd.words[wi];
14443
- const st = w.plain ?? (w.parts.length > 0 && w.parts.every(pt => pt.kind === "text") ? w.parts.map(pt => pt.value).join("") : undefined);
14444
- if (st === undefined)
14445
- return false;
14446
- simArgs.push(st);
14447
- }
14448
- if (this.evalSyncSeq(simArgs) === undefined)
14449
- return false;
14450
- }
14451
- continue;
14280
+ // Dynamic substitutions execute at the committed expansion boundary.
14281
+ return false;
14452
14282
  }
14453
14283
  return false;
14454
14284
  }
@@ -14521,7 +14351,7 @@ export class Runtime {
14521
14351
  };
14522
14352
  const safeArgWord = (w, numeric = false) => (!checkIntVars || this.isPureSyncValueWord(w, rawState)) &&
14523
14353
  (w.parts.every(p => p.quoted || (p.kind === "text" && p.value.length > 0 && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true))) ||
14524
- (numeric && ((!checkIntVars && w.parts.length === 1 && w.parts[0].kind === "variable") || (checkIntVars && rawState.variables.IFS === undefined && isGuaranteedIntWord(w)))));
14354
+ (numeric && ((!checkIntVars && w.parts.length === 1 && w.parts[0].kind === "variable") || (checkIntVars && (rawState.variables.IFS === undefined || rawState.variables.IFS === " \t\n") && isGuaranteedIntWord(w)))));
14525
14355
  if (args.length === 2) {
14526
14356
  const op = args[0].plain;
14527
14357
  if ((op === "-n" || op === "-z") && safeArgWord(args[1])) {
@@ -15034,7 +14864,7 @@ export class Runtime {
15034
14864
  for (const cl of cmd.clauses) {
15035
14865
  if (cl.terminator !== ";;" && cl.terminator !== "esac")
15036
14866
  return false;
15037
- if (!cl.patterns.every(pw => pw.plain !== undefined && tryMatchesPatternSync(pw.plain, "", work, false, false) !== undefined))
14867
+ if (!cl.patterns.every(pw => pw.plain !== undefined && !pw.plain.startsWith("~") && tryMatchesPatternSync(pw.plain, "", work, false, false) !== undefined))
15038
14868
  return false;
15039
14869
  if (!isSimpleEchoOrPrintf(cl.body))
15040
14870
  return false;
@@ -15137,7 +14967,7 @@ export class Runtime {
15137
14967
  return false;
15138
14968
  if (pw.plain === undefined && !pw.parts.every(p => p.quoted))
15139
14969
  return false;
15140
- const pattern = pw.plain ?? (io ? this.tryBuildSyncPatternWord(pw, rawState, io) : undefined);
14970
+ const pattern = (io ? this.tryBuildSyncPatternWord(pw, rawState, io) : (pw.plain?.startsWith("~") ? undefined : pw.plain));
15141
14971
  return pattern !== undefined && tryMatchesPatternSync(pattern, "", work, false, false) !== undefined;
15142
14972
  })) {
15143
14973
  caseOk = false;
@@ -15760,7 +15590,14 @@ export class Runtime {
15760
15590
  for (let b = 0; b + 1 < bodyAssignments.length; b++) {
15761
15591
  const curr = bodyAssignments[b];
15762
15592
  const next = bodyAssignments[b + 1];
15763
- if (curr.targetWord !== undefined && curr.value !== undefined && this.isSimpleRedirectEchoWord(curr.value) && !curr.append && next.targetWord !== undefined && next.value !== undefined && this.isSimpleRedirectEchoWord(next.value) && next.append && sameRedirectTargetWord(curr.targetWord, next.targetWord)) {
15593
+ // The first echo must finish before a dependent command or $? expansion.
15594
+ if (curr.listOperator === undefined && next.listOperator === undefined &&
15595
+ curr.targetWord !== undefined && curr.value !== undefined &&
15596
+ this.isSimpleRedirectEchoWord(curr.value) && !curr.append &&
15597
+ next.targetWord !== undefined && next.value !== undefined &&
15598
+ this.isSimpleRedirectEchoWord(next.value) && next.append &&
15599
+ sameRedirectTargetWord(curr.targetWord, next.targetWord) &&
15600
+ [next.value, next.targetWord].every(word => word.parts.every(part => part.kind !== "variable" || part.name !== "?"))) {
15764
15601
  curr.coalesceNext = true;
15765
15602
  b++;
15766
15603
  }
@@ -15835,22 +15672,29 @@ export class Runtime {
15835
15672
  return undefined;
15836
15673
  }
15837
15674
  const regNames = forPlan.regNames;
15675
+ for (const refName of regNames) {
15676
+ if (store?.get(refName) || store?.watches.has(refName) || monitor.hasOverlay(refName) || rawState.variableAttributes?.has(refName))
15677
+ return undefined;
15678
+ }
15679
+ const intBudgetSnapshot = this.budget.parsing.snapshot();
15838
15680
  for (let r = 0; r < regNames.length; r++) {
15839
15681
  const refName = regNames[r];
15840
- if (store?.get(refName))
15841
- return undefined;
15842
15682
  if (r > 0) {
15843
15683
  const parsed = fastSafeInt(rawState.variables[refName], this.budget.parsing);
15844
- if (parsed === undefined)
15684
+ if (parsed === undefined) {
15685
+ this.budget.parsing.restore(intBudgetSnapshot);
15845
15686
  return undefined;
15687
+ }
15846
15688
  sharedLoopIntRegs[r] = parsed | 0;
15847
15689
  }
15848
15690
  }
15849
- monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets);
15850
- this.budget.tick();
15851
15691
  const { ok } = runIntForLoop(fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
15852
- if (!ok)
15692
+ if (!ok) {
15693
+ this.budget.parsing.restore(intBudgetSnapshot);
15853
15694
  return undefined;
15695
+ }
15696
+ monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets);
15697
+ this.budget.tick();
15854
15698
  this.budget.iterations += wordCount;
15855
15699
  this.budget.commands += wordCount * forPlan.bodyStepCount;
15856
15700
  for (let r = 0; r < regNames.length; r++) {
@@ -16017,6 +15861,7 @@ export class Runtime {
16017
15861
  touched.clear();
16018
15862
  let lastCmd;
16019
15863
  let lastArg = "";
15864
+ let lastPipelineStatus;
16020
15865
  const mode = 0o666 & ~(rawState.umask ?? 0o022);
16021
15866
  if (command.kind === "arithmetic-for") {
16022
15867
  let plan = command._cachedArithPlan;
@@ -16354,6 +16199,8 @@ export class Runtime {
16354
16199
  canUseIntRegisters = false;
16355
16200
  else {
16356
16201
  usedFastIntPath = true;
16202
+ if (iterations > 0)
16203
+ lastPipelineStatus = 0;
16357
16204
  this.budget.parsing.admit(limitVal < 0 ? 4 : 2);
16358
16205
  this.budget.iterations += iterations + 1;
16359
16206
  this.budget.commands += iterations * bodyAssignments.length + subCount;
@@ -16384,6 +16231,7 @@ export class Runtime {
16384
16231
  loopStatus = rawState.status;
16385
16232
  lastCmd = fb.lastCmd;
16386
16233
  lastArg = fb.lastArg;
16234
+ lastPipelineStatus = fb.pipelineStatus;
16387
16235
  lastInductionVal = fb.lastInductionVal;
16388
16236
  }
16389
16237
  finally {
@@ -16463,12 +16311,14 @@ export class Runtime {
16463
16311
  rawState.lastArgument = lastArg;
16464
16312
  if (io.assignmentDiagnosticContext)
16465
16313
  io.assignmentDiagnosticContext.name = undefined;
16314
+ }
16315
+ if (lastPipelineStatus !== undefined) {
16466
16316
  if (!existing) {
16467
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
16317
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
16468
16318
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
16469
16319
  }
16470
16320
  else {
16471
- this.setSyncPipeStatusCell(existing, String(loopStatus));
16321
+ this.setSyncPipeStatusCell(existing, String(lastPipelineStatus));
16472
16322
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
16473
16323
  }
16474
16324
  }
@@ -16486,6 +16336,8 @@ export class Runtime {
16486
16336
  if (cp.negate || cp.commands.length !== 1)
16487
16337
  return undefined;
16488
16338
  const condCmd = cp.commands[0];
16339
+ if (condCmd.kind !== "simple" && condCmd.kind !== "arithmetic" && condCmd.kind !== "conditional")
16340
+ return undefined;
16489
16341
  let whileArithProg;
16490
16342
  let whileCondExpr;
16491
16343
  let whileReadSpec;
@@ -16714,6 +16566,7 @@ export class Runtime {
16714
16566
  this._syncArithTouched = touched;
16715
16567
  const condLine = io.diagnosticCommandLines?.get(condCmd) ?? (condCmd.line ?? diagnosticLine) + (io.diagnosticOffset ?? 0);
16716
16568
  let loopStatus = 0;
16569
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
16717
16570
  let iterCount = 0;
16718
16571
  try {
16719
16572
  if (whileReadSpec !== undefined && syncReadInputText !== undefined) {
@@ -16779,8 +16632,9 @@ export class Runtime {
16779
16632
  rawState.variables[vn] = "";
16780
16633
  touched.add(vn);
16781
16634
  }
16782
- lastCmd = rCmd;
16783
- lastArg = rLastArg;
16635
+ progress.lastCmd = rCmd;
16636
+ progress.lastArg = rLastArg;
16637
+ progress.pipelineStatus = 1;
16784
16638
  break;
16785
16639
  }
16786
16640
  const nlIdx = syncReadInputText.indexOf(readDelim, cursor);
@@ -16788,19 +16642,23 @@ export class Runtime {
16788
16642
  const partialLine = syncReadInputText.slice(cursor);
16789
16643
  cursor = textLen;
16790
16644
  splitSyncReadLine(partialLine, readIfs);
16791
- lastCmd = rCmd;
16792
- lastArg = rLastArg;
16645
+ progress.lastCmd = rCmd;
16646
+ progress.lastArg = rLastArg;
16647
+ progress.pipelineStatus = 1;
16793
16648
  break;
16794
16649
  }
16795
16650
  const lineStr = syncReadInputText.slice(cursor, nlIdx);
16796
16651
  cursor = nlIdx + 1;
16797
16652
  splitSyncReadLine(lineStr, readIfs);
16653
+ progress.lastCmd = rCmd;
16654
+ progress.lastArg = rLastArg;
16655
+ progress.pipelineStatus = 0;
16798
16656
  rawState.status = 0;
16799
16657
  ++iterCount;
16800
16658
  this.budget.loop();
16801
16659
  if ((iterCount & 127) === 0)
16802
16660
  runYieldCheckpoint(this.signal);
16803
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16661
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16804
16662
  loopStatus = rawState.status;
16805
16663
  if (this._syncLoopAction !== undefined) {
16806
16664
  const act = this._syncLoopAction;
@@ -16831,8 +16689,9 @@ export class Runtime {
16831
16689
  }
16832
16690
  rawState.variables[whileGetoptsSpec.optVar] = res.option;
16833
16691
  touched.add(whileGetoptsSpec.optVar);
16834
- lastCmd = whileGetoptsSpec.getoptsCmd;
16835
- lastArg = whileGetoptsSpec.cmdLastArg;
16692
+ progress.lastCmd = whileGetoptsSpec.getoptsCmd;
16693
+ progress.lastArg = whileGetoptsSpec.cmdLastArg;
16694
+ progress.pipelineStatus = res.status;
16836
16695
  if (res.status !== 0)
16837
16696
  break;
16838
16697
  rawState.status = 0;
@@ -16840,7 +16699,7 @@ export class Runtime {
16840
16699
  this.budget.loop();
16841
16700
  if ((iterCount & 127) === 0)
16842
16701
  runYieldCheckpoint(this.signal);
16843
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16702
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16844
16703
  loopStatus = rawState.status;
16845
16704
  if (this._syncLoopAction !== undefined) {
16846
16705
  const act = this._syncLoopAction;
@@ -16856,18 +16715,18 @@ export class Runtime {
16856
16715
  const condNonZero = whileCondExpr !== undefined
16857
16716
  ? (this.tryEvalConditionalSync(whileCondExpr, rawState, monitor, store, io, condLine) ?? 1) === 0
16858
16717
  : this.evalSyncLoopArithStmt(whileArithProg, rawState, io, touched, condLine);
16859
- if (condCmd.kind === "simple") {
16860
- lastCmd = condCmd;
16861
- lastArg = this.fastValueWord(condCmd.words[condCmd.words.length - 1], rawState, io, false, false, false, true);
16862
- }
16718
+ progress.lastCmd = condCmd;
16719
+ if (condCmd.kind === "simple")
16720
+ progress.lastArg = this.fastValueWord(condCmd.words[condCmd.words.length - 1], rawState, io, false, false, false, true);
16863
16721
  rawState.status = condNonZero ? 0 : 1;
16722
+ progress.pipelineStatus = rawState.status;
16864
16723
  if (condNonZero !== (command.kind === "while"))
16865
16724
  break;
16866
16725
  ++iterCount;
16867
16726
  this.budget.loop();
16868
16727
  if ((iterCount & 127) === 0)
16869
16728
  runYieldCheckpoint(this.signal);
16870
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16729
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16871
16730
  loopStatus = rawState.status;
16872
16731
  if (this._syncLoopAction !== undefined) {
16873
16732
  const act = this._syncLoopAction;
@@ -16898,6 +16757,9 @@ export class Runtime {
16898
16757
  }
16899
16758
  }
16900
16759
  }
16760
+ lastCmd = progress.lastCmd;
16761
+ lastArg = progress.lastArg;
16762
+ lastPipelineStatus = progress.pipelineStatus;
16901
16763
  if (lastCmd) {
16902
16764
  if (rawState.extensions && !rawState.extensions.eventDepth)
16903
16765
  publishCommandSpelling(rawState, commandSpelling(lastCmd));
@@ -16907,9 +16769,11 @@ export class Runtime {
16907
16769
  rawState.lastArgument = lastArg;
16908
16770
  if (io.assignmentDiagnosticContext)
16909
16771
  io.assignmentDiagnosticContext.name = undefined;
16910
- const statusStr = loopStatus === 0 ? "0" : String(loopStatus);
16772
+ }
16773
+ if (lastPipelineStatus !== undefined) {
16774
+ const statusStr = String(lastPipelineStatus);
16911
16775
  if (!existing) {
16912
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
16776
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
16913
16777
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
16914
16778
  }
16915
16779
  else {
@@ -17204,6 +17068,8 @@ export class Runtime {
17204
17068
  canUseIntRegisters = false;
17205
17069
  else {
17206
17070
  usedFastIntFor = true;
17071
+ if (fastLoopWords.length > 0)
17072
+ lastPipelineStatus = 0;
17207
17073
  lastCmd = bodyAssignments[bodyAssignments.length - 1]?.cmd;
17208
17074
  this.budget.iterations += fastLoopWords.length;
17209
17075
  this.budget.commands += fastLoopWords.length * bodyAssignments.length + subCount;
@@ -17234,6 +17100,7 @@ export class Runtime {
17234
17100
  loopStatus = fastLoopWords.length === 0 ? 0 : rawState.status;
17235
17101
  lastCmd = fb.lastCmd;
17236
17102
  lastArg = fb.lastArg;
17103
+ lastPipelineStatus = fb.pipelineStatus;
17237
17104
  }
17238
17105
  finally {
17239
17106
  this._syncReturnDepth--;
@@ -17282,12 +17149,14 @@ export class Runtime {
17282
17149
  rawState.lastArgument = lastArg;
17283
17150
  if (io.assignmentDiagnosticContext)
17284
17151
  io.assignmentDiagnosticContext.name = undefined;
17152
+ }
17153
+ if (lastPipelineStatus !== undefined) {
17285
17154
  if (!existing) {
17286
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
17155
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
17287
17156
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
17288
17157
  }
17289
17158
  else {
17290
- this.setSyncPipeStatusCell(existing, String(loopStatus));
17159
+ this.setSyncPipeStatusCell(existing, String(lastPipelineStatus));
17291
17160
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
17292
17161
  }
17293
17162
  }
@@ -17912,8 +17781,7 @@ export class Runtime {
17912
17781
  }
17913
17782
  runSyncArithForFallback(e0, e1, e2, inductionName, hasDeferredSteps, deferredMask, bodyAssignments, rawState, io, monitor, touched, mode, diagnosticLine) {
17914
17783
  let enteredBody = false;
17915
- let lastCmd;
17916
- let lastArg = rawState.lastArgument ?? "";
17784
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
17917
17785
  let lastInductionVal;
17918
17786
  touched.add(inductionName);
17919
17787
  this.syncShellArithmeticNonZero(e0, rawState, diagnosticLine);
@@ -17927,160 +17795,7 @@ export class Runtime {
17927
17795
  enteredBody = true;
17928
17796
  if (hasDeferredSteps)
17929
17797
  lastInductionVal = rawState.variables[inductionName];
17930
- for (let b = 0; b < bodyAssignments.length; b++) {
17931
- const step = bodyAssignments[b];
17932
- if (step.listOperator !== undefined && ((step.listOperator === "&&" && rawState.status !== 0) || (step.listOperator === "||" && rawState.status === 0)))
17933
- continue;
17934
- if (step.caseClauses === undefined && step.ifBranches === undefined && step.nestedLoop === undefined)
17935
- lastCmd = step.cmd;
17936
- this.budget.tick();
17937
- if (step.loopAction !== undefined) {
17938
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
17939
- rawState.status = 0;
17940
- this._syncLoopAction = step.loopAction;
17941
- break;
17942
- }
17943
- if (step.unsetVars !== undefined) {
17944
- lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
17945
- rawState.status = 0;
17946
- continue;
17947
- }
17948
- if (step.localDecl !== undefined) {
17949
- lastArg = this.execSyncLocalDeclStep(step.localDecl, rawState, io, monitor, touched, step.line);
17950
- rawState.status = 0;
17951
- continue;
17952
- }
17953
- if (step.shiftCount !== undefined) {
17954
- const shRes = this.execSyncShiftStep(step.shiftCount, step.cmd, rawState);
17955
- lastArg = shRes.lastArg;
17956
- rawState.status = shRes.status;
17957
- continue;
17958
- }
17959
- if (step.readHereString !== undefined) {
17960
- lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
17961
- continue;
17962
- }
17963
- if (deferredMask & (1 << b)) {
17964
- lastArg = "";
17965
- rawState.status = 0;
17966
- continue;
17967
- }
17968
- if (step.coalesceNext) {
17969
- const nextStep = bodyAssignments[++b];
17970
- this.budget.tick();
17971
- const encoded = this.encodeSyncRedirectWordsToScratch(step.value, nextStep.value, rawState, io);
17972
- this.writeSyncRedirectStep(step, encoded, false, mode, rawState, io);
17973
- this.budget.fileSystemOperation();
17974
- this.budget.fileSystemOperation();
17975
- this.budget.bytes += encoded.byteLength;
17976
- lastCmd = nextStep.cmd;
17977
- lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io) ?? "";
17978
- }
17979
- else if (step.targetWord !== undefined && step.value !== undefined) {
17980
- if (this.isSimpleRedirectEchoWord(step.value)) {
17981
- const encoded = this.encodeSyncRedirectWordsToScratch(step.value, undefined, rawState, io);
17982
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
17983
- this.budget.fileSystemOperation();
17984
- this.budget.bytes += encoded.byteLength;
17985
- lastArg = this.evalSyncRedirectWord(step.value, rawState, io) ?? "";
17986
- }
17987
- else {
17988
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
17989
- const encoded = fastSharedTextEncoder.encode(this.formatSyncEchoLine(val));
17990
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
17991
- this.budget.fileSystemOperation();
17992
- this.budget.bytes += encoded.byteLength;
17993
- lastArg = val;
17994
- }
17995
- }
17996
- else if (step.targetWord !== undefined && step.printfVArgs !== undefined) {
17997
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
17998
- const encoded = fastSharedTextEncoder.encode(formatted);
17999
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18000
- this.budget.fileSystemOperation();
18001
- this.budget.bytes += encoded.byteLength;
18002
- lastArg = pLastArg;
18003
- }
18004
- else if (step.isStdoutEcho && step.value !== undefined) {
18005
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18006
- this.writeSyncStdoutText(this.formatSyncEchoLine(val), io);
18007
- lastArg = val;
18008
- }
18009
- else if (step.isStdoutEcho && step.printfVArgs !== undefined) {
18010
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18011
- this.writeSyncStdoutText(formatted, io);
18012
- lastArg = pLastArg;
18013
- }
18014
- else if (step.arrayAssign !== undefined) {
18015
- if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, undefined, undefined, true)) {
18016
- throw new Error("Synchronous loop array assignment was not executable");
18017
- }
18018
- lastArg = "";
18019
- }
18020
- else if (step.caseClauses !== undefined) {
18021
- this.flushSyncStdoutBatch(io);
18022
- this.execSyncCaseStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18023
- if (this._syncLoopAction !== undefined)
18024
- break;
18025
- continue;
18026
- }
18027
- else if (step.ifBranches !== undefined) {
18028
- this.flushSyncStdoutBatch(io);
18029
- this.execSyncIfStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18030
- if (this._syncLoopAction !== undefined)
18031
- break;
18032
- continue;
18033
- }
18034
- else if (step.condStmt !== undefined) {
18035
- const cStatus = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
18036
- if (step.cmd.kind === "simple") {
18037
- lastArg = this.fastValueWord(step.cmd.words[step.cmd.words.length - 1], rawState, io, false, false, false, true);
18038
- }
18039
- rawState.status = cStatus;
18040
- continue;
18041
- }
18042
- else if (step.nestedLoop !== undefined) {
18043
- this.flushSyncStdoutBatch(io);
18044
- this.execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18045
- continue;
18046
- }
18047
- else if (step.fnCall !== undefined) {
18048
- this.flushSyncStdoutBatch(io);
18049
- this.execSyncFnStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18050
- continue;
18051
- }
18052
- else if (step.arithStmt !== undefined) {
18053
- const nonZero = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line);
18054
- rawState.status = nonZero ? 0 : 1;
18055
- continue;
18056
- }
18057
- else if (step.printfVArgs !== undefined && step.name !== undefined) {
18058
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18059
- rawState.variables[step.name] = formatted;
18060
- touched.add(step.name);
18061
- lastArg = pLastArg;
18062
- }
18063
- else if (step.isDiscardDevNull && step.discardWords !== undefined) {
18064
- lastArg = this.runSyncDiscardStep(step, rawState, io);
18065
- }
18066
- else if (step.name !== undefined && step.value !== undefined) {
18067
- rawState.substitutionStatus = 0;
18068
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18069
- if (step.append) {
18070
- const curRaw = rawState.variables[step.name];
18071
- const curStr = curRaw === undefined ? "" : (touched.has(step.name) ? curRaw : (monitor.values.get(step.name, curRaw) ?? curRaw));
18072
- rawState.variables[step.name] = (typeof curStr === "string" ? curStr : "") + val;
18073
- }
18074
- else
18075
- rawState.variables[step.name] = val;
18076
- touched.add(step.name);
18077
- lastArg = "";
18078
- }
18079
- else {
18080
- lastArg = step.cmd.words[0].plain;
18081
- }
18082
- rawState.status = step.name !== undefined && step.value !== undefined ? rawState.substitutionStatus : 0;
18083
- }
17798
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress, deferredMask);
18084
17799
  if (this._syncLoopAction !== undefined) {
18085
17800
  const act = this._syncLoopAction;
18086
17801
  this._syncLoopAction = undefined;
@@ -18092,7 +17807,7 @@ export class Runtime {
18092
17807
  this.flushSyncStdoutBatch(io);
18093
17808
  if (!enteredBody)
18094
17809
  rawState.status = 0;
18095
- return { lastCmd, lastArg, lastInductionVal };
17810
+ return { ...progress, lastInductionVal };
18096
17811
  }
18097
17812
  _syncLoopFnCheckDepth = 0;
18098
17813
  canSyncReadOnlyArraySubscripts(tree, rawState) {
@@ -18295,7 +18010,7 @@ export class Runtime {
18295
18010
  rawState.positional = savedPos;
18296
18011
  }
18297
18012
  }
18298
- execSyncFnStep(step, rawState, io, monitor, touched, mode, onUpdate) {
18013
+ execSyncFnStep(step, rawState, io, monitor, touched, mode, progress) {
18299
18014
  const fnCall = step.fnCall;
18300
18015
  const fnArgs = [];
18301
18016
  for (let i = 0; i < fnCall.argWords.length; i++) {
@@ -18336,13 +18051,15 @@ export class Runtime {
18336
18051
  }
18337
18052
  }
18338
18053
  if (fnCall.steps.length > 0) {
18339
- this.execSyncLoopSteps(fnCall.steps, rawState, io, monitor, touched, mode, onUpdate);
18054
+ this.execSyncLoopSteps(fnCall.steps, rawState, io, monitor, touched, mode, progress);
18340
18055
  }
18341
18056
  else {
18342
18057
  rawState.status = 0;
18343
18058
  }
18344
18059
  rawState.lastArgument = fnArgs.at(-1) ?? fnCall.name;
18345
- onUpdate({ lastCmd: step.cmd, lastArg: rawState.lastArgument });
18060
+ progress.lastCmd = step.cmd;
18061
+ progress.lastArg = rawState.lastArgument;
18062
+ progress.pipelineStatus = rawState.status;
18346
18063
  }
18347
18064
  finally {
18348
18065
  for (let i = savedLocals.length - 1; i >= 0; i--) {
@@ -18362,16 +18079,10 @@ export class Runtime {
18362
18079
  this._fastSubPositional = prevFastSubPos;
18363
18080
  }
18364
18081
  }
18365
- execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, onUpdate) {
18082
+ execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, progress) {
18366
18083
  const nl = step.nestedLoop;
18367
18084
  const lc = nl.loopCmd;
18368
- let innerLastCmd;
18369
- let innerLastArg = "";
18370
18085
  let innerStatus = 0;
18371
- const updateInner = (v) => {
18372
- innerLastCmd = v.lastCmd;
18373
- innerLastArg = v.lastArg;
18374
- };
18375
18086
  rawState.loopDepth++;
18376
18087
  try {
18377
18088
  if (lc.kind === "arithmetic-for") {
@@ -18385,7 +18096,7 @@ export class Runtime {
18385
18096
  this.budget.loop();
18386
18097
  if ((++turn & 127) === 0)
18387
18098
  runYieldCheckpoint(this.signal);
18388
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
18099
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18389
18100
  innerStatus = rawState.status;
18390
18101
  if (this._syncLoopAction !== undefined) {
18391
18102
  const act = this._syncLoopAction;
@@ -18406,7 +18117,7 @@ export class Runtime {
18406
18117
  if ((++turn & 127) === 0)
18407
18118
  runYieldCheckpoint(this.signal);
18408
18119
  rawState.variables[lc.name] = words[i];
18409
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
18120
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18410
18121
  innerStatus = rawState.status;
18411
18122
  if (this._syncLoopAction !== undefined) {
18412
18123
  const act = this._syncLoopAction;
@@ -18423,17 +18134,17 @@ export class Runtime {
18423
18134
  const condOk = nl.condExpr !== undefined
18424
18135
  ? (this.tryEvalConditionalSync(nl.condExpr, rawState, monitor, arrayStore(rawState), io, nl.condLine) ?? 1) === 0
18425
18136
  : this.evalSyncLoopArithStmt(nl.condArith, rawState, io, touched, nl.condLine);
18426
- if (nl.condCmd?.kind === "simple") {
18427
- innerLastCmd = nl.condCmd;
18428
- innerLastArg = this.fastValueWord(nl.condCmd.words[nl.condCmd.words.length - 1], rawState, io, false, false, false, true);
18429
- }
18137
+ progress.lastCmd = nl.condCmd;
18138
+ if (nl.condCmd?.kind === "simple")
18139
+ progress.lastArg = this.fastValueWord(nl.condCmd.words[nl.condCmd.words.length - 1], rawState, io, false, false, false, true);
18430
18140
  rawState.status = condOk ? 0 : 1;
18141
+ progress.pipelineStatus = rawState.status;
18431
18142
  if (condOk !== (lc.kind === "while"))
18432
18143
  break;
18433
18144
  this.budget.loop();
18434
18145
  if ((++turn & 127) === 0)
18435
18146
  runYieldCheckpoint(this.signal);
18436
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
18147
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18437
18148
  innerStatus = rawState.status;
18438
18149
  if (this._syncLoopAction !== undefined) {
18439
18150
  const act = this._syncLoopAction;
@@ -18448,17 +18159,15 @@ export class Runtime {
18448
18159
  rawState.loopDepth--;
18449
18160
  }
18450
18161
  rawState.status = innerStatus;
18451
- if (innerLastCmd)
18452
- onUpdate({ lastCmd: innerLastCmd, lastArg: innerLastArg });
18453
18162
  }
18454
- execSyncCaseStep(step, rawState, io, monitor, touched, mode, onUpdate) {
18163
+ execSyncCaseStep(step, rawState, io, monitor, touched, mode, progress) {
18455
18164
  const subj = this.fastValueWord(step.caseSubject, rawState, io, false, false, false, false, 0, step.line);
18456
18165
  const work = { remaining: this.budget.limits.maxExpansionBytes, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
18457
18166
  let chosen;
18458
18167
  for (let ci = 0; ci < step.caseClauses.length; ci++) {
18459
18168
  const cl = step.caseClauses[ci];
18460
18169
  for (let pi = 0; pi < cl.patterns.length; pi++) {
18461
- const pattern = cl.patterns[pi].plain ?? this.tryBuildSyncPatternWord(cl.patterns[pi], rawState, io, step.line);
18170
+ const pattern = this.tryBuildSyncPatternWord(cl.patterns[pi], rawState, io, step.line);
18462
18171
  if (pattern !== undefined && tryMatchesPatternSync(pattern, subj, work, false, false)) {
18463
18172
  chosen = cl.steps;
18464
18173
  break;
@@ -18471,10 +18180,10 @@ export class Runtime {
18471
18180
  rawState.status = 0;
18472
18181
  }
18473
18182
  else {
18474
- this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, onUpdate);
18183
+ this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, progress);
18475
18184
  }
18476
18185
  }
18477
- execSyncIfStep(step, rawState, io, monitor, touched, mode, onUpdate) {
18186
+ execSyncIfStep(step, rawState, io, monitor, touched, mode, progress) {
18478
18187
  let chosen;
18479
18188
  for (let bi = 0; bi < step.ifBranches.length; bi++) {
18480
18189
  const br = step.ifBranches[bi];
@@ -18482,9 +18191,11 @@ export class Runtime {
18482
18191
  const condOk = br.condExpr !== undefined
18483
18192
  ? (this.tryEvalConditionalSync(br.condExpr, rawState, monitor, arrayStore(rawState), io, br.condLine) ?? 1) === 0
18484
18193
  : this.evalSyncLoopArithStmt(br.cond, rawState, io, touched, br.condLine);
18194
+ progress.lastCmd = br.condCmd;
18485
18195
  if (br.condCmd.kind === "simple")
18486
- onUpdate({ lastCmd: br.condCmd, lastArg: this.fastValueWord(br.condCmd.words[br.condCmd.words.length - 1], rawState, io, false, false, false, true) });
18196
+ progress.lastArg = this.fastValueWord(br.condCmd.words[br.condCmd.words.length - 1], rawState, io, false, false, false, true);
18487
18197
  rawState.status = condOk ? 0 : 1;
18198
+ progress.pipelineStatus = rawState.status;
18488
18199
  if (condOk) {
18489
18200
  chosen = br.steps;
18490
18201
  break;
@@ -18496,83 +18207,63 @@ export class Runtime {
18496
18207
  rawState.status = 0;
18497
18208
  }
18498
18209
  else {
18499
- this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, onUpdate);
18210
+ this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, progress);
18500
18211
  }
18501
18212
  }
18502
- execSyncLoopSteps(steps, rawState, io, monitor, touched, mode, onUpdate) {
18503
- let lastCmd;
18504
- let lastArg = rawState.lastArgument ?? "";
18213
+ execSyncLoopSteps(steps, rawState, io, monitor, touched, mode, progress, deferredMask = 0) {
18505
18214
  for (let b = 0; b < steps.length; b++) {
18506
18215
  const step = steps[b];
18507
18216
  if (step.listOperator !== undefined && ((step.listOperator === "&&" && rawState.status !== 0) || (step.listOperator === "||" && rawState.status === 0)))
18508
18217
  continue;
18509
- if (step.caseClauses === undefined && step.ifBranches === undefined && step.nestedLoop === undefined)
18510
- lastCmd = step.cmd;
18511
18218
  this.budget.tick();
18512
- if (step.loopAction !== undefined) {
18513
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
18514
- rawState.status = 0;
18515
- this._syncLoopAction = step.loopAction;
18516
- onUpdate({ lastCmd, lastArg });
18517
- break;
18518
- }
18519
- if (step.unsetVars !== undefined) {
18520
- lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18521
- rawState.status = 0;
18522
- onUpdate({ lastCmd, lastArg });
18523
- continue;
18524
- }
18525
- if (step.localDecl !== undefined) {
18526
- lastArg = this.execSyncLocalDeclStep(step.localDecl, rawState, io, monitor, touched, step.line);
18527
- rawState.status = 0;
18528
- onUpdate({ lastCmd, lastArg });
18219
+ // Compound commands return their body's status, but only executed pipelines
18220
+ // update PIPESTATUS. Share progress so empty branches and loops preserve it.
18221
+ if (step.nestedLoop !== undefined || step.fnCall !== undefined || step.caseClauses !== undefined || step.ifBranches !== undefined) {
18222
+ this.flushSyncStdoutBatch(io);
18223
+ if (step.nestedLoop !== undefined)
18224
+ this.execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, progress);
18225
+ else if (step.fnCall !== undefined)
18226
+ this.execSyncFnStep(step, rawState, io, monitor, touched, mode, progress);
18227
+ else if (step.caseClauses !== undefined)
18228
+ this.execSyncCaseStep(step, rawState, io, monitor, touched, mode, progress);
18229
+ else
18230
+ this.execSyncIfStep(step, rawState, io, monitor, touched, mode, progress);
18231
+ if (this._syncLoopAction !== undefined)
18232
+ break;
18529
18233
  continue;
18530
18234
  }
18531
- if (step.shiftCount !== undefined) {
18532
- const shRes = this.execSyncShiftStep(step.shiftCount, step.cmd, rawState);
18533
- lastArg = shRes.lastArg;
18534
- rawState.status = shRes.status;
18535
- onUpdate({ lastCmd, lastArg });
18536
- continue;
18235
+ progress.lastCmd = step.cmd;
18236
+ let status = 0;
18237
+ if (step.loopAction !== undefined) {
18238
+ progress.lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
18239
+ this._syncLoopAction = step.loopAction;
18537
18240
  }
18538
- if (step.readHereString !== undefined) {
18539
- lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
18540
- onUpdate({ lastCmd, lastArg });
18541
- continue;
18241
+ else if (step.unsetVars !== undefined) {
18242
+ progress.lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18542
18243
  }
18543
- if (step.nestedLoop !== undefined) {
18544
- this.execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; onUpdate(v); });
18545
- continue;
18244
+ else if (step.localDecl !== undefined) {
18245
+ progress.lastArg = this.execSyncLocalDeclStep(step.localDecl, rawState, io, monitor, touched, step.line);
18546
18246
  }
18547
- else if (step.fnCall !== undefined) {
18548
- this.execSyncFnStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; onUpdate(v); });
18549
- continue;
18247
+ else if (step.shiftCount !== undefined) {
18248
+ const result = this.execSyncShiftStep(step.shiftCount, step.cmd, rawState);
18249
+ progress.lastArg = result.lastArg;
18250
+ status = result.status;
18550
18251
  }
18551
- else if (step.caseClauses !== undefined) {
18552
- this.execSyncCaseStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; onUpdate(v); });
18553
- if (this._syncLoopAction !== undefined)
18554
- break;
18555
- continue;
18252
+ else if (step.readHereString !== undefined) {
18253
+ progress.lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
18254
+ status = rawState.status;
18556
18255
  }
18557
- else if (step.ifBranches !== undefined) {
18558
- this.execSyncIfStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; onUpdate(v); });
18559
- if (this._syncLoopAction !== undefined)
18560
- break;
18561
- continue;
18256
+ else if (deferredMask & (1 << b)) {
18257
+ progress.lastArg = "";
18562
18258
  }
18563
18259
  else if (step.condStmt !== undefined) {
18564
- const cStatus = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
18260
+ status = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
18565
18261
  if (step.cmd.kind === "simple") {
18566
- lastArg = this.fastValueWord(step.cmd.words[step.cmd.words.length - 1], rawState, io, false, false, false, true);
18567
- onUpdate({ lastCmd, lastArg });
18262
+ progress.lastArg = this.fastValueWord(step.cmd.words[step.cmd.words.length - 1], rawState, io, false, false, false, true);
18568
18263
  }
18569
- rawState.status = cStatus;
18570
- continue;
18571
18264
  }
18572
18265
  else if (step.arithStmt !== undefined) {
18573
- const nonZero = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line);
18574
- rawState.status = nonZero ? 0 : 1;
18575
- continue;
18266
+ status = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line) ? 0 : 1;
18576
18267
  }
18577
18268
  else if (step.coalesceNext) {
18578
18269
  const nextStep = steps[++b];
@@ -18582,8 +18273,8 @@ export class Runtime {
18582
18273
  this.budget.fileSystemOperation();
18583
18274
  this.budget.fileSystemOperation();
18584
18275
  this.budget.bytes += encoded.byteLength;
18585
- lastCmd = nextStep.cmd;
18586
- lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io);
18276
+ progress.lastCmd = nextStep.cmd;
18277
+ progress.lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io);
18587
18278
  }
18588
18279
  else if (step.targetWord !== undefined && step.value !== undefined) {
18589
18280
  if (this.isSimpleRedirectEchoWord(step.value)) {
@@ -18591,7 +18282,7 @@ export class Runtime {
18591
18282
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18592
18283
  this.budget.fileSystemOperation();
18593
18284
  this.budget.bytes += encoded.byteLength;
18594
- lastArg = this.evalSyncRedirectWord(step.value, rawState, io);
18285
+ progress.lastArg = this.evalSyncRedirectWord(step.value, rawState, io);
18595
18286
  }
18596
18287
  else {
18597
18288
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -18599,31 +18290,31 @@ export class Runtime {
18599
18290
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18600
18291
  this.budget.fileSystemOperation();
18601
18292
  this.budget.bytes += encoded.byteLength;
18602
- lastArg = val;
18293
+ progress.lastArg = val;
18603
18294
  }
18604
18295
  }
18605
18296
  else if (step.targetWord !== undefined && step.printfVArgs !== undefined) {
18606
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18297
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18607
18298
  const encoded = fastSharedTextEncoder.encode(formatted);
18608
18299
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18609
18300
  this.budget.fileSystemOperation();
18610
18301
  this.budget.bytes += encoded.byteLength;
18611
- lastArg = pLastArg;
18302
+ progress.lastArg = lastArg;
18612
18303
  }
18613
18304
  else if (step.arrayAssign !== undefined) {
18614
18305
  if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, undefined, undefined, true)) {
18615
18306
  throw new Error("Synchronous loop array assignment was not executable");
18616
18307
  }
18617
- lastArg = "";
18308
+ progress.lastArg = "";
18618
18309
  }
18619
18310
  else if (step.printfVArgs !== undefined && step.name !== undefined) {
18620
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18311
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18621
18312
  rawState.variables[step.name] = formatted;
18622
18313
  touched.add(step.name);
18623
- lastArg = pLastArg;
18314
+ progress.lastArg = lastArg;
18624
18315
  }
18625
18316
  else if (step.isDiscardDevNull && step.discardWords !== undefined) {
18626
- lastArg = this.runSyncDiscardStep(step, rawState, io);
18317
+ progress.lastArg = this.runSyncDiscardStep(step, rawState, io);
18627
18318
  }
18628
18319
  else if (step.name !== undefined && step.value !== undefined) {
18629
18320
  rawState.substitutionStatus = 0;
@@ -18636,179 +18327,37 @@ export class Runtime {
18636
18327
  else
18637
18328
  rawState.variables[step.name] = val;
18638
18329
  touched.add(step.name);
18639
- lastArg = "";
18330
+ progress.lastArg = "";
18331
+ status = rawState.substitutionStatus;
18640
18332
  }
18641
18333
  else if (step.isStdoutEcho && step.value !== undefined) {
18642
18334
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18643
18335
  this.writeSyncStdoutText(this.formatSyncEchoLine(val), io);
18644
- lastArg = val;
18336
+ progress.lastArg = val;
18645
18337
  }
18646
18338
  else if (step.isStdoutEcho && step.printfVArgs !== undefined) {
18647
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18339
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18648
18340
  this.writeSyncStdoutText(formatted, io);
18649
- lastArg = pLastArg;
18341
+ progress.lastArg = lastArg;
18650
18342
  }
18651
18343
  else {
18652
- lastArg = step.cmd.words[0].plain;
18344
+ progress.lastArg = step.cmd.words[0].plain;
18653
18345
  }
18654
- rawState.status = step.name !== undefined && step.value !== undefined ? rawState.substitutionStatus : 0;
18655
- onUpdate({ lastCmd, lastArg });
18346
+ rawState.status = status;
18347
+ progress.pipelineStatus = status;
18348
+ if (this._syncLoopAction !== undefined)
18349
+ break;
18656
18350
  }
18657
18351
  }
18658
18352
  runSyncForFallback(varName, fastLoopWords, bodyAssignments, rawState, io, monitor, touched, mode) {
18659
- let lastCmd;
18660
- let lastArg = rawState.lastArgument ?? "";
18353
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
18661
18354
  let loopTurn = 0;
18662
18355
  for (let idx = 0; idx < fastLoopWords.length; idx++) {
18663
18356
  this.budget.loop();
18664
18357
  if ((++loopTurn & 127) === 0)
18665
18358
  runYieldCheckpoint(this.signal);
18666
18359
  rawState.variables[varName] = fastLoopWords[idx];
18667
- for (let b = 0; b < bodyAssignments.length; b++) {
18668
- const step = bodyAssignments[b];
18669
- if (step.listOperator !== undefined && ((step.listOperator === "&&" && rawState.status !== 0) || (step.listOperator === "||" && rawState.status === 0)))
18670
- continue;
18671
- if (step.caseClauses === undefined && step.ifBranches === undefined && step.nestedLoop === undefined)
18672
- lastCmd = step.cmd;
18673
- this.budget.tick();
18674
- if (step.loopAction !== undefined) {
18675
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
18676
- rawState.status = 0;
18677
- this._syncLoopAction = step.loopAction;
18678
- break;
18679
- }
18680
- if (step.unsetVars !== undefined) {
18681
- lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18682
- rawState.status = 0;
18683
- continue;
18684
- }
18685
- if (step.localDecl !== undefined) {
18686
- lastArg = this.execSyncLocalDeclStep(step.localDecl, rawState, io, monitor, touched, step.line);
18687
- rawState.status = 0;
18688
- continue;
18689
- }
18690
- if (step.shiftCount !== undefined) {
18691
- const shRes = this.execSyncShiftStep(step.shiftCount, step.cmd, rawState);
18692
- lastArg = shRes.lastArg;
18693
- rawState.status = shRes.status;
18694
- continue;
18695
- }
18696
- if (step.readHereString !== undefined) {
18697
- lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
18698
- continue;
18699
- }
18700
- if (step.coalesceNext) {
18701
- const nextStep = bodyAssignments[++b];
18702
- this.budget.tick();
18703
- const encoded = this.encodeSyncRedirectWordsToScratch(step.value, nextStep.value, rawState, io);
18704
- this.writeSyncRedirectStep(step, encoded, false, mode, rawState, io);
18705
- this.budget.fileSystemOperation();
18706
- this.budget.fileSystemOperation();
18707
- this.budget.bytes += encoded.byteLength;
18708
- lastCmd = nextStep.cmd;
18709
- lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io) ?? "";
18710
- }
18711
- else if (step.targetWord !== undefined && step.value !== undefined) {
18712
- if (this.isSimpleRedirectEchoWord(step.value)) {
18713
- const encoded = this.encodeSyncRedirectWordsToScratch(step.value, undefined, rawState, io);
18714
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18715
- this.budget.fileSystemOperation();
18716
- this.budget.bytes += encoded.byteLength;
18717
- lastArg = this.evalSyncRedirectWord(step.value, rawState, io) ?? "";
18718
- }
18719
- else {
18720
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18721
- const encoded = fastSharedTextEncoder.encode(this.formatSyncEchoLine(val));
18722
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18723
- this.budget.fileSystemOperation();
18724
- this.budget.bytes += encoded.byteLength;
18725
- lastArg = val;
18726
- }
18727
- }
18728
- else if (step.targetWord !== undefined && step.printfVArgs !== undefined) {
18729
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18730
- const encoded = fastSharedTextEncoder.encode(formatted);
18731
- this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18732
- this.budget.fileSystemOperation();
18733
- this.budget.bytes += encoded.byteLength;
18734
- lastArg = pLastArg;
18735
- }
18736
- else if (step.nestedLoop !== undefined) {
18737
- this.execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18738
- continue;
18739
- }
18740
- else if (step.fnCall !== undefined) {
18741
- this.execSyncFnStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18742
- continue;
18743
- }
18744
- else if (step.caseClauses !== undefined) {
18745
- this.execSyncCaseStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18746
- if (this._syncLoopAction !== undefined)
18747
- break;
18748
- continue;
18749
- }
18750
- else if (step.ifBranches !== undefined) {
18751
- this.execSyncIfStep(step, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
18752
- if (this._syncLoopAction !== undefined)
18753
- break;
18754
- continue;
18755
- }
18756
- else if (step.condStmt !== undefined) {
18757
- const cStatus = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
18758
- if (step.cmd.kind === "simple") {
18759
- lastArg = this.fastValueWord(step.cmd.words[step.cmd.words.length - 1], rawState, io, false, false, false, true);
18760
- }
18761
- rawState.status = cStatus;
18762
- continue;
18763
- }
18764
- else if (step.arrayAssign !== undefined) {
18765
- if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, undefined, undefined, true)) {
18766
- throw new Error("Synchronous loop array assignment was not executable");
18767
- }
18768
- lastArg = "";
18769
- }
18770
- else if (step.arithStmt !== undefined) {
18771
- const nonZero = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line);
18772
- rawState.status = nonZero ? 0 : 1;
18773
- continue;
18774
- }
18775
- else if (step.printfVArgs !== undefined && step.name !== undefined) {
18776
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line);
18777
- rawState.variables[step.name] = formatted;
18778
- touched.add(step.name);
18779
- lastArg = pLastArg;
18780
- }
18781
- else if (step.isDiscardDevNull && step.discardWords !== undefined) {
18782
- lastArg = this.runSyncDiscardStep(step, rawState, io);
18783
- }
18784
- else if (step.name !== undefined && step.value !== undefined) {
18785
- rawState.substitutionStatus = 0;
18786
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18787
- if (step.append) {
18788
- const curRaw = rawState.variables[step.name];
18789
- const curStr = curRaw === undefined ? "" : (touched.has(step.name) ? curRaw : (monitor.values.get(step.name, curRaw) ?? curRaw));
18790
- rawState.variables[step.name] = (typeof curStr === "string" ? curStr : "") + val;
18791
- }
18792
- else
18793
- rawState.variables[step.name] = val;
18794
- touched.add(step.name);
18795
- lastArg = "";
18796
- }
18797
- else if (step.isStdoutEcho && step.value !== undefined) {
18798
- const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18799
- this.writeSyncStdoutText(this.formatSyncEchoLine(val), io);
18800
- lastArg = val;
18801
- }
18802
- else if (step.isStdoutEcho && step.printfVArgs !== undefined) {
18803
- const { formatted, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18804
- this.writeSyncStdoutText(formatted, io);
18805
- lastArg = pLastArg;
18806
- }
18807
- else {
18808
- lastArg = step.cmd.words[0].plain;
18809
- }
18810
- rawState.status = step.name !== undefined && step.value !== undefined ? rawState.substitutionStatus : 0;
18811
- }
18360
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
18812
18361
  if (this._syncLoopAction !== undefined) {
18813
18362
  const act = this._syncLoopAction;
18814
18363
  this._syncLoopAction = undefined;
@@ -18817,7 +18366,7 @@ export class Runtime {
18817
18366
  }
18818
18367
  }
18819
18368
  this.flushSyncStdoutBatch(io);
18820
- return { lastCmd, lastArg };
18369
+ return progress;
18821
18370
  }
18822
18371
  async script(script, state, io, startListIndex = 0, startPipelineIndex = 0, skipFirstSync = false) {
18823
18372
  if (state.extensions?.syntax.indexedDeclarations?.includes("readonly"))
@@ -19138,13 +18687,11 @@ export class Runtime {
19138
18687
  const isFastPure = isPureStage || runtime.isPureExternalStageCommand(command, rawStateForChild);
19139
18688
  const forkedExt = isFastPure ? forkExtensions(state.extensions, "pipeline") : undefined;
19140
18689
  const child = isFastPure
19141
- ? Object.assign(new RootShellState(rawStateForChild.cwd, rawStateForChild.variables, rawStateForChild.exported, forkedExt), rawStateForChild, {
18690
+ ? Object.assign(cloneRawState(rawStateForChild, false), {
19142
18691
  extensions: forkedExt, isolated: true, _readOnlyStage: true,
19143
18692
  })
19144
18693
  : (tryCloneStateSync(state) ?? await cloneState(state, this.signal));
19145
18694
  preparedChild = child;
19146
- if (child._readOnlyStage)
19147
- child.variables = { ...child.variables };
19148
18695
  child.variables.BASH_SUBSHELL = String(Number(state.variables.BASH_SUBSHELL ?? 0) + 1);
19149
18696
  if (!child._readOnlyStage) {
19150
18697
  child.extensions = undefined;
@@ -19440,7 +18987,7 @@ export class Runtime {
19440
18987
  }
19441
18988
  }
19442
18989
  }
19443
- const extDef = this.getExternalCommand(firstName);
18990
+ const extDef = this.commands.get(firstName);
19444
18991
  return extDef !== undefined && !customRegisteredCommands.has(extDef.execute) && !customRegisteredRegistries.has(this.commands);
19445
18992
  }
19446
18993
  publishStatus(state, statuses, io, terminal) {
@@ -19758,7 +19305,7 @@ export class Runtime {
19758
19305
  }
19759
19306
  for (let pIdx = 0; pIdx < clause.patterns.length; pIdx++) {
19760
19307
  const pw = clause.patterns[pIdx];
19761
- const pStr = pw.plain ?? (pw.parts.length === 1 && pw.parts[0].kind === "text" && !pw.parts[0].quoted && !pw.parts[0].value.includes("~") ? pw.parts[0].value : undefined);
19308
+ const pStr = this.tryBuildSyncPatternWord(pw, state, originalIO, diagnosticLine);
19762
19309
  if (pStr === undefined) {
19763
19310
  allFast = false;
19764
19311
  break;
@@ -21697,7 +21244,7 @@ export class Runtime {
21697
21244
  }
21698
21245
  }
21699
21246
  const scope = io[invocationScope].child();
21700
- const externalDef = typeof name === "string" ? this.getExternalCommand(name) : undefined;
21247
+ const externalDef = typeof name === "string" ? this.commands.get(name) : undefined;
21701
21248
  const fastInline = !state.externalInvocation && this.middleware.length === 0 && typeof name === "string" && (!externalDef || (!customRegisteredCommands.has(externalDef.execute) && !customRegisteredRegistries.has(this.commands))) && !(!bypassFunctions && state.functions.has(name)) && !state.extensions?.builtins.has(name) && name !== "." && name !== "source" && name !== "eval" && name !== "command" && name !== "builtin" && name !== "type" && name !== "read" && name !== "mapfile" && name !== "readarray";
21702
21249
  if (fastInline && externalDef !== undefined && values.every(value => typeof value === "string") && !implementedBuiltins.has(name) && !(name === "printf" && externalDef.execute === printfCommand.execute && args[0]?.startsWith("-v"))) {
21703
21250
  try {
@@ -22155,7 +21702,7 @@ export class Runtime {
22155
21702
  return { exitCode: builtin };
22156
21703
  }
22157
21704
  }
22158
- const definition = this.getExternalCommand(context.command);
21705
+ const definition = this.commands.get(context.command);
22159
21706
  if (context.command === "printf" && definition?.execute === printfCommand.execute && context.args[0]?.startsWith("-v")) {
22160
21707
  ensureRuntimeContext();
22161
21708
  return { exitCode: await this.printfVariable(context, state, assignments) };
@@ -22249,7 +21796,7 @@ export class Runtime {
22249
21796
  matches.push({ kind: "function", name });
22250
21797
  if (implementedBuiltins.has(name) || state.extensions?.builtins.has(name))
22251
21798
  matches.push({ kind: "builtin", name });
22252
- else if (this.hasExternalCommand(name))
21799
+ else if (this.commands.has(name))
22253
21800
  matches.push({ kind: "command", name });
22254
21801
  else if (name === "bash" || name === "sh")
22255
21802
  matches.push({ kind: "interpreter", name });
@@ -22298,23 +21845,12 @@ export class Runtime {
22298
21845
  return "function";
22299
21846
  if (isBuiltin)
22300
21847
  return "builtin";
22301
- if (this.hasExternalCommand(name))
21848
+ if (this.commands.has(name))
22302
21849
  return "command";
22303
21850
  if (name === "bash" || name === "sh")
22304
21851
  return "interpreter";
22305
21852
  return undefined;
22306
21853
  }
22307
- getExternalCommand(name) {
22308
- const direct = this.commands.get(name);
22309
- if (direct)
22310
- return direct;
22311
- if (this.commands.has("rg") || this.commands.has("grep"))
22312
- return getRuntimeMuscleMemoryCommand(name);
22313
- return undefined;
22314
- }
22315
- hasExternalCommand(name) {
22316
- return this.getExternalCommand(name) !== undefined;
22317
- }
22318
21854
  async discoveryBuiltin(context, state, io, assignments, inheritedDefaultPath = false) {
22319
21855
  const args = [...context.args];
22320
21856
  const command = context.command === "command";
@@ -26119,7 +25655,7 @@ export class Runtime {
26119
25655
  const name = this.referenceName(state, part.name);
26120
25656
  const binding = arrayStore(state)?.get(name);
26121
25657
  const index = binding?.associative ? binding.keys.get("30")?.index ?? -1 : 0;
26122
- retained = binding?.getValue(index) ?? stateMonitor(state)?.values.get(name, value) ?? value;
25658
+ retained = name === "RANDOM" || name === "SECONDS" || name === "LINENO" ? value : binding?.getValue(index) ?? stateMonitor(state)?.values.get(name, value) ?? value;
26123
25659
  }
26124
25660
  else if (/^0+$/u.test(part.name))
26125
25661
  retained = stateMonitor(state)?.positionals.get(zeroPositionKey, value) ?? value;
@@ -26523,6 +26059,8 @@ export class Runtime {
26523
26059
  let out = "";
26524
26060
  for (let i = 0; i < word.parts.length; i++) {
26525
26061
  let resolvedPart = word.parts[i];
26062
+ if (resolvedPart.kind === "variable" && (resolveSyncNameref(rawState, resolvedPart.name) === "RANDOM" || resolveSyncNameref(rawState, resolvedPart.name) === "SECONDS"))
26063
+ return undefined;
26526
26064
  if (resolvedPart.kind === "variable" && !resolvedPart.prefixNames && rawState.variableAttributes?.get(resolvedPart.name)?.includes("n")) {
26527
26065
  if (resolvedPart.indirect)
26528
26066
  return undefined;
@@ -27273,7 +26811,7 @@ export class Runtime {
27273
26811
  if (!patQuoted && hasGlobOrEscape(pat, !!rawState.extglob)) {
27274
26812
  if (rawState.nocasematch || byteLocale(rawVars))
27275
26813
  return undefined;
27276
- if (isPrefixTrim && pat.charCodeAt(0) === 42 && !hasGlobOrEscape(pat.slice(1), !!rawState.extglob))
26814
+ if (isPrefixTrim && pat.charCodeAt(0) === 42 && !(rawState.extglob && pat.charCodeAt(1) === 40) && !hasGlobOrEscape(pat.slice(1), !!rawState.extglob))
27277
26815
  starWildcardLit = pat.slice(1);
27278
26816
  else if (!isPrefixTrim && pat.charCodeAt(pat.length - 1) === 42 && !hasGlobOrEscape(pat.slice(0, -1), !!rawState.extglob))
27279
26817
  starWildcardLit = pat.slice(0, -1);
@@ -27478,6 +27016,11 @@ export class Runtime {
27478
27016
  else if (part.kind === "substitution") {
27479
27017
  if (split && !part.quoted)
27480
27018
  return undefined;
27019
+ // General word probes may be replayed by a caller after another word or
27020
+ // command guard declines. Run substitutions at the committed valuePart
27021
+ // boundary; only pre-admitted loop invariants belong in this path.
27022
+ if (!this._syncLoopInvariantSubMap?.has(part))
27023
+ return undefined;
27481
27024
  const substVal = this.tryFastPureSubstitution(part, state, rawState, io);
27482
27025
  if (substVal === undefined)
27483
27026
  return undefined;
@@ -36171,7 +35714,7 @@ export class Runtime {
36171
35714
  if (p.kind === "text")
36172
35715
  continue;
36173
35716
  if (p.kind === "variable") {
36174
- if (p.name === "BASH_SUBSHELL")
35717
+ if (p.name === "BASH_SUBSHELL" || p.name === "RANDOM" || p.name === "SECONDS")
36175
35718
  return false;
36176
35719
  if (!p.indirect && !p.prefixNames && !p.length && !p.substring && !p.transform && p.operator === undefined && getArraySelector(p) === undefined && (p.name === "?" || p.name === "#" || (p.name.length === 1 && p.name >= "1" && p.name <= "9"))) {
36177
35720
  const activePos = this._fastSubPositional ?? rawState.positional;
@@ -36189,17 +35732,19 @@ export class Runtime {
36189
35732
  continue;
36190
35733
  }
36191
35734
  if (p.kind === "arithmetic") {
36192
- if (p.expression.hasSubscript || p.expression.hasMutation || rawState.nounset)
36193
- return false;
36194
- if (p.expression.error && (p.expression.source.includes("=") || p.expression.source.includes("++") || p.expression.source.includes("--")))
36195
- return false;
36196
- continue;
35735
+ // Even read-only arithmetic can fail (including through variable values).
35736
+ // Its diagnostic and exit status belong to the substitution's child shell.
35737
+ return false;
36197
35738
  }
36198
35739
  return false;
36199
35740
  }
36200
35741
  return true;
36201
35742
  }
36202
35743
  tryFastPureSubstitution(part, state, rawState, io) {
35744
+ // Synchronous evaluators do not expose cumulative source-read accounting.
35745
+ // Use the command context whenever the caller has set an input ceiling.
35746
+ if (this.budget.limits.maxInputBytes !== Infinity)
35747
+ return undefined;
36203
35748
  const cachedInv = this._syncLoopInvariantSubMap?.get(part);
36204
35749
  if (cachedInv !== undefined && !cachedInv.dynamic) {
36205
35750
  const nextTotalBytes = this.budget.bytes + cachedInv.outBytes;
@@ -36243,7 +35788,7 @@ export class Runtime {
36243
35788
  continue;
36244
35789
  if (name === "fmt" && command === pipeline.commands[0] && command.redirects.length === 0 && !io.stdinIsDefault)
36245
35790
  return undefined;
36246
- const definition = this.getExternalCommand(name);
35791
+ const definition = this.commands.get(name);
36247
35792
  if (definition && customRegisteredCommands.has(definition.execute))
36248
35793
  return undefined;
36249
35794
  if (name === "uname" || name === "nproc" || name === "hostname" || name === "id" || name === "whoami") {
@@ -36285,7 +35830,7 @@ export class Runtime {
36285
35830
  return undefined;
36286
35831
  if (!cmd0StdinRedir && !cmd0HereStringRedir && w0Plain0 === "cat" && cmd0.words.length < 2)
36287
35832
  return undefined;
36288
- const def0 = (w0Plain0 === "printf" || w0Plain0 === "echo" || w0Plain0 === "cat" || w0Plain0 === "pwd" || w0Plain0 === "dirname" || w0Plain0 === "basename") ? this.commands.get(w0Plain0) : this.getExternalCommand(w0Plain0);
35833
+ const def0 = this.commands.get(w0Plain0);
36289
35834
  if (!def0 || (w0Plain0 === "printf" ? def0.execute !== printfCommand.execute : w0Plain0 === "echo" ? !defaultEchoExecutors.has(def0.execute) : (w0Plain0 === "cat" || w0Plain0 === "seq" || cmd0YesStage || cmd0SysStage || cmd0StdinRedir || cmd0HereStringRedir || cmd0FileStage) ? (w0Plain0 !== "rev" && w0Plain0 !== "tac" && w0Plain0 !== "nl" && w0Plain0 !== "paste" && w0Plain0 !== "comm" && w0Plain0 !== "join" && w0Plain0 !== "jq" && w0Plain0 !== "strings" && w0Plain0 !== "bc" && w0Plain0 !== "factor" && w0Plain0 !== "tsort" && w0Plain0 !== "envsubst" && w0Plain0 !== "xxd" && w0Plain0 !== "od" && w0Plain0 !== "hexdump" && w0Plain0 !== "hd" && w0Plain0 !== "fmt" && w0Plain0 !== "md5sum" && w0Plain0 !== "sha1sum" && w0Plain0 !== "sha224sum" && w0Plain0 !== "sha256sum" && w0Plain0 !== "sha384sum" && w0Plain0 !== "sha512sum" && w0Plain0 !== "cksum" && w0Plain0 !== "base32" && w0Plain0 !== "base64" && w0Plain0 !== "csvcut" && w0Plain0 !== "csvgrep" && w0Plain0 !== "dos2unix" && w0Plain0 !== "unix2dos" && w0Plain0 !== "iconv" && w0Plain0 !== "gzip" && w0Plain0 !== "gunzip" && w0Plain0 !== "zcat" && w0Plain0 !== "unzstd" && w0Plain0 !== "zstdcat" && w0Plain0 !== "htmlq" && w0Plain0 !== "xmllint" && w0Plain0 !== "xq" && w0Plain0 !== "yq" && w0Plain0 !== "mdq" && w0Plain0 !== "shuf" && w0Plain0 !== "html-to-markdown" && w0Plain0 !== "unrtf" && w0Plain0 !== "pr" && w0Plain0 !== "file" && w0Plain0 !== "diff3" && w0Plain0 !== "cmp" && w0Plain0 !== "which" && w0Plain0 !== "diff" && w0Plain0 !== "xan" && w0Plain0 !== "less" && w0Plain0 !== "more" && w0Plain0 !== "df" && w0Plain0 !== "du" && w0Plain0 !== "tree" && w0Plain0 !== "stat" && w0Plain0 !== "fd" && w0Plain0 !== "rg" && w0Plain0 !== "readlink" && w0Plain0 !== "realpath" && w0Plain0 !== "ls" && w0Plain0 !== "find" && w0Plain0 !== "csvlook" && w0Plain0 !== "csvjson" && w0Plain0 !== "csvsort" && w0Plain0 !== "csvformat" && w0Plain0 !== "csvstat" && w0Plain0 !== "in2csv" && w0Plain0 !== "csvstack" && w0Plain0 !== "csvjoin" && w0Plain0 !== "dd" && w0Plain0 !== "env" && w0Plain0 !== "xargs" && w0Plain0 !== "openssl" && w0Plain0 !== "sqlite3" && w0Plain0 !== "gpg" && w0Plain0 !== "ssh" && w0Plain0 !== "ssh-keygen" && w0Plain0 !== "pdfinfo" && w0Plain0 !== "pdffonts" && w0Plain0 !== "pdftotext" && w0Plain0 !== "pdftohtml" && w0Plain0 !== "exiftool" && w0Plain0 !== "qpdf" && w0Plain0 !== "pdftk" && w0Plain0 !== "sips" && w0Plain0 !== "identify" && w0Plain0 !== "magick" && w0Plain0 !== "convert" && w0Plain0 !== "pdfimages" && w0Plain0 !== "pdfdetach" && w0Plain0 !== "ffprobe" && w0Plain0 !== "ffmpeg" && w0Plain0 !== "gh" && w0Plain0 !== "pdftoppm" && w0Plain0 !== "pdftocairo" && w0Plain0 !== "mmdc" && w0Plain0 !== "pandoc" && w0Plain0 !== "soffice" && w0Plain0 !== "libreoffice" && w0Plain0 !== "ssconvert" && w0Plain0 !== "wkhtmltopdf" && w0Plain0 !== "op" && w0Plain0 !== "date" && w0Plain0 !== "printenv" && w0Plain0 !== "egrep" && w0Plain0 !== "fgrep" && w0Plain0 !== "yes" && w0Plain0 !== "cal" && w0Plain0 !== "ncal" && w0Plain0 !== "expr" && w0Plain0 !== "getopt" && w0Plain0 !== "pathchk" && !builtInDirectContextExecutors.has(def0.execute)) : (customRegisteredCommands.has(def0.execute) || customRegisteredRegistries.has(this.commands))))
36290
35835
  return undefined;
36291
35836
  if (!this.arePureArgWords(cmd0.words, rawState))
@@ -36302,7 +35847,7 @@ export class Runtime {
36302
35847
  const sName = sCmd.words[0].plain;
36303
35848
  if (!sName || hasShellFunction(rawState, sName) || rawState.extensions?.builtins.has(sName))
36304
35849
  return undefined;
36305
- const extDef = this.getExternalCommand(sName);
35850
+ const extDef = this.commands.get(sName);
36306
35851
  if (!extDef || ((sName !== "cat" || startStageIdx === 0) && sName !== "rev" && sName !== "tac" && sName !== "nl" && sName !== "paste" && sName !== "column" && sName !== "fold" && sName !== "expand" && sName !== "unexpand" && sName !== "strings" && sName !== "comm" && sName !== "join" && sName !== "jq" && sName !== "bc" && sName !== "factor" && sName !== "tsort" && sName !== "envsubst" && sName !== "xxd" && sName !== "od" && sName !== "hexdump" && sName !== "hd" && sName !== "fmt" && sName !== "md5sum" && sName !== "sha1sum" && sName !== "sha224sum" && sName !== "sha256sum" && sName !== "sha384sum" && sName !== "sha512sum" && sName !== "cksum" && sName !== "base32" && sName !== "base64" && sName !== "csvcut" && sName !== "csvgrep" && sName !== "dos2unix" && sName !== "unix2dos" && sName !== "iconv" && sName !== "gzip" && sName !== "gunzip" && sName !== "zcat" && sName !== "unzstd" && sName !== "zstdcat" && sName !== "htmlq" && sName !== "xmllint" && sName !== "xq" && sName !== "yq" && sName !== "mdq" && sName !== "shuf" && sName !== "html-to-markdown" && sName !== "unrtf" && sName !== "pr" && sName !== "file" && sName !== "diff3" && sName !== "cmp" && sName !== "which" && sName !== "diff" && sName !== "xan" && sName !== "less" && sName !== "more" && sName !== "df" && sName !== "du" && sName !== "tree" && sName !== "stat" && sName !== "fd" && sName !== "rg" && sName !== "readlink" && sName !== "realpath" && sName !== "ls" && sName !== "find" && sName !== "csvlook" && sName !== "csvjson" && sName !== "csvsort" && sName !== "csvformat" && sName !== "csvstat" && sName !== "in2csv" && sName !== "csvstack" && sName !== "csvjoin" && sName !== "dd" && sName !== "xargs" && sName !== "openssl" && sName !== "sqlite3" && sName !== "gpg" && sName !== "ssh" && sName !== "ssh-keygen" && sName !== "pdfinfo" && sName !== "pdffonts" && sName !== "pdftotext" && sName !== "pdftohtml" && sName !== "exiftool" && sName !== "qpdf" && sName !== "pdftk" && sName !== "sips" && sName !== "identify" && sName !== "magick" && sName !== "convert" && sName !== "pdfimages" && sName !== "pdfdetach" && sName !== "ffprobe" && sName !== "ffmpeg" && sName !== "gh" && sName !== "pdftoppm" && sName !== "pdftocairo" && sName !== "mmdc" && sName !== "pandoc" && sName !== "soffice" && sName !== "libreoffice" && sName !== "ssconvert" && sName !== "wkhtmltopdf" && sName !== "op" && sName !== "date" && sName !== "cal" && sName !== "ncal" && sName !== "getopt" && sName !== "pathchk" && sName !== "printenv" && sName !== "env" && sName !== "egrep" && sName !== "fgrep" && !builtInDirectContextExecutors.has(extDef.execute)) || customRegisteredCommands.has(extDef.execute))
36307
35852
  return undefined;
36308
35853
  if ((sName === "xxd" || sName === "od") && !builtInDirectContextExecutors.has(extDef.execute))
@@ -36633,8 +36178,10 @@ export class Runtime {
36633
36178
  if (stage0Formatted === undefined || stage0Formatted.length > 8192)
36634
36179
  return undefined;
36635
36180
  const stage0ByteLen = shellValueByteLength(stage0Formatted);
36636
- if (stage0ByteLen > sharedSyncPipeBuf0.byteLength)
36181
+ if (stage0ByteLen > 65536)
36637
36182
  return undefined;
36183
+ const sharedSyncPipeBuf0 = new Uint8Array(65536);
36184
+ const sharedSyncPipeBuf1 = new Uint8Array(65536);
36638
36185
  const nextBytes0 = this.budget.bytes + stage0ByteLen;
36639
36186
  if (nextBytes0 > this.budget.maxOutputBytesSmi && stage0ByteLen > this.budget.limits.maxOutputBytes - this.budget.bytes)
36640
36187
  this.budget.fail("maxOutputBytes");
@@ -37839,7 +37386,7 @@ export class Runtime {
37839
37386
  for (const cl of cmd.clauses) {
37840
37387
  let matched = false;
37841
37388
  for (const pw of cl.patterns) {
37842
- if (pw.plain !== undefined && tryMatchesPatternSync(pw.plain, subj, work, false, false) === true) {
37389
+ if (pw.plain !== undefined && !pw.plain.startsWith("~") && tryMatchesPatternSync(pw.plain, subj, work, false, false) === true) {
37843
37390
  matched = true;
37844
37391
  break;
37845
37392
  }
@@ -37879,14 +37426,14 @@ export class Runtime {
37879
37426
  if (w0Plain === "fmt" && !hasSingleStdinRedir && !hasSingleHereStringRedir && !io.stdinIsDefault)
37880
37427
  return undefined;
37881
37428
  if (w0Plain === "xxd" || w0Plain === "od" || w0Plain === "mktemp" || w0Plain === "chmod" || w0Plain === "uname" || w0Plain === "nproc" || w0Plain === "hostname" || w0Plain === "id" || w0Plain === "whoami") {
37882
- const definition = this.getExternalCommand(w0Plain);
37429
+ const definition = this.commands.get(w0Plain);
37883
37430
  if (!definition || !builtInDirectContextExecutors.has(definition.execute))
37884
37431
  return undefined;
37885
37432
  }
37886
37433
  if (cmd.words.length === 2 && cmd.redirects.length === 0 && (cmd.words[1]?.plain === "--help" || cmd.words[1]?.plain === "--version")) {
37887
37434
  const gnuInfo = gnuInformationSync(w0Plain, [cmd.words[1].plain], false, (rawState.exported.has("POSIXLY_CORRECT") || rawState.allexport) && rawState.variables.POSIXLY_CORRECT !== undefined);
37888
37435
  if (gnuInfo !== undefined) {
37889
- const extDef = this.getExternalCommand(w0Plain);
37436
+ const extDef = this.commands.get(w0Plain);
37890
37437
  if (!extDef || !builtInDirectContextExecutors.has(extDef.execute))
37891
37438
  return undefined;
37892
37439
  return gnuInfo.replace(/\n+$/, "");
@@ -37907,7 +37454,7 @@ export class Runtime {
37907
37454
  w0Plain === "uniq" ||
37908
37455
  w0Plain === "tr" ||
37909
37456
  (w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "numfmt" || w0Plain === "column" || w0Plain === "fold" || w0Plain === "expand" || w0Plain === "unexpand" || w0Plain === "strings" || w0Plain === "comm" || w0Plain === "join") || w0Plain === "comm" || w0Plain === "join" || w0Plain === "paste" || w0Plain === "numfmt" || w0Plain === "nl" || w0Plain === "expr" || w0Plain === "bc" || w0Plain === "xxd" || w0Plain === "od" || w0Plain === "factor" || w0Plain === "tsort" || w0Plain === "envsubst" || w0Plain === "hexdump" || w0Plain === "hd" || w0Plain === "fmt" || w0Plain === "uname" || w0Plain === "id" || w0Plain === "whoami" || w0Plain === "hostname" || w0Plain === "nproc" || w0Plain === "getconf" || w0Plain === "locale" || w0Plain === "csvcut" || w0Plain === "csvgrep" || w0Plain === "getopt" || w0Plain === "dos2unix" || w0Plain === "unix2dos" || w0Plain === "iconv" || w0Plain === "gzip" || w0Plain === "gunzip" || w0Plain === "zcat" || w0Plain === "unzstd" || w0Plain === "zstdcat" || w0Plain === "zstd" || w0Plain === "bzip2" || w0Plain === "bunzip2" || w0Plain === "bzcat" || w0Plain === "xz" || w0Plain === "unxz" || w0Plain === "xzcat" || w0Plain === "lzma" || w0Plain === "unlzma" || w0Plain === "lzcat" || w0Plain === "htmlq" || w0Plain === "xmllint" || w0Plain === "xq" || w0Plain === "yq" || w0Plain === "mdq" || w0Plain === "shuf" || w0Plain === "html-to-markdown" || w0Plain === "unrtf" || w0Plain === "pr" || w0Plain === "pathchk" || w0Plain === "file" || w0Plain === "diff3" || w0Plain === "cmp" || w0Plain === "which" || w0Plain === "diff" || w0Plain === "xan" || w0Plain === "less" || w0Plain === "more" || w0Plain === "df" || w0Plain === "du" || w0Plain === "tree" || w0Plain === "stat" || w0Plain === "fd" || w0Plain === "rg" || w0Plain === "readlink" || w0Plain === "realpath" || w0Plain === "ls" || w0Plain === "find" || w0Plain === "csvlook" || w0Plain === "csvjson" || w0Plain === "csvsort" || w0Plain === "csvformat" || w0Plain === "csvstat" || w0Plain === "in2csv" || w0Plain === "csvstack" || w0Plain === "csvjoin" || w0Plain === "dd" || w0Plain === "env" || w0Plain === "xargs" || w0Plain === "openssl" || w0Plain === "sqlite3" || w0Plain === "gpg" || w0Plain === "ssh" || w0Plain === "ssh-keygen" || w0Plain === "pdfinfo" || w0Plain === "pdffonts" || w0Plain === "pdftotext" || w0Plain === "pdftohtml" || w0Plain === "exiftool" || w0Plain === "qpdf" || w0Plain === "pdftk" || w0Plain === "sips" || w0Plain === "identify" || w0Plain === "magick" || w0Plain === "convert" || w0Plain === "mogrify" || w0Plain === "composite" || w0Plain === "montage" || w0Plain === "compare" || w0Plain === "pdfimages" || w0Plain === "pdfdetach" || w0Plain === "ffprobe" || w0Plain === "ffmpeg" || w0Plain === "gh" || w0Plain === "pdftoppm" || w0Plain === "pdftocairo" || w0Plain === "mmdc" || w0Plain === "pandoc" || w0Plain === "soffice" || w0Plain === "libreoffice" || w0Plain === "ssconvert" || w0Plain === "wkhtmltopdf" || w0Plain === "op" || w0Plain === "git" || w0Plain === "tar" || w0Plain === "unzip" || w0Plain === "zip" || w0Plain === "timeout" || w0Plain === "split" || w0Plain === "csplit" || w0Plain === "curl" || w0Plain === "wget" || w0Plain === "sponge" || w0Plain === "truncate" || w0Plain === "install" || w0Plain === "apply_patch" || w0Plain === "mktemp" || w0Plain === "tee" || w0Plain === "touch" || w0Plain === "cp" || w0Plain === "mv" || w0Plain === "rmdir" || w0Plain === "sleep" || w0Plain === "chmod" || w0Plain === "patch" || w0Plain === "mkdir" || w0Plain === "rm" || w0Plain === "ln" || w0Plain === "date" || w0Plain === "printenv" || w0Plain === "egrep" || w0Plain === "fgrep" || w0Plain === "cal" || w0Plain === "ncal" || w0Plain === "md5sum" || w0Plain === "sha1sum" || w0Plain === "sha224sum" || w0Plain === "sha256sum" || w0Plain === "sha384sum" || w0Plain === "sha512sum" || w0Plain === "cksum" || w0Plain === "base32";
37910
- if (isSingleFileTool && !hasShellFunction(rawState, w0Plain) && (this.commands.has(w0Plain) || ((w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "column" || w0Plain === "fold" || w0Plain === "expand" || w0Plain === "unexpand" || w0Plain === "strings" || w0Plain === "comm" || w0Plain === "join" || w0Plain === "expr" || w0Plain === "bc" || w0Plain === "xxd" || w0Plain === "od" || w0Plain === "factor" || w0Plain === "tsort" || w0Plain === "envsubst" || w0Plain === "hexdump" || w0Plain === "hd" || w0Plain === "fmt" || w0Plain === "uname" || w0Plain === "id" || w0Plain === "whoami" || w0Plain === "hostname" || w0Plain === "nproc" || w0Plain === "getconf" || w0Plain === "locale" || w0Plain === "csvcut" || w0Plain === "csvgrep" || w0Plain === "getopt" || w0Plain === "dos2unix" || w0Plain === "unix2dos" || w0Plain === "iconv" || w0Plain === "gzip" || w0Plain === "gunzip" || w0Plain === "zcat" || w0Plain === "unzstd" || w0Plain === "zstdcat" || w0Plain === "zstd" || w0Plain === "bzip2" || w0Plain === "bunzip2" || w0Plain === "bzcat" || w0Plain === "xz" || w0Plain === "unxz" || w0Plain === "xzcat" || w0Plain === "lzma" || w0Plain === "unlzma" || w0Plain === "lzcat" || w0Plain === "htmlq" || w0Plain === "xmllint" || w0Plain === "xq" || w0Plain === "yq" || w0Plain === "mdq" || w0Plain === "shuf" || w0Plain === "html-to-markdown" || w0Plain === "unrtf" || w0Plain === "pr" || w0Plain === "pathchk" || w0Plain === "file" || w0Plain === "diff3" || w0Plain === "cmp" || w0Plain === "which" || w0Plain === "diff" || w0Plain === "xan" || w0Plain === "less" || w0Plain === "more" || w0Plain === "df" || w0Plain === "du" || w0Plain === "tree" || w0Plain === "stat" || w0Plain === "fd" || w0Plain === "rg" || w0Plain === "readlink" || w0Plain === "realpath" || w0Plain === "ls" || w0Plain === "find" || w0Plain === "csvlook" || w0Plain === "csvjson" || w0Plain === "csvsort" || w0Plain === "csvformat" || w0Plain === "csvstat" || w0Plain === "in2csv" || w0Plain === "csvstack" || w0Plain === "csvjoin" || w0Plain === "dd" || w0Plain === "env" || w0Plain === "xargs" || w0Plain === "openssl" || w0Plain === "sqlite3" || w0Plain === "gpg" || w0Plain === "ssh" || w0Plain === "ssh-keygen" || w0Plain === "pdfinfo" || w0Plain === "pdffonts" || w0Plain === "pdftotext" || w0Plain === "pdftohtml" || w0Plain === "exiftool" || w0Plain === "qpdf" || w0Plain === "pdftk" || w0Plain === "sips" || w0Plain === "identify" || w0Plain === "magick" || w0Plain === "convert" || w0Plain === "mogrify" || w0Plain === "composite" || w0Plain === "montage" || w0Plain === "compare" || w0Plain === "pdfimages" || w0Plain === "pdfdetach" || w0Plain === "ffprobe" || w0Plain === "ffmpeg" || w0Plain === "gh" || w0Plain === "pdftoppm" || w0Plain === "pdftocairo" || w0Plain === "mmdc" || w0Plain === "pandoc" || w0Plain === "soffice" || w0Plain === "libreoffice" || w0Plain === "ssconvert" || w0Plain === "wkhtmltopdf" || w0Plain === "op" || w0Plain === "git" || w0Plain === "tar" || w0Plain === "unzip" || w0Plain === "zip" || w0Plain === "timeout" || w0Plain === "split" || w0Plain === "csplit" || w0Plain === "curl" || w0Plain === "wget" || w0Plain === "sponge" || w0Plain === "truncate" || w0Plain === "install" || w0Plain === "apply_patch" || w0Plain === "mktemp" || w0Plain === "tee" || w0Plain === "touch" || w0Plain === "cp" || w0Plain === "mv" || w0Plain === "rmdir" || w0Plain === "sleep" || w0Plain === "chmod" || w0Plain === "patch" || w0Plain === "mkdir" || w0Plain === "rm" || w0Plain === "ln" || w0Plain === "date" || w0Plain === "printenv" || w0Plain === "egrep" || w0Plain === "fgrep" || w0Plain === "cal" || w0Plain === "ncal" || w0Plain === "md5sum" || w0Plain === "sha1sum" || w0Plain === "sha224sum" || w0Plain === "sha256sum" || w0Plain === "sha384sum" || w0Plain === "sha512sum" || w0Plain === "cksum" || w0Plain === "base32") && Boolean(this.getExternalCommand(w0Plain))))) {
37457
+ if (isSingleFileTool && !hasShellFunction(rawState, w0Plain) && (this.commands.has(w0Plain) || ((w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "column" || w0Plain === "fold" || w0Plain === "expand" || w0Plain === "unexpand" || w0Plain === "strings" || w0Plain === "comm" || w0Plain === "join" || w0Plain === "expr" || w0Plain === "bc" || w0Plain === "xxd" || w0Plain === "od" || w0Plain === "factor" || w0Plain === "tsort" || w0Plain === "envsubst" || w0Plain === "hexdump" || w0Plain === "hd" || w0Plain === "fmt" || w0Plain === "uname" || w0Plain === "id" || w0Plain === "whoami" || w0Plain === "hostname" || w0Plain === "nproc" || w0Plain === "getconf" || w0Plain === "locale" || w0Plain === "csvcut" || w0Plain === "csvgrep" || w0Plain === "getopt" || w0Plain === "dos2unix" || w0Plain === "unix2dos" || w0Plain === "iconv" || w0Plain === "gzip" || w0Plain === "gunzip" || w0Plain === "zcat" || w0Plain === "unzstd" || w0Plain === "zstdcat" || w0Plain === "zstd" || w0Plain === "bzip2" || w0Plain === "bunzip2" || w0Plain === "bzcat" || w0Plain === "xz" || w0Plain === "unxz" || w0Plain === "xzcat" || w0Plain === "lzma" || w0Plain === "unlzma" || w0Plain === "lzcat" || w0Plain === "htmlq" || w0Plain === "xmllint" || w0Plain === "xq" || w0Plain === "yq" || w0Plain === "mdq" || w0Plain === "shuf" || w0Plain === "html-to-markdown" || w0Plain === "unrtf" || w0Plain === "pr" || w0Plain === "pathchk" || w0Plain === "file" || w0Plain === "diff3" || w0Plain === "cmp" || w0Plain === "which" || w0Plain === "diff" || w0Plain === "xan" || w0Plain === "less" || w0Plain === "more" || w0Plain === "df" || w0Plain === "du" || w0Plain === "tree" || w0Plain === "stat" || w0Plain === "fd" || w0Plain === "rg" || w0Plain === "readlink" || w0Plain === "realpath" || w0Plain === "ls" || w0Plain === "find" || w0Plain === "csvlook" || w0Plain === "csvjson" || w0Plain === "csvsort" || w0Plain === "csvformat" || w0Plain === "csvstat" || w0Plain === "in2csv" || w0Plain === "csvstack" || w0Plain === "csvjoin" || w0Plain === "dd" || w0Plain === "env" || w0Plain === "xargs" || w0Plain === "openssl" || w0Plain === "sqlite3" || w0Plain === "gpg" || w0Plain === "ssh" || w0Plain === "ssh-keygen" || w0Plain === "pdfinfo" || w0Plain === "pdffonts" || w0Plain === "pdftotext" || w0Plain === "pdftohtml" || w0Plain === "exiftool" || w0Plain === "qpdf" || w0Plain === "pdftk" || w0Plain === "sips" || w0Plain === "identify" || w0Plain === "magick" || w0Plain === "convert" || w0Plain === "mogrify" || w0Plain === "composite" || w0Plain === "montage" || w0Plain === "compare" || w0Plain === "pdfimages" || w0Plain === "pdfdetach" || w0Plain === "ffprobe" || w0Plain === "ffmpeg" || w0Plain === "gh" || w0Plain === "pdftoppm" || w0Plain === "pdftocairo" || w0Plain === "mmdc" || w0Plain === "pandoc" || w0Plain === "soffice" || w0Plain === "libreoffice" || w0Plain === "ssconvert" || w0Plain === "wkhtmltopdf" || w0Plain === "op" || w0Plain === "git" || w0Plain === "tar" || w0Plain === "unzip" || w0Plain === "zip" || w0Plain === "timeout" || w0Plain === "split" || w0Plain === "csplit" || w0Plain === "curl" || w0Plain === "wget" || w0Plain === "sponge" || w0Plain === "truncate" || w0Plain === "install" || w0Plain === "apply_patch" || w0Plain === "mktemp" || w0Plain === "tee" || w0Plain === "touch" || w0Plain === "cp" || w0Plain === "mv" || w0Plain === "rmdir" || w0Plain === "sleep" || w0Plain === "chmod" || w0Plain === "patch" || w0Plain === "mkdir" || w0Plain === "rm" || w0Plain === "ln" || w0Plain === "date" || w0Plain === "printenv" || w0Plain === "egrep" || w0Plain === "fgrep" || w0Plain === "cal" || w0Plain === "ncal" || w0Plain === "md5sum" || w0Plain === "sha1sum" || w0Plain === "sha224sum" || w0Plain === "sha256sum" || w0Plain === "sha384sum" || w0Plain === "sha512sum" || w0Plain === "cksum" || w0Plain === "base32") && Boolean(this.commands.get(w0Plain))))) {
37911
37458
  const allArgs = [];
37912
37459
  let fOk = true;
37913
37460
  for (let i = 1; i < cmd.words.length; i++) {
@@ -38039,7 +37586,7 @@ export class Runtime {
38039
37586
  }
38040
37587
  }
38041
37588
  if (fOk && (w0Plain === "date" || w0Plain === "printenv" || w0Plain === "env") && !hasSingleStdinRedir && !hasSingleHereStringRedir) {
38042
- const ext = this.getExternalCommand(w0Plain);
37589
+ const ext = this.commands.get(w0Plain);
38043
37590
  const dpOut = w0Plain === "date"
38044
37591
  ? evalSyncDate(allArgs, rawState.exported.has("TZ") ? rawState.variables.TZ : undefined, ext?.execute, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true), (p) => this.tryInspectMemoryNodeSync(resolvePath(rawState.cwd, p), true, true)?.mtimeMs)
38045
37592
  : w0Plain === "env"
@@ -38067,7 +37614,7 @@ export class Runtime {
38067
37614
  const inspectNode = (p) => this.tryInspectMemoryNodeSync(p, true);
38068
37615
  const inspectStat = (p, follow) => this.tryInspectMemoryNodeSync(p, true, follow);
38069
37616
  const vfsOut = w0Plain === "df"
38070
- ? evalSyncDf(allArgs, rawState.cwd, rawState.variables, inspectNode, this.getExternalCommand("df")?.execute)
37617
+ ? evalSyncDf(allArgs, rawState.cwd, rawState.variables, inspectNode, this.commands.get("df")?.execute)
38071
37618
  : w0Plain === "du"
38072
37619
  ? evalSyncDu(allArgs, rawState.cwd, rawState.variables, inspectNode)
38073
37620
  : w0Plain === "tree"
@@ -38327,7 +37874,7 @@ export class Runtime {
38327
37874
  return false;
38328
37875
  } })
38329
37876
  : w0Plain === "gh"
38330
- ? syncCommandEvaluators.evalSyncGh?.(this.getExternalCommand("gh").execute, allArgs, rawState.variables, rawState.cwd, readFile)
37877
+ ? syncCommandEvaluators.evalSyncGh?.(this.commands.get("gh").execute, allArgs, rawState.variables, rawState.cwd, readFile)
38331
37878
  : w0Plain === "pdftoppm"
38332
37879
  ? syncCommandEvaluators.evalSyncPdftoppm?.(optInBytes, allArgs, readFile, (p, b) => { try {
38333
37880
  if (this._inSyncLoopPreflight)
@@ -38389,7 +37936,7 @@ export class Runtime {
38389
37936
  return false;
38390
37937
  } })
38391
37938
  : w0Plain === "ssconvert"
38392
- ? syncCommandEvaluators.evalSyncSsconvert?.(this.getExternalCommand("ssconvert").execute, allArgs, optInBytes, readFile, (p, b) => { try {
37939
+ ? syncCommandEvaluators.evalSyncSsconvert?.(this.commands.get("ssconvert").execute, allArgs, optInBytes, readFile, (p, b) => { try {
38393
37940
  if (this._inSyncLoopPreflight)
38394
37941
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
38395
37942
  const fp = resolvePath(rawState.cwd, p);
@@ -38413,9 +37960,9 @@ export class Runtime {
38413
37960
  return false;
38414
37961
  } })
38415
37962
  : w0Plain === "op"
38416
- ? syncCommandEvaluators.evalSyncOp?.(this.getExternalCommand("op").execute, allArgs, rawState.variables)
37963
+ ? syncCommandEvaluators.evalSyncOp?.(this.commands.get("op").execute, allArgs, rawState.variables)
38417
37964
  : w0Plain === "git"
38418
- ? syncCommandEvaluators.evalSyncGit?.(optInBytes, allArgs, rawState.cwd, (p, follow) => this.tryInspectMemoryNodeSync(p, p === "/", follow), (p) => this.tryReadMemoryFileViewSync(p, false, true), this.getExternalCommand("git").execute, (p, b, m) => { try {
37965
+ ? syncCommandEvaluators.evalSyncGit?.(optInBytes, allArgs, rawState.cwd, (p, follow) => this.tryInspectMemoryNodeSync(p, p === "/", follow), (p) => this.tryReadMemoryFileViewSync(p, false, true), this.commands.get("git").execute, (p, b, m) => { try {
38419
37966
  if (this._inSyncLoopPreflight)
38420
37967
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
38421
37968
  const dir = p.slice(0, p.lastIndexOf("/")) || "/";
@@ -39287,7 +38834,7 @@ export class Runtime {
39287
38834
  } });
39288
38835
  }
39289
38836
  else if (w0Plain === "gh") {
39290
- fileRes = syncCommandEvaluators.evalSyncGh?.(this.getExternalCommand("gh").execute, opArgs, rawState.variables, rawState.cwd, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), false));
38837
+ fileRes = syncCommandEvaluators.evalSyncGh?.(this.commands.get("gh").execute, opArgs, rawState.variables, rawState.cwd, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), false));
39291
38838
  }
39292
38839
  else if (w0Plain === "pdftoppm") {
39293
38840
  const readFile = (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true);
@@ -39360,7 +38907,7 @@ export class Runtime {
39360
38907
  } });
39361
38908
  }
39362
38909
  else if (w0Plain === "ssconvert") {
39363
- fileRes = syncCommandEvaluators.evalSyncSsconvert?.(this.getExternalCommand("ssconvert").execute, opArgs, view, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true), (p, b) => { try {
38910
+ fileRes = syncCommandEvaluators.evalSyncSsconvert?.(this.commands.get("ssconvert").execute, opArgs, view, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true), (p, b) => { try {
39364
38911
  if (this._inSyncLoopPreflight)
39365
38912
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
39366
38913
  const fp = resolvePath(rawState.cwd, p);
@@ -39387,10 +38934,10 @@ export class Runtime {
39387
38934
  } });
39388
38935
  }
39389
38936
  else if (w0Plain === "op") {
39390
- fileRes = syncCommandEvaluators.evalSyncOp?.(this.getExternalCommand("op").execute, opArgs, rawState.variables);
38937
+ fileRes = syncCommandEvaluators.evalSyncOp?.(this.commands.get("op").execute, opArgs, rawState.variables);
39391
38938
  }
39392
38939
  else if (w0Plain === "git") {
39393
- fileRes = syncCommandEvaluators.evalSyncGit?.(view, opArgs, rawState.cwd, (p, follow) => this.tryInspectMemoryNodeSync(p, p === "/", follow), (p) => this.tryReadMemoryFileViewSync(p, false, true), this.getExternalCommand("git").execute, (p, b, m) => { try {
38940
+ fileRes = syncCommandEvaluators.evalSyncGit?.(view, opArgs, rawState.cwd, (p, follow) => this.tryInspectMemoryNodeSync(p, p === "/", follow), (p) => this.tryReadMemoryFileViewSync(p, false, true), this.commands.get("git").execute, (p, b, m) => { try {
39394
38941
  if (this._inSyncLoopPreflight)
39395
38942
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
39396
38943
  const dir = p.slice(0, p.lastIndexOf("/")) || "/";
@@ -39869,6 +39416,8 @@ export class Runtime {
39869
39416
  }
39870
39417
  let fnPositional;
39871
39418
  if (rawState.functions.has(w0Plain)) {
39419
+ if (rawState.functionDepth >= this.budget.limits.maxFunctionDepth)
39420
+ return undefined;
39872
39421
  if (rawState.depth + 1 >= this.budget.limits.maxSubstitutionDepth)
39873
39422
  return undefined;
39874
39423
  const fnBody = rawState.functions.get(w0Plain);
@@ -39906,7 +39455,7 @@ export class Runtime {
39906
39455
  const disc = typeof targetName === "string" ? this.tryResolveSyncDiscovery(w0Plain === "command" ? "name" : "kind", targetName, rawState) : undefined;
39907
39456
  if (disc !== undefined && (disc.status === 0 || !rawState.errexit)) {
39908
39457
  if (disc.status === 0) {
39909
- const byteLength = (disc.text.length * 3 > 127 ? shellValueByteLength(disc.text) : disc.text.length) + 1;
39458
+ const byteLength = shellValueByteLength(disc.text) + 1;
39910
39459
  const nextBytes = this.budget.bytes + byteLength;
39911
39460
  if (nextBytes > this.budget.maxOutputBytesSmi && byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes)
39912
39461
  this.budget.fail("maxOutputBytes");
@@ -39924,7 +39473,7 @@ export class Runtime {
39924
39473
  let res = rawState.cwd;
39925
39474
  while (res.endsWith("\n"))
39926
39475
  res = res.slice(0, -1);
39927
- const byteLength = (res.length * 3 > 127 ? shellValueByteLength(res) : res.length) + 1;
39476
+ const byteLength = shellValueByteLength(res) + 1;
39928
39477
  const nextBytes = this.budget.bytes + byteLength;
39929
39478
  if (nextBytes > this.budget.maxOutputBytesSmi && byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes)
39930
39479
  this.budget.fail("maxOutputBytes");
@@ -39938,7 +39487,7 @@ export class Runtime {
39938
39487
  }
39939
39488
  if (w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq")
39940
39489
  return undefined;
39941
- const def = w0Plain === "seq" ? this.getExternalCommand(w0Plain) : this.commands.get(w0Plain);
39490
+ const def = this.commands.get(w0Plain);
39942
39491
  if (!def)
39943
39492
  return undefined;
39944
39493
  if (w0Plain === "printf" && def.execute !== printfCommand.execute)
@@ -41001,6 +40550,7 @@ export class RootShellState {
41001
40550
  this.status = 0;
41002
40551
  this.substitutionStatus = 0;
41003
40552
  this.lastArgument = "";
40553
+ this.secondsOrigin = Date.now();
41004
40554
  }
41005
40555
  get exported() {
41006
40556
  const raw = stateMonitor(this)?.raw;