@poe-platform/safe-bash 0.1.800 → 0.1.802

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 (502) hide show
  1. package/README.md +16 -5
  2. package/dist/image-ast/index.browser.js +122 -76
  3. package/dist/image-ast/index.js +122 -76
  4. package/dist/pdf-ast/index.js +4 -3
  5. package/dist/safe-bash/chunks/chunk-3HQU4OJO.js +13 -0
  6. package/dist/safe-bash/chunks/{chunk-LUOFIVNI.js → chunk-3NDIFSNM.js} +3 -3
  7. package/dist/safe-bash/chunks/{chunk-4SEW2Q6H.js → chunk-3R3AANOR.js} +1 -1
  8. package/dist/safe-bash/chunks/{chunk-K4YMYFRJ.js → chunk-44ALJ4QG.js} +5809 -7424
  9. package/dist/safe-bash/chunks/{chunk-KHMGTPD6.js → chunk-46Z5E5EV.js} +2 -2
  10. package/dist/safe-bash/chunks/chunk-4BSJLKNM.js +14 -0
  11. package/dist/safe-bash/chunks/chunk-4D4N7IU2.js +47 -0
  12. package/dist/safe-bash/chunks/chunk-55YJASTN.js +14 -0
  13. package/dist/safe-bash/chunks/{chunk-XB3B7KMM.js → chunk-6O77NL2S.js} +1 -1
  14. package/dist/safe-bash/chunks/{chunk-T3JTVIEP.js → chunk-6PAVEFT3.js} +1 -1
  15. package/dist/safe-bash/chunks/{chunk-PYVEAFJM.js → chunk-74GHTNJA.js} +3 -2
  16. package/dist/safe-bash/chunks/{chunk-LQHGH25W.js → chunk-7R5BDCG7.js} +1 -1
  17. package/dist/safe-bash/chunks/chunk-7ZBU7KYV.js +14 -0
  18. package/dist/safe-bash/chunks/{chunk-MHZ24KEI.js → chunk-AM5ESLPH.js} +1 -1
  19. package/dist/safe-bash/chunks/{chunk-3L3T6LYV.js → chunk-AUSNDQTJ.js} +1 -1
  20. package/dist/safe-bash/chunks/{chunk-YG5WAHK7.js → chunk-B7TAL7S5.js} +1 -3
  21. package/dist/safe-bash/chunks/{chunk-QVSRRNZT.js → chunk-BJA5XNP6.js} +6 -6
  22. package/dist/safe-bash/chunks/{chunk-K7IQZE7D.js → chunk-C5OWC2TL.js} +1 -1
  23. package/dist/safe-bash/chunks/{chunk-F3RV2F72.js → chunk-CHYGPFVM.js} +1 -1
  24. package/dist/safe-bash/chunks/{chunk-M4CFCXHN.js → chunk-CS4MNM6I.js} +1 -1
  25. package/dist/safe-bash/chunks/{chunk-H6JW3E4F.js → chunk-CTVWDACF.js} +1 -1
  26. package/dist/safe-bash/chunks/{chunk-BHJE5LPZ.js → chunk-D3ANYGMC.js} +1 -1
  27. package/dist/safe-bash/chunks/chunk-DQP3VHSB.js +15 -0
  28. package/dist/safe-bash/chunks/{chunk-NLAW7KDI.js → chunk-E7OYNDGL.js} +1 -1
  29. package/dist/safe-bash/chunks/{chunk-SOZK5JVX.js → chunk-FBUCWVTE.js} +1 -1
  30. package/dist/safe-bash/chunks/chunk-FZE4HW6G.js +11 -0
  31. package/dist/safe-bash/chunks/chunk-GEG3BWGE.js +14 -0
  32. package/dist/safe-bash/chunks/{chunk-HHW7MGS2.js → chunk-GETUOD5D.js} +4 -4
  33. package/dist/safe-bash/chunks/chunk-HBCN24ZA.js +50 -0
  34. package/dist/safe-bash/chunks/chunk-HZ7BWKQ3.js +13 -0
  35. package/dist/safe-bash/chunks/{chunk-JJSTTIEZ.js → chunk-HZAMGT5I.js} +3 -3
  36. package/dist/safe-bash/chunks/{chunk-KCVSVD65.js → chunk-I5HZ4FGE.js} +1 -1
  37. package/dist/safe-bash/chunks/{chunk-KV7PKOHV.js → chunk-IWDICZVK.js} +1 -1
  38. package/dist/safe-bash/chunks/{chunk-I4OAEOP6.js → chunk-J42RIHHJ.js} +1 -1
  39. package/dist/safe-bash/chunks/{chunk-K2VCOJ2B.js → chunk-K6VCD7IY.js} +7 -12
  40. package/dist/safe-bash/chunks/chunk-KDNSPLII.js +83 -0
  41. package/dist/safe-bash/chunks/{chunk-63FXVDGF.js → chunk-LVOBFF4D.js} +1 -1
  42. package/dist/safe-bash/chunks/{chunk-U5NUZPCC.js → chunk-MHMMRCYC.js} +1 -1
  43. package/dist/safe-bash/chunks/{chunk-KW24TAIU.js → chunk-NQCM3TYR.js} +922 -658
  44. package/dist/safe-bash/chunks/{chunk-VYZTG3GV.js → chunk-NZQXYWA3.js} +1 -1
  45. package/dist/safe-bash/chunks/{chunk-TFGRKY43.js → chunk-OQRVVGR6.js} +1 -1
  46. package/dist/safe-bash/chunks/{chunk-PPYM75Z3.js → chunk-OV6IHKO6.js} +2 -2
  47. package/dist/safe-bash/chunks/{chunk-TYD7EVUJ.js → chunk-PH63PLPZ.js} +8 -8
  48. package/dist/safe-bash/chunks/chunk-QGUV42T5.js +44 -0
  49. package/dist/safe-bash/chunks/chunk-R3NAKOED.js +51 -0
  50. package/dist/safe-bash/chunks/chunk-RRR7AQ24.js +38 -0
  51. package/dist/safe-bash/chunks/{chunk-RKKRJ54E.js → chunk-RSTHLAF3.js} +30 -23
  52. package/dist/safe-bash/chunks/{chunk-RMWLWH7Q.js → chunk-SHEMU2Z7.js} +378 -1148
  53. package/dist/safe-bash/chunks/{chunk-7YSRXFEG.js → chunk-TFIBK2GI.js} +1 -1
  54. package/dist/safe-bash/chunks/{chunk-I7L3G3NX.js → chunk-UE5KZDEK.js} +2 -2
  55. package/dist/safe-bash/chunks/{chunk-QU3BVQ53.js → chunk-UTBUUFDM.js} +1 -1
  56. package/dist/safe-bash/chunks/{chunk-6HZYFL3H.js → chunk-VKNVHEX3.js} +2 -7
  57. package/dist/safe-bash/chunks/chunk-VSAJ4OTM.js +962 -0
  58. package/dist/safe-bash/chunks/{chunk-46UISJCK.js → chunk-VTH3MLDU.js} +1 -1
  59. package/dist/safe-bash/chunks/{chunk-JTLSUJ7V.js → chunk-WDLGKIHD.js} +56 -39
  60. package/dist/safe-bash/chunks/chunk-XAQMU6OY.js +14 -0
  61. package/dist/safe-bash/chunks/{chunk-LLZCZ24K.js → chunk-XVOSKJE2.js} +1 -1
  62. package/dist/safe-bash/chunks/chunk-ZVD5IS4V.js +49 -0
  63. package/dist/safe-bash/chunks/{csvkit-QGP3GAOB.js → csvkit-TACDU7FC.js} +3 -3
  64. package/dist/safe-bash/chunks/{ffmpeg-JTVH26MK.js → ffmpeg-WTC3TEFI.js} +2 -2
  65. package/dist/safe-bash/chunks/{gh-I7QX7N5C.js → gh-6WU6PXL4.js} +2 -2
  66. package/dist/safe-bash/chunks/{git-MA7NKYVP.js → git-EFZIGJW4.js} +2 -2
  67. package/dist/safe-bash/chunks/{imagemagick-Y4NPWX2Q.js → imagemagick-EIEYGWPF.js} +2 -2
  68. package/dist/safe-bash/chunks/{implementation-BWDKOVQJ.js → implementation-MLFHUQ5M.js} +2 -2
  69. package/dist/safe-bash/chunks/{mmdc-44PELHDG.js → mmdc-ROQJT5HQ.js} +2 -2
  70. package/dist/safe-bash/chunks/{pdfimages-635TRW4Q.js → pdfimages-DW7LWXFI.js} +2 -2
  71. package/dist/safe-bash/chunks/{pdfinfo-FSDAA2KY.js → pdfinfo-TIP6XLUQ.js} +2 -2
  72. package/dist/safe-bash/chunks/{pdftk-GQ5UH3VG.js → pdftk-DMG22ITZ.js} +2 -2
  73. package/dist/safe-bash/chunks/{pdftoppm-YTXQCAYT.js → pdftoppm-WNDYR72T.js} +2 -2
  74. package/dist/safe-bash/chunks/{pdftotext-CVA2G7FY.js → pdftotext-5IPZ4NI7.js} +2 -2
  75. package/dist/safe-bash/chunks/{qpdf-HZMIFG4A.js → qpdf-TTX2DIUA.js} +2 -2
  76. package/dist/safe-bash/chunks/{sips-E7UBDP33.js → sips-XYS46JPJ.js} +2 -2
  77. package/dist/safe-bash/chunks/{soffice-ELASUWUK.js → soffice-TU73E5KL.js} +2 -2
  78. package/dist/safe-bash/chunks/{wkhtmltopdf-EPO6YCMG.js → wkhtmltopdf-FSZ2CHGE.js} +2 -2
  79. package/dist/safe-bash/command-chunks/{chunk-QBGA56UH.js → chunk-2ELYGJDD.js} +7 -7
  80. package/dist/safe-bash/command-chunks/{chunk-52PCQXD2.js → chunk-2NHI5F5S.js} +2 -1
  81. package/dist/safe-bash/command-chunks/{chunk-HDKVO47G.js → chunk-2SQEIUGJ.js} +3 -3
  82. package/dist/safe-bash/command-chunks/{chunk-5LSGEIZY.js → chunk-3HHCU5YU.js} +4 -3
  83. package/dist/safe-bash/command-chunks/{chunk-TF6OA2GK.js → chunk-3NV3HYT2.js} +1 -1
  84. package/dist/safe-bash/command-chunks/{chunk-2QHG43WJ.js → chunk-4BB2SWJ5.js} +1 -1
  85. package/dist/safe-bash/command-chunks/{chunk-IEXHHNOF.js → chunk-4J5CZ2DP.js} +2 -7
  86. package/dist/safe-bash/command-chunks/{chunk-WDHI3S6Y.js → chunk-4OOUQTQO.js} +1 -1
  87. package/dist/safe-bash/command-chunks/{chunk-YMONDXET.js → chunk-4ZQWGOZB.js} +2 -2
  88. package/dist/safe-bash/command-chunks/{chunk-L6DVEBW3.js → chunk-5BSTFCXG.js} +2 -2
  89. package/dist/safe-bash/command-chunks/{chunk-Q3DII3Q7.js → chunk-5PWJG2UK.js} +1 -1
  90. package/dist/safe-bash/command-chunks/{chunk-JMPP4TCW.js → chunk-5UBXNSFZ.js} +3 -2
  91. package/dist/safe-bash/command-chunks/{chunk-3NG75MOB.js → chunk-67GQA75T.js} +1 -1
  92. package/dist/safe-bash/command-chunks/{chunk-L6SU4S26.js → chunk-6B7WQIKB.js} +0 -7
  93. package/dist/safe-bash/command-chunks/{chunk-V6MSPQLA.js → chunk-6BNTBWIK.js} +4 -39
  94. package/dist/safe-bash/command-chunks/{chunk-SAMH7SQE.js → chunk-6GWJUQAV.js} +237 -145
  95. package/dist/safe-bash/command-chunks/{chunk-JN7WIP6S.js → chunk-6KJ3LPI2.js} +2 -2
  96. package/dist/safe-bash/command-chunks/{chunk-HLDTOR7M.js → chunk-6ZVI7LUY.js} +1 -1
  97. package/dist/safe-bash/command-chunks/{chunk-X6NJC3IC.js → chunk-75OFBY5R.js} +1 -1
  98. package/dist/safe-bash/command-chunks/{chunk-MRW5HD2D.js → chunk-7O3E4LPT.js} +4 -22
  99. package/dist/safe-bash/command-chunks/{chunk-TEVJJPTC.js → chunk-7U7EXOXX.js} +1 -1
  100. package/dist/safe-bash/command-chunks/{chunk-6CYTRQ24.js → chunk-7VTKQUA5.js} +20 -17
  101. package/dist/safe-bash/command-chunks/{chunk-BZPAWTUL.js → chunk-AEF5BA3D.js} +1 -1
  102. package/dist/safe-bash/command-chunks/{chunk-63R3FEZJ.js → chunk-AIV5BF5W.js} +1 -1
  103. package/dist/safe-bash/command-chunks/{chunk-AYUTO323.js → chunk-AKJG2XD3.js} +2 -18
  104. package/dist/safe-bash/command-chunks/{chunk-J34TZVMW.js → chunk-ALDC4XP4.js} +0 -5
  105. package/dist/safe-bash/command-chunks/{chunk-CKXV2CLD.js → chunk-ARBYOQUZ.js} +1 -1
  106. package/dist/safe-bash/command-chunks/{chunk-44AHAB5O.js → chunk-BDSMROQZ.js} +1 -4
  107. package/dist/safe-bash/command-chunks/{chunk-53P53XFM.js → chunk-BPE5INLI.js} +1 -1
  108. package/dist/safe-bash/command-chunks/{chunk-OT4LZMLB.js → chunk-BR73BIOW.js} +1 -1
  109. package/dist/safe-bash/command-chunks/{chunk-WB5SVIG7.js → chunk-C5YYCQHW.js} +498 -88
  110. package/dist/safe-bash/command-chunks/{chunk-EUSPTFAX.js → chunk-CAP7ZJSY.js} +7 -7
  111. package/dist/safe-bash/command-chunks/{chunk-DWFLVJC6.js → chunk-CCRHMAU5.js} +2 -1
  112. package/dist/safe-bash/command-chunks/{chunk-GI4CJED2.js → chunk-CQTRW45K.js} +1 -1
  113. package/dist/safe-bash/command-chunks/{chunk-KKG4BAFZ.js → chunk-DIEPXUM4.js} +6 -0
  114. package/dist/safe-bash/command-chunks/{chunk-QJAFJP2G.js → chunk-DZCY63VJ.js} +12 -10
  115. package/dist/safe-bash/command-chunks/{chunk-QUENU6GM.js → chunk-E55UKBIE.js} +3 -3
  116. package/dist/safe-bash/command-chunks/{chunk-MC3VWLIZ.js → chunk-FDBUV4HJ.js} +28 -19
  117. package/dist/safe-bash/command-chunks/{chunk-7FKUC34S.js → chunk-FPVUD6TH.js} +6 -3
  118. package/dist/safe-bash/command-chunks/{chunk-E2LB7FRT.js → chunk-FXOA7RBK.js} +1 -1
  119. package/dist/safe-bash/command-chunks/{chunk-QWIDNAAK.js → chunk-FZTK4MFI.js} +3 -3
  120. package/dist/safe-bash/command-chunks/{chunk-K543PB3I.js → chunk-G66QUHIZ.js} +6 -35
  121. package/dist/safe-bash/command-chunks/{chunk-YJDV76GL.js → chunk-GFQZCKO6.js} +29 -19
  122. package/dist/safe-bash/command-chunks/{chunk-FKKB5X5V.js → chunk-GOB777HR.js} +1 -1
  123. package/dist/safe-bash/command-chunks/{chunk-IYPAQ7PH.js → chunk-GRBWW4SG.js} +6 -0
  124. package/dist/safe-bash/command-chunks/{chunk-EFANWIHL.js → chunk-GY3BWK7K.js} +1 -0
  125. package/dist/safe-bash/command-chunks/{chunk-PPNBNFAU.js → chunk-GYQ2HAKQ.js} +8 -8
  126. package/dist/safe-bash/command-chunks/{chunk-PJJUYO3R.js → chunk-II77KPZN.js} +2 -2
  127. package/dist/safe-bash/command-chunks/{chunk-VL67NWNS.js → chunk-JDYXY44P.js} +2 -2
  128. package/dist/safe-bash/command-chunks/{chunk-4QJOYXVB.js → chunk-JV7LBUTP.js} +1 -1
  129. package/dist/safe-bash/command-chunks/{chunk-IKS2YXZQ.js → chunk-K67MWWWH.js} +3 -3
  130. package/dist/safe-bash/command-chunks/{chunk-BKCNF5U3.js → chunk-KQLD3AED.js} +2 -2
  131. package/dist/safe-bash/command-chunks/{chunk-UMDIOL3O.js → chunk-KXU3IRUO.js} +1 -1
  132. package/dist/safe-bash/command-chunks/{chunk-QZF3SINC.js → chunk-LAOM65EE.js} +2 -2
  133. package/dist/safe-bash/command-chunks/{chunk-HFII3QYO.js → chunk-LWS62ISU.js} +46 -32
  134. package/dist/safe-bash/command-chunks/{chunk-BZDDAPSV.js → chunk-LWSBAWLT.js} +1 -1
  135. package/dist/safe-bash/command-chunks/{chunk-U6G67N23.js → chunk-MIXBO6U7.js} +18 -5
  136. package/dist/safe-bash/command-chunks/{chunk-JQ74HC37.js → chunk-MQFIPHIQ.js} +23 -50
  137. package/dist/safe-bash/command-chunks/{chunk-ZJBR5Q5I.js → chunk-MSFXC3OC.js} +4 -4
  138. package/dist/safe-bash/command-chunks/{chunk-NI7MKJPN.js → chunk-MTQH74CF.js} +3 -55
  139. package/dist/safe-bash/command-chunks/chunk-MWUZZWXK.js +354 -0
  140. package/dist/safe-bash/command-chunks/{chunk-RVLO4DYT.js → chunk-N4PFUSRM.js} +1 -1
  141. package/dist/safe-bash/command-chunks/{chunk-WBNZ4PRE.js → chunk-NGG2XL56.js} +7 -4
  142. package/dist/safe-bash/command-chunks/{chunk-D4OP2BR3.js → chunk-NKFYQSES.js} +1 -2
  143. package/dist/safe-bash/command-chunks/{chunk-NGWB2YBL.js → chunk-O4JQSB7O.js} +1 -1
  144. package/dist/safe-bash/command-chunks/{chunk-GLOZX57Y.js → chunk-OQKC5ZU2.js} +23 -114
  145. package/dist/safe-bash/command-chunks/{chunk-7L24L4UO.js → chunk-OQU6UT6X.js} +2 -20
  146. package/dist/safe-bash/command-chunks/{chunk-TYCGMRLM.js → chunk-OYYV7ZAF.js} +1 -1
  147. package/dist/safe-bash/command-chunks/{chunk-SVULUDOP.js → chunk-P2N33UMN.js} +20 -81
  148. package/dist/safe-bash/command-chunks/{chunk-Q7Q5GM5S.js → chunk-P5APDEFB.js} +2 -2
  149. package/dist/safe-bash/command-chunks/{chunk-3HXDA5PT.js → chunk-PMBFZXTK.js} +1 -1
  150. package/dist/safe-bash/command-chunks/{chunk-4Y3WVMK4.js → chunk-PV66YWHB.js} +1 -0
  151. package/dist/safe-bash/command-chunks/{chunk-AXK3H4PX.js → chunk-QJ33BHI4.js} +1 -1
  152. package/dist/safe-bash/command-chunks/{chunk-3LSOYLNV.js → chunk-QKFSRZGQ.js} +2 -2
  153. package/dist/safe-bash/command-chunks/{chunk-JZSNU2MY.js → chunk-QKJLP53H.js} +2 -2
  154. package/dist/safe-bash/command-chunks/{chunk-LC2MFKT4.js → chunk-RMWQAAO5.js} +24 -25
  155. package/dist/safe-bash/command-chunks/{chunk-QDTBMSBE.js → chunk-RO62EWX6.js} +2 -2
  156. package/dist/safe-bash/command-chunks/{chunk-4C6QI5BQ.js → chunk-RZZI24ZE.js} +4 -4
  157. package/dist/safe-bash/command-chunks/{chunk-PFAADCB5.js → chunk-SDNBCQ3X.js} +10 -24
  158. package/dist/safe-bash/command-chunks/{chunk-36O5OT7E.js → chunk-T35Y7YQD.js} +1 -1
  159. package/dist/safe-bash/command-chunks/{chunk-6HMX4CQS.js → chunk-TGSNCQSR.js} +44 -16
  160. package/dist/safe-bash/command-chunks/{chunk-5T7CRJHW.js → chunk-TIOCQVUQ.js} +4 -7
  161. package/dist/safe-bash/command-chunks/{chunk-GN2TKLE7.js → chunk-TS65BJHG.js} +5 -5
  162. package/dist/safe-bash/command-chunks/{chunk-7RGB363W.js → chunk-TSCGT46G.js} +3 -2
  163. package/dist/safe-bash/command-chunks/{chunk-KBEURXFF.js → chunk-UN6WS55J.js} +3 -3
  164. package/dist/safe-bash/command-chunks/{chunk-SX2X3IH4.js → chunk-V2V5OCL3.js} +1 -1
  165. package/dist/safe-bash/command-chunks/{chunk-ERYJLO6G.js → chunk-V7A7DRTU.js} +1 -1
  166. package/dist/safe-bash/command-chunks/{chunk-5SHGJ7NO.js → chunk-VA5ZHYYA.js} +73 -33
  167. package/dist/safe-bash/command-chunks/{chunk-XETLEHZP.js → chunk-VPR5LQYX.js} +3 -2
  168. package/dist/safe-bash/command-chunks/{chunk-3DT2YOGW.js → chunk-VSRGNQCP.js} +3 -3
  169. package/dist/safe-bash/command-chunks/{chunk-N2F74VRO.js → chunk-VT6MJBEI.js} +1 -1
  170. package/dist/safe-bash/command-chunks/{chunk-J5SN3PZ3.js → chunk-VXSLJH7G.js} +53 -3
  171. package/dist/safe-bash/command-chunks/{chunk-PXYOWWMV.js → chunk-W7RAD4EW.js} +4 -3
  172. package/dist/safe-bash/command-chunks/{chunk-YGC6OS5O.js → chunk-WECIOOQB.js} +5 -8
  173. package/dist/safe-bash/command-chunks/{chunk-HHP343KT.js → chunk-WTECBRU4.js} +1 -1
  174. package/dist/safe-bash/command-chunks/{chunk-AO6Z5EQ7.js → chunk-WVE64WM2.js} +6 -5
  175. package/dist/safe-bash/command-chunks/{chunk-Z7RVSD5K.js → chunk-WVHONVZ4.js} +1 -1
  176. package/dist/safe-bash/command-chunks/{chunk-HLGKIZ25.js → chunk-X54L3DBL.js} +6 -9
  177. package/dist/safe-bash/command-chunks/{chunk-QNIMV57G.js → chunk-XNLFHHOC.js} +1 -1
  178. package/dist/safe-bash/command-chunks/{chunk-XAFSZDY2.js → chunk-XS72HTMA.js} +11 -0
  179. package/dist/safe-bash/command-chunks/{chunk-KYSPGS33.js → chunk-YIQACGEW.js} +2 -0
  180. package/dist/safe-bash/command-chunks/{chunk-NAY27PXB.js → chunk-YOFC45RK.js} +1 -1
  181. package/dist/safe-bash/command-chunks/{chunk-T5H5UJQ3.js → chunk-YVNGTIJO.js} +1 -1
  182. package/dist/safe-bash/command-chunks/{chunk-QI7LGHJJ.js → chunk-Z45N42QC.js} +21 -6
  183. package/dist/safe-bash/command-chunks/{chunk-67IQF5GC.js → chunk-ZYHTWNAE.js} +23 -9
  184. package/dist/safe-bash/command-chunks/{chunk-STC3LEWJ.js → chunk-ZYXH3B66.js} +5 -3
  185. package/dist/safe-bash/commands/apply-patch/index.browser.js +14 -0
  186. package/dist/safe-bash/commands/archive/index.browser.js +36 -0
  187. package/dist/safe-bash/commands/bytes/compression/index.js +3 -2
  188. package/dist/safe-bash/commands/column/index.browser.js +12 -0
  189. package/dist/safe-bash/commands/copy-preserve.d.ts +1 -0
  190. package/dist/safe-bash/commands/csplit/index.browser.js +2 -2
  191. package/dist/safe-bash/commands/docx/index.browser.js +1 -1
  192. package/dist/safe-bash/commands/du/index.browser.js +14 -0
  193. package/dist/safe-bash/commands/execution.js +19 -13
  194. package/dist/safe-bash/commands/expr/index.browser.js +12 -0
  195. package/dist/safe-bash/commands/factor/index.browser.js +2 -2
  196. package/dist/safe-bash/commands/file/index.browser.js +14 -0
  197. package/dist/safe-bash/commands/filesystem.d.ts +1 -1
  198. package/dist/safe-bash/commands/filesystem.js +26 -15
  199. package/dist/safe-bash/commands/getopt/index.browser.js +2 -2
  200. package/dist/safe-bash/commands/grep-aliases/index.browser.js +14 -0
  201. package/dist/safe-bash/commands/hexdump/index.browser.js +2 -2
  202. package/dist/safe-bash/commands/html-to-markdown/index.browser.js +16 -0
  203. package/dist/safe-bash/commands/htmlq/index.d.ts +1 -1
  204. package/dist/safe-bash/commands/iconv/index.browser.js +2 -2
  205. package/dist/safe-bash/commands/line-endings/index.browser.js +2 -2
  206. package/dist/safe-bash/commands/llm/index.browser.js +2 -2
  207. package/dist/safe-bash/commands/llm/providers/index.browser.js +1 -1
  208. package/dist/safe-bash/commands/mdq/index.browser.js +3 -3
  209. package/dist/safe-bash/commands/media/index.browser.js +1 -1
  210. package/dist/safe-bash/commands/metadata/index.browser.js +21 -0
  211. package/dist/safe-bash/commands/network/curl.d.ts +1 -1
  212. package/dist/safe-bash/commands/network/curl.js +1 -3
  213. package/dist/safe-bash/commands/network/index.browser.js +4 -4
  214. package/dist/safe-bash/commands/network/platform-portable.d.ts +1 -5
  215. package/dist/safe-bash/commands/network/platform-portable.js +1 -26
  216. package/dist/safe-bash/commands/network/public.d.ts +2 -2
  217. package/dist/safe-bash/commands/network/public.js +2 -2
  218. package/dist/safe-bash/commands/network/transport.js +2 -2
  219. package/dist/safe-bash/commands/network/wget.d.ts +1 -1
  220. package/dist/safe-bash/commands/network/wget.js +1 -3
  221. package/dist/safe-bash/commands/node/filesystem.js +3 -2
  222. package/dist/safe-bash/commands/node/index.browser.js +8 -8
  223. package/dist/safe-bash/commands/node/types.js +1 -1
  224. package/dist/safe-bash/commands/op/index.browser.js +3 -3
  225. package/dist/safe-bash/commands/pr/index.browser.js +2 -2
  226. package/dist/safe-bash/commands/python/host-capabilities.js +31 -14
  227. package/dist/safe-bash/commands/python/index.browser.js +11 -11
  228. package/dist/safe-bash/commands/python/manifest.d.ts +1 -0
  229. package/dist/safe-bash/commands/python/manifest.js +6 -3
  230. package/dist/safe-bash/commands/python/shell-capability.d.ts +1 -0
  231. package/dist/safe-bash/commands/python/shell-capability.js +3 -2
  232. package/dist/safe-bash/commands/python/worker.browser.js +3 -3
  233. package/dist/safe-bash/commands/regex-execution/public.browser.js +8 -6
  234. package/dist/safe-bash/commands/safejs/runtime.js +16 -7
  235. package/dist/safe-bash/commands/split/index.browser.js +14 -0
  236. package/dist/safe-bash/commands/standard.d.ts +1 -0
  237. package/dist/safe-bash/commands/standard.js +2 -1
  238. package/dist/safe-bash/commands/stream-format/index.browser.js +11 -0
  239. package/dist/safe-bash/commands/stream-inspection/index.browser.js +11 -0
  240. package/dist/safe-bash/commands/streams.js +11 -29
  241. package/dist/safe-bash/commands/table-text/index.browser.js +11 -0
  242. package/dist/safe-bash/commands/text.js +269 -496
  243. package/dist/safe-bash/commands/time-env/index.browser.js +15 -0
  244. package/dist/safe-bash/commands/tree/index.browser.js +14 -0
  245. package/dist/safe-bash/commands/tsort/index.browser.js +2 -2
  246. package/dist/safe-bash/commands/xml/index.browser.js +2 -2
  247. package/dist/safe-bash/commands/yq/index.browser.js +2 -2
  248. package/dist/safe-bash/core.browser.js +1 -1
  249. package/dist/safe-bash/core.d.ts +6 -1
  250. package/dist/safe-bash/core.js +1 -1
  251. package/dist/safe-bash/full-core.browser.js +308 -295
  252. package/dist/safe-bash/jobs.browser.js +5 -5
  253. package/dist/safe-bash/opt-in/commands/dd/index.js +2 -0
  254. package/dist/safe-bash/opt-in/optional/commands/shuf/options.d.ts +1 -0
  255. package/dist/safe-bash/opt-in/optional/commands/shuf/options.js +2 -4
  256. package/dist/safe-bash/opt-in/optional/commands/shuf/shuf.js +2 -1
  257. package/dist/safe-bash/optional-host.browser.js +15 -15
  258. package/dist/safe-bash/plugins/composition.d.ts +1 -0
  259. package/dist/safe-bash/plugins/composition.js +3 -8
  260. package/dist/safe-bash/plugins/index.browser.js +41 -27
  261. package/dist/safe-bash/registry-entry.browser.js +42 -28
  262. package/dist/safe-bash/search.browser.js +48 -0
  263. package/dist/safe-bash/shell/arrays/bindings.js +1 -1
  264. package/dist/safe-bash/shell/arrays/state.js +4 -0
  265. package/dist/safe-bash/shell/brace-expansion.js +1 -1
  266. package/dist/safe-bash/shell/dynamic-variables.d.ts +10 -0
  267. package/dist/safe-bash/shell/dynamic-variables.js +25 -0
  268. package/dist/safe-bash/shell/parser.js +8 -1
  269. package/dist/safe-bash/shell/runtime.d.ts +4 -13
  270. package/dist/safe-bash/shell/runtime.js +334 -1049
  271. package/dist/safe-bash/shell/shell.js +2 -54
  272. package/dist/safe-bash/shell-entry.browser.js +35 -26
  273. package/dist/safe-bash/trap.browser.js +4 -4
  274. package/dist/safe-bash/yq-browser/index.js +1 -1
  275. package/dist/safe-bash-base-encoding-engine/base.js +2 -2
  276. package/dist/safe-bash-base-encoding-engine/shared.js +1 -1
  277. package/dist/safe-bash-byte-input-engine/index.d.ts +3 -2
  278. package/dist/safe-bash-byte-input-engine/index.js +4 -1
  279. package/dist/safe-bash-checksum-engine/index.js +13 -6
  280. package/dist/safe-bash-command-apply-patch/apply.d.ts +1 -1
  281. package/dist/safe-bash-command-apply-patch/apply.js +4 -3
  282. package/dist/safe-bash-command-apply-patch/index.js +3 -3
  283. package/dist/safe-bash-command-apply-patch/matcher.js +1 -1
  284. package/dist/safe-bash-command-apply-patch/parser.js +1 -1
  285. package/dist/safe-bash-command-awk/awk-inspection.js +2 -2
  286. package/dist/safe-bash-command-awk/awk-runtime.js +3 -3
  287. package/dist/safe-bash-command-awk/awk-syntax.d.ts +1 -1
  288. package/dist/safe-bash-command-awk/awk-syntax.js +2 -2
  289. package/dist/safe-bash-command-awk/awk-values.js +1 -1
  290. package/dist/safe-bash-command-awk/awk.js +5 -5
  291. package/dist/safe-bash-command-awk/index.js +5 -5
  292. package/dist/safe-bash-command-bc/index.d.ts +2 -0
  293. package/dist/safe-bash-command-bc/index.js +123 -92
  294. package/dist/safe-bash-command-column/column.js +5 -5
  295. package/dist/safe-bash-command-column/display.d.ts +1 -1
  296. package/dist/safe-bash-command-column/display.js +1 -1
  297. package/dist/safe-bash-command-column/index.js +5 -5
  298. package/dist/safe-bash-command-column/internal.d.ts +0 -2
  299. package/dist/safe-bash-command-column/internal.js +1 -1
  300. package/dist/safe-bash-command-column/layout.js +4 -4
  301. package/dist/safe-bash-command-column/table.js +2 -2
  302. package/dist/safe-bash-command-comm/comm.js +1 -1
  303. package/dist/safe-bash-command-comm/index.js +1 -1
  304. package/dist/safe-bash-command-csvcut/index.d.ts +1 -0
  305. package/dist/safe-bash-command-csvcut/index.js +1 -0
  306. package/dist/safe-bash-command-csvgrep/index.d.ts +1 -0
  307. package/dist/safe-bash-command-csvgrep/index.js +2 -2
  308. package/dist/safe-bash-command-csvkit/index.js +9 -9
  309. package/dist/safe-bash-command-csvkit/sync-support.js +1 -1
  310. package/dist/safe-bash-command-curl/curl.js +1 -1
  311. package/dist/safe-bash-command-curl/index.js +1 -1
  312. package/dist/safe-bash-command-dd/index.js +2 -0
  313. package/dist/safe-bash-command-diff/diff.js +1 -1
  314. package/dist/safe-bash-command-diff/index.js +1 -1
  315. package/dist/safe-bash-command-exiftool/index.d.ts +1 -0
  316. package/dist/safe-bash-command-fd/index.js +9 -9
  317. package/dist/safe-bash-command-ffmpeg/index.js +31 -8
  318. package/dist/safe-bash-command-file/index.js +1 -1
  319. package/dist/safe-bash-command-file/shared.js +1 -1
  320. package/dist/safe-bash-command-find/find.js +1 -1
  321. package/dist/safe-bash-command-find/index.js +1 -1
  322. package/dist/safe-bash-command-gzip/index.js +3 -2
  323. package/dist/safe-bash-command-hexdump/command.js +4 -4
  324. package/dist/safe-bash-command-hexdump/custom.d.ts +24 -0
  325. package/dist/safe-bash-command-hexdump/index.js +4 -4
  326. package/dist/safe-bash-command-hexdump/internal.d.ts +2 -0
  327. package/dist/safe-bash-command-hexdump/internal.js +1 -1
  328. package/dist/safe-bash-command-hexdump/io.js +2 -2
  329. package/dist/safe-bash-command-hexdump/options.d.ts +3 -0
  330. package/dist/safe-bash-command-hexdump/options.js +2 -2
  331. package/dist/safe-bash-command-hostname/index.js +1 -1
  332. package/dist/safe-bash-command-html-to-markdown/budget.js +1 -1
  333. package/dist/safe-bash-command-html-to-markdown/entities.js +3 -3
  334. package/dist/safe-bash-command-html-to-markdown/index.js +6 -6
  335. package/dist/safe-bash-command-html-to-markdown/input.js +5 -5
  336. package/dist/safe-bash-command-html-to-markdown/parser.d.ts +1 -0
  337. package/dist/safe-bash-command-html-to-markdown/parser.js +4 -4
  338. package/dist/safe-bash-command-html-to-markdown/render.js +5 -5
  339. package/dist/safe-bash-command-html-to-markdown/text.js +2 -2
  340. package/dist/safe-bash-command-htmlq/index.d.ts +1 -0
  341. package/dist/safe-bash-command-htmlq/index.js +27 -9
  342. package/dist/safe-bash-command-iconv/codec.js +1 -1
  343. package/dist/safe-bash-command-iconv/command.js +2 -2
  344. package/dist/safe-bash-command-iconv/index.js +2 -2
  345. package/dist/safe-bash-command-imagemagick/index.js +24 -6
  346. package/dist/safe-bash-command-join/index.js +1 -1
  347. package/dist/safe-bash-command-join/join.js +1 -1
  348. package/dist/safe-bash-command-jq/index.js +1 -1
  349. package/dist/safe-bash-command-jq/jq.js +1 -1
  350. package/dist/safe-bash-command-less/index.js +43 -28
  351. package/dist/safe-bash-command-mmdc/index.d.ts +1 -0
  352. package/dist/safe-bash-command-nl/index.js +1 -1
  353. package/dist/safe-bash-command-nl/nl.js +1 -1
  354. package/dist/safe-bash-command-numfmt/index.js +0 -11
  355. package/dist/safe-bash-command-od/index.js +101 -68
  356. package/dist/safe-bash-command-pandoc/command.js +1 -1
  357. package/dist/safe-bash-command-pandoc/index.js +1 -1
  358. package/dist/safe-bash-command-paste/index.js +1 -1
  359. package/dist/safe-bash-command-paste/paste.js +1 -1
  360. package/dist/safe-bash-command-pathchk/index.js +3 -13
  361. package/dist/safe-bash-command-pdfimages/index.js +27 -11
  362. package/dist/safe-bash-command-pdfinfo/index.js +19 -10
  363. package/dist/safe-bash-command-pdftk/index.js +3 -3
  364. package/dist/safe-bash-command-pdftoppm/index.js +26 -10
  365. package/dist/safe-bash-command-pdftotext/index.js +27 -13
  366. package/dist/safe-bash-command-qpdf/index.js +5 -5
  367. package/dist/safe-bash-command-rg/index.js +1 -1
  368. package/dist/safe-bash-command-rg/rg-command.d.ts +0 -1
  369. package/dist/safe-bash-command-rg/rg-command.js +3 -5
  370. package/dist/safe-bash-command-sed/index.js +1 -1
  371. package/dist/safe-bash-command-sed/sed.js +1 -1
  372. package/dist/safe-bash-command-shuf/options.d.ts +1 -0
  373. package/dist/safe-bash-command-shuf/options.js +2 -4
  374. package/dist/safe-bash-command-shuf/shuf.js +2 -1
  375. package/dist/safe-bash-command-soffice/index.js +20 -16
  376. package/dist/safe-bash-command-split/index.js +3 -3
  377. package/dist/safe-bash-command-split/io.js +1 -1
  378. package/dist/safe-bash-command-split/outputs.js +2 -2
  379. package/dist/safe-bash-command-split/split.js +3 -3
  380. package/dist/safe-bash-command-sqlite3/btree.d.ts +1 -0
  381. package/dist/safe-bash-command-sqlite3/engine.d.ts +6 -0
  382. package/dist/safe-bash-command-sqlite3/index.js +284 -85
  383. package/dist/safe-bash-command-ssconvert/commands.js +9 -9
  384. package/dist/safe-bash-command-ssconvert/core.js +8 -8
  385. package/dist/safe-bash-command-ssconvert/formats/csv.js +9 -9
  386. package/dist/safe-bash-command-ssconvert/formats/ods.js +8 -8
  387. package/dist/safe-bash-command-ssconvert/formats/spreadsheetml.js +2 -2
  388. package/dist/safe-bash-command-ssconvert/formats/xls.js +9 -9
  389. package/dist/safe-bash-command-ssconvert/formats/xlsx.js +8 -8
  390. package/dist/safe-bash-command-ssconvert/index.js +20 -20
  391. package/dist/safe-bash-command-tar/extract.js +1 -1
  392. package/dist/safe-bash-command-tar/index.js +5 -4
  393. package/dist/safe-bash-command-tar/modes.js +2 -2
  394. package/dist/safe-bash-command-tree/arguments.js +3 -3
  395. package/dist/safe-bash-command-tree/charset.js +1 -1
  396. package/dist/safe-bash-command-tree/index.js +4 -4
  397. package/dist/safe-bash-command-tree/io.js +1 -1
  398. package/dist/safe-bash-command-tree/pattern.js +2 -2
  399. package/dist/safe-bash-command-tree/tree.js +4 -4
  400. package/dist/safe-bash-command-unexpand/index.js +1 -1
  401. package/dist/safe-bash-command-unexpand/unexpand.js +1 -1
  402. package/dist/safe-bash-command-unrtf/index.js +14 -7
  403. package/dist/safe-bash-command-unzip/index.js +1 -1
  404. package/dist/safe-bash-command-unzip/unzip.js +1 -1
  405. package/dist/safe-bash-command-wget/index.js +1 -1
  406. package/dist/safe-bash-command-wget/wget.js +1 -1
  407. package/dist/safe-bash-command-xan/argv.d.ts +1 -1
  408. package/dist/safe-bash-command-xan/argv.js +1 -1
  409. package/dist/safe-bash-command-xan/commands.js +5 -3
  410. package/dist/safe-bash-command-xan/csv.d.ts +1 -1
  411. package/dist/safe-bash-command-xan/csv.js +1 -1
  412. package/dist/safe-bash-command-xan/index.js +7 -7
  413. package/dist/safe-bash-command-xan/io.js +3 -3
  414. package/dist/safe-bash-command-xmllint/index.js +1 -1
  415. package/dist/safe-bash-command-xxd/index.js +105 -91
  416. package/dist/safe-bash-command-xz/command.d.ts +2 -0
  417. package/dist/safe-bash-command-xz/index.d.ts +1 -1
  418. package/dist/safe-bash-command-xz/index.js +8 -0
  419. package/dist/safe-bash-command-yq/query.js +1 -1
  420. package/dist/safe-bash-command-zip/index.js +1 -1
  421. package/dist/safe-bash-command-zip/zip.js +1 -1
  422. package/dist/safe-bash-contracts/escaping.js +3 -3
  423. package/dist/safe-bash-contracts/filesystem-output.js +2 -2
  424. package/dist/safe-bash-contracts/index.d.ts +1 -0
  425. package/dist/safe-bash-contracts/index.js +7 -3
  426. package/dist/safe-bash-contracts/io.d.ts +4 -1
  427. package/dist/safe-bash-contracts/io.js +3 -1
  428. package/dist/safe-bash-contracts/managed-abort.d.ts +10 -0
  429. package/dist/safe-bash-contracts/output.js +2 -2
  430. package/dist/safe-bash-diff-engine/index.js +1 -1
  431. package/dist/safe-bash-diff-engine/shared.d.ts +3 -2
  432. package/dist/safe-bash-diff-engine/shared.js +1 -1
  433. package/dist/safe-bash-io-engine/commands/archive/internal.js +5 -23
  434. package/dist/safe-bash-io-engine/commands/search/requirements.js +2 -2
  435. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +33 -44
  436. package/dist/safe-bash-io-engine/internal.js +1 -1
  437. package/dist/safe-bash-io-engine/shell/pattern.js +1 -1
  438. package/dist/safe-bash-io-engine/shell/string-operations.js +1 -1
  439. package/dist/safe-bash-mcp/index.browser.d.ts +155 -35
  440. package/dist/safe-bash-mcp/index.browser.js +416 -0
  441. package/dist/safe-bash-mcp/index.d.ts +54 -2
  442. package/dist/safe-bash-mcp/index.js +286 -90
  443. package/dist/safe-bash-network-engine/aggregate.js +2 -2
  444. package/dist/safe-bash-network-engine/args.js +4 -4
  445. package/dist/safe-bash-network-engine/authorizer.js +1 -1
  446. package/dist/safe-bash-network-engine/body.js +6 -6
  447. package/dist/safe-bash-network-engine/decode.d.ts +1 -1
  448. package/dist/safe-bash-network-engine/decode.js +3 -4
  449. package/dist/safe-bash-network-engine/fetch-transport.js +3 -3
  450. package/dist/safe-bash-network-engine/form-content-type.js +2 -2
  451. package/dist/safe-bash-network-engine/form-headers.js +2 -2
  452. package/dist/safe-bash-network-engine/glob.js +1 -1
  453. package/dist/safe-bash-network-engine/index.js +4 -4
  454. package/dist/safe-bash-network-engine/input.js +6 -6
  455. package/dist/safe-bash-network-engine/output.js +2 -2
  456. package/dist/safe-bash-network-engine/platform-portable.js +3 -3
  457. package/dist/safe-bash-network-engine/shared.js +2 -2
  458. package/dist/safe-bash-network-engine/types.d.ts +7 -2
  459. package/dist/safe-bash-network-engine/types.js +1 -1
  460. package/dist/safe-bash-network-engine/url.js +2 -2
  461. package/dist/safe-bash-query-engine/capture.js +3 -3
  462. package/dist/safe-bash-query-engine/delpaths.js +3 -3
  463. package/dist/safe-bash-query-engine/formats.js +2 -2
  464. package/dist/safe-bash-query-engine/index.js +11 -11
  465. package/dist/safe-bash-query-engine/indices.js +3 -3
  466. package/dist/safe-bash-query-engine/input.js +1 -1
  467. package/dist/safe-bash-query-engine/interpreter.js +9 -9
  468. package/dist/safe-bash-query-engine/parser.js +1 -1
  469. package/dist/safe-bash-query-engine/query-core.js +11 -11
  470. package/dist/safe-bash-query-engine/regex.js +4 -4
  471. package/dist/safe-bash-query-engine/splits.js +5 -5
  472. package/dist/safe-bash-query-engine/values.js +2 -2
  473. package/dist/safe-bash-regex-engine/ere/matcher.js +102 -30
  474. package/dist/safe-bash-regex-engine/execution/bounded-provider.js +55 -67
  475. package/dist/safe-bash-regex-engine/execution/portable.d.ts +0 -1
  476. package/dist/safe-bash-regex-engine/execution/portable.js +6 -10
  477. package/dist/safe-bash-regex-engine/execution/protocol.d.ts +0 -5
  478. package/dist/safe-bash-regex-engine/execution/protocol.js +1 -3
  479. package/dist/safe-bash-regex-engine/index.js +6 -4
  480. package/dist/safe-bash-regex-engine/text/budget.d.ts +1 -1
  481. package/dist/safe-bash-regex-engine/text/budget.js +1 -1
  482. package/dist/safe-bash-regex-engine/text/regex.d.ts +14 -0
  483. package/dist/safe-bash-regex-engine/text/regex.js +6 -4
  484. package/dist/safe-bash-regex-engine/text/replacement-buffer.js +2 -2
  485. package/dist/safe-bash-regex-engine/text/rust-syntax.js +2 -2
  486. package/dist/safe-bash-search-engine/grep.js +189 -227
  487. package/dist/safe-bash-table-text-engine/table-text/internal.d.ts +7 -5
  488. package/dist/safe-bash-table-text-engine/table-text/internal.js +39 -21
  489. package/dist/safe-playwright-cloudflare/browser-trace-budget.js +6 -2
  490. package/dist/spreadsheet-engine/codecs/odf-hyperlinks.js +8 -2
  491. package/dist/spreadsheet-engine/formulas/functions/captured-bessel-phase.js +2 -2
  492. package/dist/spreadsheet-engine/formulas/label-references.js +54 -33
  493. package/dist/spreadsheet-engine/formulas/parser.js +3 -1
  494. package/dist/spreadsheet-engine/formulas/rewriting.js +13 -3
  495. package/dist/spreadsheet-format-xls/biff-data-tables.js +4 -6
  496. package/dist/spreadsheet-format-xls/biff-formulas.js +3 -0
  497. package/dist/spreadsheet-format-xls/biff-label-ranges.js +9 -6
  498. package/dist/spreadsheet-format-xls/biff.js +1 -1
  499. package/dist/xlsx-ast/xlsx.js +8 -5
  500. package/package.json +68 -12
  501. package/dist/safe-bash/command-chunks/chunk-KAGBORIC.js +0 -88
  502. /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);
@@ -7444,282 +7446,6 @@ export class Runtime {
7444
7446
  }
7445
7447
  }
7446
7448
  }
7447
- tryRunFastConstEchoBatch(entryCachedUnit, sourceLength, state, io) {
7448
- if (state.noexec)
7449
- return undefined;
7450
- let leadingMkdirUnit;
7451
- let leadingMkdirPaths;
7452
- let firstCachedUnit = entryCachedUnit;
7453
- let firstCc = firstCachedUnit.unit.script._fastConstEcho;
7454
- if (!firstCc) {
7455
- const nextU = entryCachedUnit.nextCached;
7456
- if (!nextU || entryCachedUnit.locale !== false || nextU.locale !== false || (entryCachedUnit.unit.script.warnings && entryCachedUnit.unit.script.warnings.length > 0))
7457
- return undefined;
7458
- firstCc = nextU.unit.script._fastConstEcho;
7459
- if (!firstCc)
7460
- return undefined;
7461
- const mScript = entryCachedUnit.unit.script;
7462
- let mPaths = mScript._cachedMkdirPPaths;
7463
- if (mPaths === undefined) {
7464
- mPaths = null;
7465
- if (mScript.lists.length === 1 && !mScript.lists[0].terminator && mScript.lists[0].pipelines.length === 1 && !mScript.lists[0].pipelines[0].negate && mScript.lists[0].pipelines[0].commands.length === 1) {
7466
- const mCmd = mScript.lists[0].pipelines[0].commands[0];
7467
- if (mCmd.kind === "simple" && mCmd.redirects.length === 0 && mCmd.words.length >= 3 && mCmd.words[0].plain === "mkdir" && mCmd.words[1].plain === "-p") {
7468
- const arr = [];
7469
- let ok = true;
7470
- for (let wi = 2; wi < mCmd.words.length; wi++) {
7471
- const wp = mCmd.words[wi].plain;
7472
- if (!wp || !isCleanAbsolutePath(wp) || wp === "/" || wp === "/dev" || wp.startsWith("/dev/")) {
7473
- ok = false;
7474
- break;
7475
- }
7476
- arr.push(wp);
7477
- }
7478
- if (ok)
7479
- mPaths = arr;
7480
- }
7481
- }
7482
- mScript._cachedMkdirPPaths = mPaths;
7483
- }
7484
- if (!mPaths)
7485
- return undefined;
7486
- leadingMkdirUnit = entryCachedUnit;
7487
- leadingMkdirPaths = mPaths;
7488
- firstCachedUnit = nextU;
7489
- }
7490
- if (this.middleware.length > 0 || io.terminal !== undefined || io.asyncDefaultInput !== undefined || io.admittedHandles !== undefined || (this._fileWrites !== undefined && this._fileWrites.size > 0) || !this._isMemoryBackingFs || !this.backingFs || !this.budget.canRedirect1 || !this.budget.hasInfiniteFsOps || (io.descriptors && (io.descriptors.size > 3 || io.descriptors.get(0)?.closed || io.descriptors.get(1)?.closed || io.descriptors.get(2)?.closed))) {
7491
- return undefined;
7492
- }
7493
- const monitor = ensureStateMonitor(state, this.budget, io[invocationScope]);
7494
- const rawState = monitor.raw;
7495
- if (!this.tryStartExtensionsSync(state) || hasActiveExtensions(rawState) || rawState.externalInvocation || hasActiveVariableAttributes(rawState) || guestArrays(state) || rawState.noclobber || rawState.readonlyVariables?.has("PIPESTATUS") || hasShellFunction(rawState, "echo") || rawState.extensions?.builtins.has("echo")) {
7496
- return undefined;
7497
- }
7498
- const def = this.commands.get("echo");
7499
- if (!def || !defaultEchoExecutors.has(def.execute))
7500
- return undefined;
7501
- const store = monitor.store;
7502
- const existing = store?.get("PIPESTATUS");
7503
- const psTarget = existing ? "indexed" : pipelineStatusTarget(rawState);
7504
- if ((psTarget !== "indexed" && psTarget !== "absent") || store?.watches.has("PIPESTATUS") || monitor.hasOverlay("PIPESTATUS"))
7505
- return undefined;
7506
- if (existing && (existing.associative || existing.values.size !== 1 || existing.maximum !== 0))
7507
- return undefined;
7508
- const elem0 = existing?.values.get(0);
7509
- if (existing && (!elem0 || elem0.text.bytes !== 1 || existing.references !== 1 || elem0.text.references !== 1))
7510
- return undefined;
7511
- const byteLength0 = firstCc.encoded.byteLength;
7512
- if ((this.budget.bytes + byteLength0 > this.budget.maxOutputBytesSmi && byteLength0 > this.budget.limits.maxOutputBytes - this.budget.bytes) || !this.budget.canFileSystemOperation() || (this.budget.commands + 1 > this.budget.maxCommandsSmi && this.budget.commands + 1 > this.budget.limits.maxCommands)) {
7513
- return undefined;
7514
- }
7515
- const umask = rawState.umask ?? 0o022;
7516
- if (leadingMkdirUnit !== undefined && leadingMkdirPaths !== undefined) {
7517
- if ((umask & 0o300) !== 0 || (this._outputFiles !== undefined && this._outputFiles.size > 0) || hasShellFunction(rawState, "mkdir") || rawState.extensions?.builtins.has("mkdir"))
7518
- return undefined;
7519
- const mkdirDef = this.commands.get("mkdir");
7520
- if (!mkdirDef || !defaultMkdirExecutors.has(mkdirDef.execute))
7521
- return undefined;
7522
- const dirMode = 0o777 & ~umask;
7523
- try {
7524
- for (let mi = 0; mi < leadingMkdirPaths.length; mi++) {
7525
- const mp = leadingMkdirPaths[mi];
7526
- if (!tryMkdirMemorySync(this.backingFs, mp, true, dirMode, this.commandSignal, firstCc.dirPrefix.startsWith(mp) && firstCc.dirPrefix.length === mp.length + 1 ? firstCc.dirPrefix : undefined))
7527
- return undefined;
7528
- this.budget.fileSystemOperation();
7529
- }
7530
- }
7531
- catch {
7532
- this.signal.throwIfAborted();
7533
- return undefined;
7534
- }
7535
- this.budget.commands++;
7536
- this.budget.parsing.admit(firstCachedUnit.unitsCharged);
7537
- }
7538
- const mode = 0o666 & ~umask;
7539
- try {
7540
- if (!tryWriteMemoryFileInDirSync(this.backingFs, firstCc.dirPrefix, firstCc.fileName, firstCc.encoded, firstCc.append, mode, this.commandSignal))
7541
- return undefined;
7542
- }
7543
- catch {
7544
- this.signal.throwIfAborted();
7545
- return undefined;
7546
- }
7547
- this.budget.tick();
7548
- this.budget.fileSystemOperation();
7549
- this.budget.bytes += byteLength0;
7550
- let lastArg = firstCc.arg0;
7551
- let cur = firstCachedUnit;
7552
- const vars = rawState.variables;
7553
- const curLocale = (vars.LC_ALL || vars.LC_CTYPE || vars.LANG) ? byteLocale(vars) : false;
7554
- const mem = this.backingFs;
7555
- let deadRmTarget;
7556
- let deadRmTargetLen = 0;
7557
- const rmDef = this.commands.get("rm");
7558
- if (mem.symlinkCount === 0 && curLocale === false && rmDef && defaultRmExecutors.has(rmDef.execute) && !hasShellFunction(rawState, "rm") && !rawState.extensions?.builtins.has("rm")) {
7559
- const cachedCc = firstCc;
7560
- let target = cachedCc._cachedRmTarget;
7561
- let scanCount = cachedCc._cachedScanCount ?? 0;
7562
- if (target === undefined) {
7563
- let scan = firstCachedUnit;
7564
- scanCount = 1;
7565
- while (scan.nextCached !== undefined && scan.nextCached.locale === false && (!scan.nextCached.unit.script.warnings || scan.nextCached.unit.script.warnings.length === 0) && scan.nextCached.unit.script._fastConstEcho !== undefined) {
7566
- scan = scan.nextCached;
7567
- scanCount++;
7568
- }
7569
- target = null;
7570
- const after = scan.nextCached;
7571
- if (after !== undefined && after.locale === false && (!after.unit.script.warnings || after.unit.script.warnings.length === 0) && after.unit.script.lists.length === 1) {
7572
- const list0 = after.unit.script.lists[0];
7573
- if (!list0.terminator && list0.pipelines.length === 1 && !list0.pipelines[0].negate && list0.pipelines[0].commands.length === 1) {
7574
- const cmd0 = list0.pipelines[0].commands[0];
7575
- if (cmd0.kind === "simple" && cmd0.redirects.length === 0 && cmd0.words.length === 3 && cmd0.words[0].plain === "rm" && (cmd0.words[1].plain === "-rf" || cmd0.words[1].plain === "-fr")) {
7576
- const t = cmd0.words[2].plain;
7577
- if (t && t.length > 1 && t.charCodeAt(0) === 47 && t.charCodeAt(t.length - 1) !== 47 && !t.includes("/."))
7578
- target = t;
7579
- }
7580
- }
7581
- }
7582
- cachedCc._cachedRmTarget = target;
7583
- cachedCc._cachedScanCount = scanCount;
7584
- }
7585
- if (target !== null && this.budget.commands + scanCount + 1 <= this.budget.maxCommandsSmi && tryGetMemoryDirectoryEntryNamesSync(this.backingFs, target)?.size === 0) {
7586
- deadRmTarget = target;
7587
- deadRmTargetLen = target.length;
7588
- }
7589
- }
7590
- const cachedBatchPlan = deadRmTarget !== undefined ? firstCc._cachedEchoBatch : undefined;
7591
- if (cachedBatchPlan !== undefined && cachedBatchPlan !== null && mem.symlinkCount === 0 && !this.signal.aborted && this.budget.bytes + cachedBatchPlan.totalBytes <= this.budget.maxOutputBytesSmi && this.budget._fileSystemOperations + cachedBatchPlan.totalCount <= this.budget.maxFileSystemOperationsSmi && this.budget.commands + cachedBatchPlan.totalCount <= this.budget.maxCommandsSmi) {
7592
- this.budget.parsing.admit(cachedBatchPlan.totalUnitsCharged);
7593
- try {
7594
- mem.writeMemoryFilesInDirBatchFast(firstCc.fileName, firstCc.dirPrefix, cachedBatchPlan.fileNames, cachedBatchPlan.nameHashes, cachedBatchPlan.payloads, cachedBatchPlan.totalNameBytes, cachedBatchPlan.payloadBytesSum, mode);
7595
- this.budget.commands += cachedBatchPlan.totalCount;
7596
- this.budget._fileSystemOperations += cachedBatchPlan.totalCount;
7597
- this.budget.bytes += cachedBatchPlan.totalBytes;
7598
- lastArg = cachedBatchPlan.lastArg;
7599
- cur = cachedBatchPlan.endUnit;
7600
- }
7601
- catch {
7602
- this.signal.throwIfAborted();
7603
- }
7604
- }
7605
- if (cur !== cachedBatchPlan?.endUnit && cur.unit.next < sourceLength && mem.symlinkCount === 0 && !this.signal.aborted) {
7606
- const buildBatchStart = cur === firstCachedUnit && deadRmTarget !== undefined && cachedBatchPlan === undefined;
7607
- let bTotalCount = 0;
7608
- let bTotalBytes = 0;
7609
- let bTotalUnits = 0;
7610
- let bTotalNameBytes = 0;
7611
- let bPayloadBytesSum = 0;
7612
- let bCanCache = buildBatchStart && !firstCc.append;
7613
- const bFileNames = bCanCache ? [] : undefined;
7614
- const bHashes = bCanCache ? [] : undefined;
7615
- const bPayloads = bCanCache ? [] : undefined;
7616
- const bSeenNames = bCanCache ? new Set([firstCc.fileName]) : undefined;
7617
- while (cur.unit.next < sourceLength && mem.symlinkCount === 0 && !this.signal.aborted) {
7618
- const next = cur.nextCached;
7619
- if (!next || next.locale !== curLocale || (next.unit.script.warnings && next.unit.script.warnings.length > 0))
7620
- break;
7621
- const nextCc = next.unit.script._fastConstEcho;
7622
- if (!nextCc)
7623
- break;
7624
- const bLen = nextCc.encoded.byteLength;
7625
- if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi || this.budget._fileSystemOperations + 1 > this.budget.maxFileSystemOperationsSmi || this.budget.commands + 1 > this.budget.maxCommandsSmi) {
7626
- break;
7627
- }
7628
- this.budget.parsing.admit(next.unitsCharged);
7629
- if (!(deadRmTarget !== undefined && nextCc.dirPrefix.length === deadRmTargetLen + 1 && nextCc.dirPrefix.charCodeAt(deadRmTargetLen) === 47 && nextCc.dirPrefix.startsWith(deadRmTarget))) {
7630
- let nameHash = nextCc._nameHash;
7631
- if (nameHash === undefined) {
7632
- const fn = nextCc.fileName;
7633
- let h = 5381;
7634
- for (let ci = 0; ci < fn.length; ci++)
7635
- h = (((h & 0x1fffff) * 33) ^ fn.charCodeAt(ci)) & 0x3fffffff;
7636
- nextCc._nameHash = nameHash = h;
7637
- }
7638
- try {
7639
- mem.writeMemoryFileInDirFast(nextCc.dirPrefix, nextCc.fileName, nextCc.encoded, nextCc.append, mode, nameHash);
7640
- }
7641
- catch {
7642
- this.signal.throwIfAborted();
7643
- break;
7644
- }
7645
- }
7646
- if (bCanCache) {
7647
- const isDeadRm = deadRmTarget !== undefined && nextCc.dirPrefix.length === deadRmTargetLen + 1 && nextCc.dirPrefix.charCodeAt(deadRmTargetLen) === 47 && nextCc.dirPrefix.startsWith(deadRmTarget);
7648
- if (isDeadRm) {
7649
- bTotalCount++;
7650
- bTotalBytes += bLen;
7651
- bTotalUnits += next.unitsCharged;
7652
- }
7653
- else if (!nextCc.append && nextCc.dirPrefix === firstCc.dirPrefix && nextCc.fileName.length <= 85 && !bSeenNames.has(nextCc.fileName)) {
7654
- bSeenNames.add(nextCc.fileName);
7655
- bFileNames.push(nextCc.fileName);
7656
- bHashes.push(nextCc._nameHash);
7657
- bPayloads.push(nextCc.encoded);
7658
- bTotalNameBytes += nextCc.fileName.length * 2;
7659
- bPayloadBytesSum += bLen;
7660
- bTotalCount++;
7661
- bTotalBytes += bLen;
7662
- bTotalUnits += next.unitsCharged;
7663
- }
7664
- else
7665
- bCanCache = false;
7666
- }
7667
- this.budget.commands++;
7668
- this.budget._fileSystemOperations++;
7669
- this.budget.bytes += bLen;
7670
- lastArg = nextCc.arg0;
7671
- cur = next;
7672
- }
7673
- if (buildBatchStart) {
7674
- firstCc._cachedEchoBatch = bCanCache && bTotalCount > 0
7675
- ? {
7676
- endUnit: cur, totalCount: bTotalCount, totalBytes: bTotalBytes, totalUnitsCharged: bTotalUnits, lastArg, fileNames: bFileNames, nameHashes: new Int32Array(bHashes), payloads: bPayloads, totalNameBytes: bTotalNameBytes, payloadBytesSum: bPayloadBytesSum,
7677
- }
7678
- : null;
7679
- }
7680
- }
7681
- if (deadRmTarget !== undefined && cur.nextCached !== undefined && !this.signal.aborted && mem.symlinkCount === 0 && (this._outputFiles === undefined || this._outputFiles.size === 0) && !hasShellFunction(rawState, "rm") && !rawState.extensions?.builtins.has("rm")) {
7682
- const rmDef = this.commands.get("rm");
7683
- const rmUnit = cur.nextCached;
7684
- const rmCmd0 = rmUnit.unit.script.lists[0]?.pipelines[0]?.commands[0];
7685
- if (rmDef && defaultRmExecutors.has(rmDef.execute) && rmCmd0 && rmCmd0.kind === "simple" && rmCmd0.words[0]?.plain === "rm" && rmCmd0.words[2]?.plain === deadRmTarget) {
7686
- let rmOk = false;
7687
- try {
7688
- rmOk = tryRmRfMemorySync(this.backingFs, deadRmTarget, this.commandSignal);
7689
- }
7690
- catch {
7691
- this.signal.throwIfAborted();
7692
- }
7693
- if (rmOk) {
7694
- this.budget.parsing.admit(rmUnit.unitsCharged);
7695
- this.budget.commands++;
7696
- this.budget._fileSystemOperations++;
7697
- lastArg = deadRmTarget;
7698
- cur = rmUnit;
7699
- }
7700
- }
7701
- }
7702
- const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
7703
- rawState.substitutionStatus = 0;
7704
- if (rawState.variables._ !== undefined)
7705
- delete rawState.variables._;
7706
- rawState.lastArgument = lastArg;
7707
- if (io.assignmentDiagnosticContext)
7708
- io.assignmentDiagnosticContext.name = undefined;
7709
- if (!existing) {
7710
- monitor.lazyPipeStatus = singleStatusZero;
7711
- monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
7712
- }
7713
- else {
7714
- elem0.text.shellValue = "0";
7715
- store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
7716
- }
7717
- rawState.status = 0;
7718
- monitor.epoch = restEpoch;
7719
- if (store)
7720
- store.epoch = restEpoch;
7721
- return cur;
7722
- }
7723
7449
  tryRunCachedSyncForScript(script, monitor, io) {
7724
7450
  const rawScript = script;
7725
7451
  let plan = rawScript._cachedSyncForScriptPlan;
@@ -7806,6 +7532,9 @@ export class Runtime {
7806
7532
  rawScript._cachedSyncForScriptPlan = plan;
7807
7533
  }
7808
7534
  const forPlan = plan.forCmd._cachedForPlan;
7535
+ // Only integer registers can skip unquoted field splitting and globbing.
7536
+ if (plan.echoVar !== undefined && (!forPlan.touchedIntNamesList.includes(plan.echoVar) || forPlan.touchedIntNamesList.includes("IFS") || (rawState.variables.IFS !== undefined && rawState.variables.IFS !== " \t\n") || plan.initAssigns.some(assignment => assignment.name === "IFS")))
7537
+ return undefined;
7809
7538
  const fastSyncSink = plan.echoVar !== undefined
7810
7539
  ? ((io.stdout instanceof BudgetedSyncSink && io.stdout.write === BudgetedSyncSink.prototype.write) || (io.stdout instanceof Capture && io.stdout.write === Capture.prototype.write) ? io.stdout : undefined)
7811
7540
  : undefined;
@@ -7813,6 +7542,10 @@ export class Runtime {
7813
7542
  const def = this.commands.get("echo");
7814
7543
  if (!fastSyncSink || !def || !defaultEchoExecutors.has(def.execute) || hasShellFunction(rawState, "echo") || rawState.extensions?.builtins.has("echo") || (io.descriptors && io.descriptors.get(1)?.output !== io.stdout))
7815
7544
  return undefined;
7545
+ // Every signed SMI plus a newline fits in 12 bytes. Admit the bound before
7546
+ // speculative arithmetic; smaller allowances use ordinary execution.
7547
+ if (this.budget.maxOutputBytesSmi - this.budget.bytes < 12)
7548
+ return undefined;
7816
7549
  }
7817
7550
  const store = monitor.store;
7818
7551
  const existing = store?.get("PIPESTATUS");
@@ -7839,36 +7572,40 @@ export class Runtime {
7839
7572
  for (const assignment of plan.initAssigns)
7840
7573
  finalValues.set(assignment.name, assignment.strVal);
7841
7574
  const regNames = forPlan.regNames;
7842
- for (let r = 1; r < regNames.length; r++) {
7843
- const refName = regNames[r];
7844
- const parsed = fastSafeInt(finalValues.get(refName) ?? rawState.variables[refName], this.budget.parsing);
7845
- if (parsed === undefined)
7846
- return undefined;
7847
- sharedLoopIntRegs[r] = parsed | 0;
7848
- }
7849
- const { ok } = runIntForLoop(forPlan.fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
7850
- if (!ok)
7851
- return undefined;
7852
- for (let r = 0; r < regNames.length; r++)
7853
- finalValues.set(regNames[r], intToStr(sharedLoopIntRegs[r]));
7575
+ const savedParseBudget = this.budget.parsing.snapshot();
7576
+ let admitted = false;
7854
7577
  let lastArg = "";
7855
- if (plan.echoVar !== undefined) {
7856
- const echoVal = finalValues.get(plan.echoVar) ?? rawState.variables[plan.echoVar] ?? "";
7857
- const ifs = finalValues.get("IFS") ?? rawState.variables.IFS;
7858
- if (ifs !== undefined && ifs !== " \t\n")
7859
- return undefined;
7860
- if (echoVal.startsWith("-") || echoVal.includes("\0"))
7861
- return undefined;
7862
- const encoded = encodeRedirectTextWithNewlineToScratch(echoVal);
7863
- if (!encoded)
7864
- return undefined;
7865
- const bLen = encoded.byteLength;
7866
- if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi)
7867
- return undefined;
7868
- if (!fastSyncSink.writeSync(encoded))
7578
+ try {
7579
+ for (let r = 1; r < regNames.length; r++) {
7580
+ const refName = regNames[r];
7581
+ const parsed = fastSafeInt(finalValues.get(refName) ?? rawState.variables[refName], this.budget.parsing);
7582
+ if (parsed === undefined)
7583
+ return undefined;
7584
+ sharedLoopIntRegs[r] = parsed | 0;
7585
+ }
7586
+ const { ok } = runIntForLoop(forPlan.fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
7587
+ if (!ok)
7869
7588
  return undefined;
7870
- this.budget.bytes += bLen;
7871
- lastArg = echoVal;
7589
+ for (const name of forPlan.touchedIntNamesList)
7590
+ finalValues.set(name, intToStr(sharedLoopIntRegs[regNames.indexOf(name)]));
7591
+ if (plan.echoVar !== undefined) {
7592
+ const echoVal = finalValues.get(plan.echoVar);
7593
+ const encoded = encodeRedirectTextWithNewlineToScratch(echoVal);
7594
+ if (!encoded)
7595
+ return undefined;
7596
+ const bLen = encoded.byteLength;
7597
+ if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi)
7598
+ return undefined;
7599
+ if (!fastSyncSink.writeSync(encoded))
7600
+ return undefined;
7601
+ this.budget.bytes += bLen;
7602
+ lastArg = echoVal;
7603
+ }
7604
+ admitted = true;
7605
+ }
7606
+ finally {
7607
+ if (!admitted)
7608
+ this.budget.parsing.restore(savedParseBudget);
7872
7609
  }
7873
7610
  for (const [name, value] of finalValues)
7874
7611
  rawState.variables[name] = value;
@@ -8058,7 +7795,7 @@ export class Runtime {
8058
7795
  const diagnosticLine = io.diagnosticCommandLines?.get(command) ?? (command.line ?? 1) + (io.diagnosticOffset ?? 0);
8059
7796
  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
7797
  w0Plain = cSingle.w0Plain;
8061
- const extD = this.getExternalCommand(w0Plain);
7798
+ const extD = this.commands.get(w0Plain);
8062
7799
  if (!extD || !builtInDirectContextExecutors.has(extD.execute) || customRegisteredCommands.has(extD.execute))
8063
7800
  return undefined;
8064
7801
  externalDef = extD;
@@ -8079,7 +7816,7 @@ export class Runtime {
8079
7816
  return undefined;
8080
7817
  }
8081
7818
  w0Plain = w0P;
8082
- const extD = this.getExternalCommand(w0Plain);
7819
+ const extD = this.commands.get(w0Plain);
8083
7820
  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
7821
  return undefined;
8085
7822
  }
@@ -8131,14 +7868,12 @@ export class Runtime {
8131
7868
  let redirectSink;
8132
7869
  if (command.redirects.length === 1) {
8133
7870
  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
- }
7871
+ let targetVal;
7872
+ try {
7873
+ targetVal = this.fastValueWord(r0.target, rawState, io, true, false, false, true, undefined, diagnosticLine);
7874
+ }
7875
+ catch {
7876
+ return undefined;
8142
7877
  }
8143
7878
  if (typeof targetVal !== "string" || !targetVal || targetVal.includes("\0"))
8144
7879
  return undefined;
@@ -8208,26 +7943,6 @@ export class Runtime {
8208
7943
  const n = pipeline.commands.length;
8209
7944
  if ((this.budget.commands + n > this.budget.maxCommandsSmi && this.budget.commands + n > this.budget.limits.maxCommands))
8210
7945
  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
7946
  for (let i = 0; i < n; i++) {
8232
7947
  const cmd = pipeline.commands[i];
8233
7948
  if (cmd.kind !== "simple" || !this.isPureExternalStageCommand(cmd, rawState) || cmd.words.length > this.budget.maxExpansionFieldsSmi)
@@ -8355,11 +8070,10 @@ export class Runtime {
8355
8070
  return undefined;
8356
8071
  }
8357
8072
  const n = pipeline.commands.length;
8358
- let firstStageRootSourceRef;
8359
8073
  for (let i = 0; i < n; i++) {
8360
8074
  const cmd = pipeline.commands[i];
8361
8075
  const name = cmd.words[0].plain;
8362
- const extDef = this.getExternalCommand(name);
8076
+ const extDef = this.commands.get(name);
8363
8077
  if (!extDef || !builtInDirectContextExecutors.has(extDef.execute) || customRegisteredCommands.has(extDef.execute)) {
8364
8078
  return undefined;
8365
8079
  }
@@ -8387,8 +8101,6 @@ export class Runtime {
8387
8101
  const rootEntry = backing.root?.entries?.get(slice1);
8388
8102
  if (!rootEntry || rootEntry.type !== "file" || (rootEntry.data && rootEntry.data.byteLength > 65536))
8389
8103
  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
8104
  }
8393
8105
  }
8394
8106
  else if (name === "find") {
@@ -8436,23 +8148,8 @@ export class Runtime {
8436
8148
  return undefined;
8437
8149
  }
8438
8150
  }
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
- }
8151
+ const sharedSyncPipeBuf0 = new Uint8Array(65536);
8152
+ const sharedSyncPipeBuf1 = new Uint8Array(65536);
8456
8153
  syncPurePipelineSlotInUse = true;
8457
8154
  this.budget.enterPipelineStages(n);
8458
8155
  this.budget.commands += n;
@@ -8463,7 +8160,7 @@ export class Runtime {
8463
8160
  for (let index = start; index < n; index++) {
8464
8161
  const cmd = pipeline.commands[index];
8465
8162
  const firstName = cmd.words[0].plain;
8466
- const extDef = this.getExternalCommand(firstName);
8163
+ const extDef = this.commands.get(firstName);
8467
8164
  const stageArgs = cmd._cachedPlainArgs;
8468
8165
  const isFirst = index === 0;
8469
8166
  const isLast = index === n - 1;
@@ -8534,22 +8231,7 @@ export class Runtime {
8534
8231
  syncPurePipelineSlotInUse = false;
8535
8232
  this.budget.leavePipelineStages(n);
8536
8233
  };
8537
- const stdout = io.stdout;
8538
- const stderr = io.stderr;
8539
8234
  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
8235
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
8554
8236
  const finalStatuses = statuses ?? ZERO_PIPE_STATUSES[n] ?? new Array(n).fill(0);
8555
8237
  monitor.lazyPipeStatus = finalStatuses;
@@ -8611,7 +8293,7 @@ export class Runtime {
8611
8293
  for (let index = 0; index < n; index++) {
8612
8294
  const cmd = pipeline.commands[index];
8613
8295
  const firstName = cmd.words[0].plain;
8614
- const extDef = this.getExternalCommand(firstName);
8296
+ const extDef = this.commands.get(firstName);
8615
8297
  let stageArgs = cmd._cachedPlainArgs;
8616
8298
  if (!stageArgs) {
8617
8299
  stageArgs = new Array(cmd.words.length - 1);
@@ -9915,7 +9597,7 @@ export class Runtime {
9915
9597
  // Loops and pure substitutions cannot replay after an unsupported result.
9916
9598
  // These operators depend on arithmetic, filesystem or collation state that
9917
9599
  // the speculative synchronous evaluator does not fully support.
9918
- if (requireTotal && ((expr.kind === "unary" && syncConditionalFileUnaryOps.has(expr.operator)) ||
9600
+ if (requireTotal && ((expr.kind === "unary" && (expr.operator === "-v" || syncConditionalFileUnaryOps.has(expr.operator))) ||
9919
9601
  (expr.kind === "binary" && expr.operator !== "==" && expr.operator !== "=" && expr.operator !== "!=" && expr.operator !== "=~")))
9920
9602
  return false;
9921
9603
  const okWord = (w) => !Runtime.wordMayMutate(w) || (rawState !== undefined && this.isPureSyncValueWord(w, rawState));
@@ -10518,7 +10200,7 @@ export class Runtime {
10518
10200
  const rhsOp = scalarMutMatch[4];
10519
10201
  const rhs2 = scalarMutMatch[5] !== undefined ? Number(scalarMutMatch[5]) : 0;
10520
10202
  const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
10521
- if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
10203
+ if (!controlNames.has(varName) && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
10522
10204
  const curVal = (this._syncArithRawWriteOnly && this._syncArithTouched?.has(varName))
10523
10205
  ? (rawState.variables[varName] ?? "0")
10524
10206
  : (monitor.values.get(varName, rawState.variables[varName] ?? "0") ?? rawState.variables[varName] ?? "0");
@@ -10787,7 +10469,7 @@ export class Runtime {
10787
10469
  const clause = command.clauses[cIdx];
10788
10470
  for (let pIdx = 0; pIdx < clause.patterns.length; pIdx++) {
10789
10471
  const pw = clause.patterns[pIdx];
10790
- const pStr = pw.plain ?? this.tryBuildSyncPatternWord(pw, rawState, io, diagnosticLine);
10472
+ const pStr = this.tryBuildSyncPatternWord(pw, rawState, io, diagnosticLine);
10791
10473
  if (pStr === undefined)
10792
10474
  return undefined;
10793
10475
  const matched = tryMatchesPatternSync(pStr, fastSubject, work, false, false);
@@ -12549,7 +12231,7 @@ export class Runtime {
12549
12231
  allArrOk = false;
12550
12232
  break;
12551
12233
  }
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") {
12234
+ 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
12235
  ops.push({ kind: "scalar", targetName: tExpanded });
12554
12236
  continue;
12555
12237
  }
@@ -12629,7 +12311,7 @@ export class Runtime {
12629
12311
  for (let ui = uStart; ui < command.words.length; ui++) {
12630
12312
  const targetName = command.words[ui].plain;
12631
12313
  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") {
12314
+ 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
12315
  targets.push(targetName);
12634
12316
  }
12635
12317
  else {
@@ -14202,7 +13884,7 @@ export class Runtime {
14202
13884
  // Unsubscripted array references expand element zero through the normal
14203
13885
  // evaluator. fastValueWord cannot guarantee that expansion throughout
14204
13886
  // a loop, so reject it before executing any loop effects.
14205
- if (stateMonitor(rawState)?.store?.get(part.name))
13887
+ if (part.name === "RANDOM" || part.name === "SECONDS" || stateMonitor(rawState)?.store?.get(part.name))
14206
13888
  return false;
14207
13889
  // These expansions can require multiple fields or asynchronous quoting
14208
13890
  // as loop state changes. Decide before the loop produces any effects.
@@ -14330,125 +14012,8 @@ export class Runtime {
14330
14012
  return false;
14331
14013
  if (this.tryAdmitLoopInvariantSubstitution(part, rawState))
14332
14014
  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;
14015
+ // Dynamic substitutions execute at the committed expansion boundary.
14016
+ return false;
14452
14017
  }
14453
14018
  return false;
14454
14019
  }
@@ -14521,7 +14086,7 @@ export class Runtime {
14521
14086
  };
14522
14087
  const safeArgWord = (w, numeric = false) => (!checkIntVars || this.isPureSyncValueWord(w, rawState)) &&
14523
14088
  (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)))));
14089
+ (numeric && ((!checkIntVars && w.parts.length === 1 && w.parts[0].kind === "variable") || (checkIntVars && (rawState.variables.IFS === undefined || rawState.variables.IFS === " \t\n") && isGuaranteedIntWord(w)))));
14525
14090
  if (args.length === 2) {
14526
14091
  const op = args[0].plain;
14527
14092
  if ((op === "-n" || op === "-z") && safeArgWord(args[1])) {
@@ -15034,7 +14599,7 @@ export class Runtime {
15034
14599
  for (const cl of cmd.clauses) {
15035
14600
  if (cl.terminator !== ";;" && cl.terminator !== "esac")
15036
14601
  return false;
15037
- if (!cl.patterns.every(pw => pw.plain !== undefined && tryMatchesPatternSync(pw.plain, "", work, false, false) !== undefined))
14602
+ if (!cl.patterns.every(pw => pw.plain !== undefined && !pw.plain.startsWith("~") && tryMatchesPatternSync(pw.plain, "", work, false, false) !== undefined))
15038
14603
  return false;
15039
14604
  if (!isSimpleEchoOrPrintf(cl.body))
15040
14605
  return false;
@@ -15137,7 +14702,7 @@ export class Runtime {
15137
14702
  return false;
15138
14703
  if (pw.plain === undefined && !pw.parts.every(p => p.quoted))
15139
14704
  return false;
15140
- const pattern = pw.plain ?? (io ? this.tryBuildSyncPatternWord(pw, rawState, io) : undefined);
14705
+ const pattern = (io ? this.tryBuildSyncPatternWord(pw, rawState, io) : (pw.plain?.startsWith("~") ? undefined : pw.plain));
15141
14706
  return pattern !== undefined && tryMatchesPatternSync(pattern, "", work, false, false) !== undefined;
15142
14707
  })) {
15143
14708
  caseOk = false;
@@ -15760,7 +15325,14 @@ export class Runtime {
15760
15325
  for (let b = 0; b + 1 < bodyAssignments.length; b++) {
15761
15326
  const curr = bodyAssignments[b];
15762
15327
  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)) {
15328
+ // The first echo must finish before a dependent command or $? expansion.
15329
+ if (curr.listOperator === undefined && next.listOperator === undefined &&
15330
+ curr.targetWord !== undefined && curr.value !== undefined &&
15331
+ this.isSimpleRedirectEchoWord(curr.value) && !curr.append &&
15332
+ next.targetWord !== undefined && next.value !== undefined &&
15333
+ this.isSimpleRedirectEchoWord(next.value) && next.append &&
15334
+ sameRedirectTargetWord(curr.targetWord, next.targetWord) &&
15335
+ [next.value, next.targetWord].every(word => word.parts.every(part => part.kind !== "variable" || part.name !== "?"))) {
15764
15336
  curr.coalesceNext = true;
15765
15337
  b++;
15766
15338
  }
@@ -15835,26 +15407,33 @@ export class Runtime {
15835
15407
  return undefined;
15836
15408
  }
15837
15409
  const regNames = forPlan.regNames;
15410
+ for (const refName of regNames) {
15411
+ if (store?.get(refName) || store?.watches.has(refName) || monitor.hasOverlay(refName) || rawState.variableAttributes?.has(refName))
15412
+ return undefined;
15413
+ }
15414
+ const intBudgetSnapshot = this.budget.parsing.snapshot();
15838
15415
  for (let r = 0; r < regNames.length; r++) {
15839
15416
  const refName = regNames[r];
15840
- if (store?.get(refName))
15841
- return undefined;
15842
15417
  if (r > 0) {
15843
15418
  const parsed = fastSafeInt(rawState.variables[refName], this.budget.parsing);
15844
- if (parsed === undefined)
15419
+ if (parsed === undefined) {
15420
+ this.budget.parsing.restore(intBudgetSnapshot);
15845
15421
  return undefined;
15422
+ }
15846
15423
  sharedLoopIntRegs[r] = parsed | 0;
15847
15424
  }
15848
15425
  }
15849
- monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets);
15850
- this.budget.tick();
15851
15426
  const { ok } = runIntForLoop(fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
15852
- if (!ok)
15427
+ if (!ok) {
15428
+ this.budget.parsing.restore(intBudgetSnapshot);
15853
15429
  return undefined;
15430
+ }
15431
+ monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets);
15432
+ this.budget.tick();
15854
15433
  this.budget.iterations += wordCount;
15855
15434
  this.budget.commands += wordCount * forPlan.bodyStepCount;
15856
- for (let r = 0; r < regNames.length; r++) {
15857
- rawState.variables[regNames[r]] = intToStr(sharedLoopIntRegs[r]);
15435
+ for (const name of forPlan.touchedIntNamesList) {
15436
+ rawState.variables[name] = intToStr(sharedLoopIntRegs[regNames.indexOf(name)]);
15858
15437
  }
15859
15438
  const touchedList = forPlan.touchedIntNamesList;
15860
15439
  for (let t = 0; t < touchedList.length; t++) {
@@ -16017,6 +15596,7 @@ export class Runtime {
16017
15596
  touched.clear();
16018
15597
  let lastCmd;
16019
15598
  let lastArg = "";
15599
+ let lastPipelineStatus;
16020
15600
  const mode = 0o666 & ~(rawState.umask ?? 0o022);
16021
15601
  if (command.kind === "arithmetic-for") {
16022
15602
  let plan = command._cachedArithPlan;
@@ -16354,6 +15934,8 @@ export class Runtime {
16354
15934
  canUseIntRegisters = false;
16355
15935
  else {
16356
15936
  usedFastIntPath = true;
15937
+ if (iterations > 0)
15938
+ lastPipelineStatus = 0;
16357
15939
  this.budget.parsing.admit(limitVal < 0 ? 4 : 2);
16358
15940
  this.budget.iterations += iterations + 1;
16359
15941
  this.budget.commands += iterations * bodyAssignments.length + subCount;
@@ -16384,6 +15966,7 @@ export class Runtime {
16384
15966
  loopStatus = rawState.status;
16385
15967
  lastCmd = fb.lastCmd;
16386
15968
  lastArg = fb.lastArg;
15969
+ lastPipelineStatus = fb.pipelineStatus;
16387
15970
  lastInductionVal = fb.lastInductionVal;
16388
15971
  }
16389
15972
  finally {
@@ -16463,12 +16046,14 @@ export class Runtime {
16463
16046
  rawState.lastArgument = lastArg;
16464
16047
  if (io.assignmentDiagnosticContext)
16465
16048
  io.assignmentDiagnosticContext.name = undefined;
16049
+ }
16050
+ if (lastPipelineStatus !== undefined) {
16466
16051
  if (!existing) {
16467
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
16052
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
16468
16053
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
16469
16054
  }
16470
16055
  else {
16471
- this.setSyncPipeStatusCell(existing, String(loopStatus));
16056
+ this.setSyncPipeStatusCell(existing, String(lastPipelineStatus));
16472
16057
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
16473
16058
  }
16474
16059
  }
@@ -16486,6 +16071,8 @@ export class Runtime {
16486
16071
  if (cp.negate || cp.commands.length !== 1)
16487
16072
  return undefined;
16488
16073
  const condCmd = cp.commands[0];
16074
+ if (condCmd.kind !== "simple" && condCmd.kind !== "arithmetic" && condCmd.kind !== "conditional")
16075
+ return undefined;
16489
16076
  let whileArithProg;
16490
16077
  let whileCondExpr;
16491
16078
  let whileReadSpec;
@@ -16714,6 +16301,7 @@ export class Runtime {
16714
16301
  this._syncArithTouched = touched;
16715
16302
  const condLine = io.diagnosticCommandLines?.get(condCmd) ?? (condCmd.line ?? diagnosticLine) + (io.diagnosticOffset ?? 0);
16716
16303
  let loopStatus = 0;
16304
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
16717
16305
  let iterCount = 0;
16718
16306
  try {
16719
16307
  if (whileReadSpec !== undefined && syncReadInputText !== undefined) {
@@ -16779,8 +16367,9 @@ export class Runtime {
16779
16367
  rawState.variables[vn] = "";
16780
16368
  touched.add(vn);
16781
16369
  }
16782
- lastCmd = rCmd;
16783
- lastArg = rLastArg;
16370
+ progress.lastCmd = rCmd;
16371
+ progress.lastArg = rLastArg;
16372
+ progress.pipelineStatus = 1;
16784
16373
  break;
16785
16374
  }
16786
16375
  const nlIdx = syncReadInputText.indexOf(readDelim, cursor);
@@ -16788,19 +16377,23 @@ export class Runtime {
16788
16377
  const partialLine = syncReadInputText.slice(cursor);
16789
16378
  cursor = textLen;
16790
16379
  splitSyncReadLine(partialLine, readIfs);
16791
- lastCmd = rCmd;
16792
- lastArg = rLastArg;
16380
+ progress.lastCmd = rCmd;
16381
+ progress.lastArg = rLastArg;
16382
+ progress.pipelineStatus = 1;
16793
16383
  break;
16794
16384
  }
16795
16385
  const lineStr = syncReadInputText.slice(cursor, nlIdx);
16796
16386
  cursor = nlIdx + 1;
16797
16387
  splitSyncReadLine(lineStr, readIfs);
16388
+ progress.lastCmd = rCmd;
16389
+ progress.lastArg = rLastArg;
16390
+ progress.pipelineStatus = 0;
16798
16391
  rawState.status = 0;
16799
16392
  ++iterCount;
16800
16393
  this.budget.loop();
16801
16394
  if ((iterCount & 127) === 0)
16802
16395
  runYieldCheckpoint(this.signal);
16803
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16396
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16804
16397
  loopStatus = rawState.status;
16805
16398
  if (this._syncLoopAction !== undefined) {
16806
16399
  const act = this._syncLoopAction;
@@ -16831,8 +16424,9 @@ export class Runtime {
16831
16424
  }
16832
16425
  rawState.variables[whileGetoptsSpec.optVar] = res.option;
16833
16426
  touched.add(whileGetoptsSpec.optVar);
16834
- lastCmd = whileGetoptsSpec.getoptsCmd;
16835
- lastArg = whileGetoptsSpec.cmdLastArg;
16427
+ progress.lastCmd = whileGetoptsSpec.getoptsCmd;
16428
+ progress.lastArg = whileGetoptsSpec.cmdLastArg;
16429
+ progress.pipelineStatus = res.status;
16836
16430
  if (res.status !== 0)
16837
16431
  break;
16838
16432
  rawState.status = 0;
@@ -16840,7 +16434,7 @@ export class Runtime {
16840
16434
  this.budget.loop();
16841
16435
  if ((iterCount & 127) === 0)
16842
16436
  runYieldCheckpoint(this.signal);
16843
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16437
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16844
16438
  loopStatus = rawState.status;
16845
16439
  if (this._syncLoopAction !== undefined) {
16846
16440
  const act = this._syncLoopAction;
@@ -16856,18 +16450,18 @@ export class Runtime {
16856
16450
  const condNonZero = whileCondExpr !== undefined
16857
16451
  ? (this.tryEvalConditionalSync(whileCondExpr, rawState, monitor, store, io, condLine) ?? 1) === 0
16858
16452
  : 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
- }
16453
+ progress.lastCmd = condCmd;
16454
+ if (condCmd.kind === "simple")
16455
+ progress.lastArg = this.fastValueWord(condCmd.words[condCmd.words.length - 1], rawState, io, false, false, false, true);
16863
16456
  rawState.status = condNonZero ? 0 : 1;
16457
+ progress.pipelineStatus = rawState.status;
16864
16458
  if (condNonZero !== (command.kind === "while"))
16865
16459
  break;
16866
16460
  ++iterCount;
16867
16461
  this.budget.loop();
16868
16462
  if ((iterCount & 127) === 0)
16869
16463
  runYieldCheckpoint(this.signal);
16870
- this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, v => { lastCmd = v.lastCmd; lastArg = v.lastArg; });
16464
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
16871
16465
  loopStatus = rawState.status;
16872
16466
  if (this._syncLoopAction !== undefined) {
16873
16467
  const act = this._syncLoopAction;
@@ -16898,6 +16492,9 @@ export class Runtime {
16898
16492
  }
16899
16493
  }
16900
16494
  }
16495
+ lastCmd = progress.lastCmd;
16496
+ lastArg = progress.lastArg;
16497
+ lastPipelineStatus = progress.pipelineStatus;
16901
16498
  if (lastCmd) {
16902
16499
  if (rawState.extensions && !rawState.extensions.eventDepth)
16903
16500
  publishCommandSpelling(rawState, commandSpelling(lastCmd));
@@ -16907,9 +16504,11 @@ export class Runtime {
16907
16504
  rawState.lastArgument = lastArg;
16908
16505
  if (io.assignmentDiagnosticContext)
16909
16506
  io.assignmentDiagnosticContext.name = undefined;
16910
- const statusStr = loopStatus === 0 ? "0" : String(loopStatus);
16507
+ }
16508
+ if (lastPipelineStatus !== undefined) {
16509
+ const statusStr = String(lastPipelineStatus);
16911
16510
  if (!existing) {
16912
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
16511
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
16913
16512
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
16914
16513
  }
16915
16514
  else {
@@ -17204,6 +16803,8 @@ export class Runtime {
17204
16803
  canUseIntRegisters = false;
17205
16804
  else {
17206
16805
  usedFastIntFor = true;
16806
+ if (fastLoopWords.length > 0)
16807
+ lastPipelineStatus = 0;
17207
16808
  lastCmd = bodyAssignments[bodyAssignments.length - 1]?.cmd;
17208
16809
  this.budget.iterations += fastLoopWords.length;
17209
16810
  this.budget.commands += fastLoopWords.length * bodyAssignments.length + subCount;
@@ -17216,8 +16817,8 @@ export class Runtime {
17216
16817
  rawState.status = 0;
17217
16818
  }
17218
16819
  runYieldCheckpoint(this.signal);
17219
- for (let r = 0; r < regNames.length; r++) {
17220
- rawState.variables[regNames[r]] = intToStr(sharedLoopIntRegs[r]);
16820
+ for (const name of forPlan.touchedIntNamesList) {
16821
+ rawState.variables[name] = intToStr(sharedLoopIntRegs[regNames.indexOf(name)]);
17221
16822
  }
17222
16823
  regNames.length = 0;
17223
16824
  }
@@ -17234,6 +16835,7 @@ export class Runtime {
17234
16835
  loopStatus = fastLoopWords.length === 0 ? 0 : rawState.status;
17235
16836
  lastCmd = fb.lastCmd;
17236
16837
  lastArg = fb.lastArg;
16838
+ lastPipelineStatus = fb.pipelineStatus;
17237
16839
  }
17238
16840
  finally {
17239
16841
  this._syncReturnDepth--;
@@ -17282,12 +16884,14 @@ export class Runtime {
17282
16884
  rawState.lastArgument = lastArg;
17283
16885
  if (io.assignmentDiagnosticContext)
17284
16886
  io.assignmentDiagnosticContext.name = undefined;
16887
+ }
16888
+ if (lastPipelineStatus !== undefined) {
17285
16889
  if (!existing) {
17286
- monitor.lazyPipeStatus = loopStatus === 0 ? singleStatusZero : [loopStatus];
16890
+ monitor.lazyPipeStatus = lastPipelineStatus === 0 ? singleStatusZero : [lastPipelineStatus];
17287
16891
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
17288
16892
  }
17289
16893
  else {
17290
- this.setSyncPipeStatusCell(existing, String(loopStatus));
16894
+ this.setSyncPipeStatusCell(existing, String(lastPipelineStatus));
17291
16895
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
17292
16896
  }
17293
16897
  }
@@ -17912,8 +17516,7 @@ export class Runtime {
17912
17516
  }
17913
17517
  runSyncArithForFallback(e0, e1, e2, inductionName, hasDeferredSteps, deferredMask, bodyAssignments, rawState, io, monitor, touched, mode, diagnosticLine) {
17914
17518
  let enteredBody = false;
17915
- let lastCmd;
17916
- let lastArg = rawState.lastArgument ?? "";
17519
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
17917
17520
  let lastInductionVal;
17918
17521
  touched.add(inductionName);
17919
17522
  this.syncShellArithmeticNonZero(e0, rawState, diagnosticLine);
@@ -17927,160 +17530,7 @@ export class Runtime {
17927
17530
  enteredBody = true;
17928
17531
  if (hasDeferredSteps)
17929
17532
  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
- }
17533
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress, deferredMask);
18084
17534
  if (this._syncLoopAction !== undefined) {
18085
17535
  const act = this._syncLoopAction;
18086
17536
  this._syncLoopAction = undefined;
@@ -18092,7 +17542,7 @@ export class Runtime {
18092
17542
  this.flushSyncStdoutBatch(io);
18093
17543
  if (!enteredBody)
18094
17544
  rawState.status = 0;
18095
- return { lastCmd, lastArg, lastInductionVal };
17545
+ return { ...progress, lastInductionVal };
18096
17546
  }
18097
17547
  _syncLoopFnCheckDepth = 0;
18098
17548
  canSyncReadOnlyArraySubscripts(tree, rawState) {
@@ -18295,7 +17745,7 @@ export class Runtime {
18295
17745
  rawState.positional = savedPos;
18296
17746
  }
18297
17747
  }
18298
- execSyncFnStep(step, rawState, io, monitor, touched, mode, onUpdate) {
17748
+ execSyncFnStep(step, rawState, io, monitor, touched, mode, progress) {
18299
17749
  const fnCall = step.fnCall;
18300
17750
  const fnArgs = [];
18301
17751
  for (let i = 0; i < fnCall.argWords.length; i++) {
@@ -18336,13 +17786,15 @@ export class Runtime {
18336
17786
  }
18337
17787
  }
18338
17788
  if (fnCall.steps.length > 0) {
18339
- this.execSyncLoopSteps(fnCall.steps, rawState, io, monitor, touched, mode, onUpdate);
17789
+ this.execSyncLoopSteps(fnCall.steps, rawState, io, monitor, touched, mode, progress);
18340
17790
  }
18341
17791
  else {
18342
17792
  rawState.status = 0;
18343
17793
  }
18344
17794
  rawState.lastArgument = fnArgs.at(-1) ?? fnCall.name;
18345
- onUpdate({ lastCmd: step.cmd, lastArg: rawState.lastArgument });
17795
+ progress.lastCmd = step.cmd;
17796
+ progress.lastArg = rawState.lastArgument;
17797
+ progress.pipelineStatus = rawState.status;
18346
17798
  }
18347
17799
  finally {
18348
17800
  for (let i = savedLocals.length - 1; i >= 0; i--) {
@@ -18362,16 +17814,10 @@ export class Runtime {
18362
17814
  this._fastSubPositional = prevFastSubPos;
18363
17815
  }
18364
17816
  }
18365
- execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, onUpdate) {
17817
+ execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, progress) {
18366
17818
  const nl = step.nestedLoop;
18367
17819
  const lc = nl.loopCmd;
18368
- let innerLastCmd;
18369
- let innerLastArg = "";
18370
17820
  let innerStatus = 0;
18371
- const updateInner = (v) => {
18372
- innerLastCmd = v.lastCmd;
18373
- innerLastArg = v.lastArg;
18374
- };
18375
17821
  rawState.loopDepth++;
18376
17822
  try {
18377
17823
  if (lc.kind === "arithmetic-for") {
@@ -18385,7 +17831,7 @@ export class Runtime {
18385
17831
  this.budget.loop();
18386
17832
  if ((++turn & 127) === 0)
18387
17833
  runYieldCheckpoint(this.signal);
18388
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
17834
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18389
17835
  innerStatus = rawState.status;
18390
17836
  if (this._syncLoopAction !== undefined) {
18391
17837
  const act = this._syncLoopAction;
@@ -18406,7 +17852,7 @@ export class Runtime {
18406
17852
  if ((++turn & 127) === 0)
18407
17853
  runYieldCheckpoint(this.signal);
18408
17854
  rawState.variables[lc.name] = words[i];
18409
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
17855
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18410
17856
  innerStatus = rawState.status;
18411
17857
  if (this._syncLoopAction !== undefined) {
18412
17858
  const act = this._syncLoopAction;
@@ -18423,17 +17869,17 @@ export class Runtime {
18423
17869
  const condOk = nl.condExpr !== undefined
18424
17870
  ? (this.tryEvalConditionalSync(nl.condExpr, rawState, monitor, arrayStore(rawState), io, nl.condLine) ?? 1) === 0
18425
17871
  : 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
- }
17872
+ progress.lastCmd = nl.condCmd;
17873
+ if (nl.condCmd?.kind === "simple")
17874
+ progress.lastArg = this.fastValueWord(nl.condCmd.words[nl.condCmd.words.length - 1], rawState, io, false, false, false, true);
18430
17875
  rawState.status = condOk ? 0 : 1;
17876
+ progress.pipelineStatus = rawState.status;
18431
17877
  if (condOk !== (lc.kind === "while"))
18432
17878
  break;
18433
17879
  this.budget.loop();
18434
17880
  if ((++turn & 127) === 0)
18435
17881
  runYieldCheckpoint(this.signal);
18436
- this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, updateInner);
17882
+ this.execSyncLoopSteps(nl.steps, rawState, io, monitor, touched, mode, progress);
18437
17883
  innerStatus = rawState.status;
18438
17884
  if (this._syncLoopAction !== undefined) {
18439
17885
  const act = this._syncLoopAction;
@@ -18448,17 +17894,15 @@ export class Runtime {
18448
17894
  rawState.loopDepth--;
18449
17895
  }
18450
17896
  rawState.status = innerStatus;
18451
- if (innerLastCmd)
18452
- onUpdate({ lastCmd: innerLastCmd, lastArg: innerLastArg });
18453
17897
  }
18454
- execSyncCaseStep(step, rawState, io, monitor, touched, mode, onUpdate) {
17898
+ execSyncCaseStep(step, rawState, io, monitor, touched, mode, progress) {
18455
17899
  const subj = this.fastValueWord(step.caseSubject, rawState, io, false, false, false, false, 0, step.line);
18456
17900
  const work = { remaining: this.budget.limits.maxExpansionBytes, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
18457
17901
  let chosen;
18458
17902
  for (let ci = 0; ci < step.caseClauses.length; ci++) {
18459
17903
  const cl = step.caseClauses[ci];
18460
17904
  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);
17905
+ const pattern = this.tryBuildSyncPatternWord(cl.patterns[pi], rawState, io, step.line);
18462
17906
  if (pattern !== undefined && tryMatchesPatternSync(pattern, subj, work, false, false)) {
18463
17907
  chosen = cl.steps;
18464
17908
  break;
@@ -18471,10 +17915,10 @@ export class Runtime {
18471
17915
  rawState.status = 0;
18472
17916
  }
18473
17917
  else {
18474
- this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, onUpdate);
17918
+ this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, progress);
18475
17919
  }
18476
17920
  }
18477
- execSyncIfStep(step, rawState, io, monitor, touched, mode, onUpdate) {
17921
+ execSyncIfStep(step, rawState, io, monitor, touched, mode, progress) {
18478
17922
  let chosen;
18479
17923
  for (let bi = 0; bi < step.ifBranches.length; bi++) {
18480
17924
  const br = step.ifBranches[bi];
@@ -18482,9 +17926,11 @@ export class Runtime {
18482
17926
  const condOk = br.condExpr !== undefined
18483
17927
  ? (this.tryEvalConditionalSync(br.condExpr, rawState, monitor, arrayStore(rawState), io, br.condLine) ?? 1) === 0
18484
17928
  : this.evalSyncLoopArithStmt(br.cond, rawState, io, touched, br.condLine);
17929
+ progress.lastCmd = br.condCmd;
18485
17930
  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) });
17931
+ progress.lastArg = this.fastValueWord(br.condCmd.words[br.condCmd.words.length - 1], rawState, io, false, false, false, true);
18487
17932
  rawState.status = condOk ? 0 : 1;
17933
+ progress.pipelineStatus = rawState.status;
18488
17934
  if (condOk) {
18489
17935
  chosen = br.steps;
18490
17936
  break;
@@ -18496,83 +17942,63 @@ export class Runtime {
18496
17942
  rawState.status = 0;
18497
17943
  }
18498
17944
  else {
18499
- this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, onUpdate);
17945
+ this.execSyncLoopSteps(chosen, rawState, io, monitor, touched, mode, progress);
18500
17946
  }
18501
17947
  }
18502
- execSyncLoopSteps(steps, rawState, io, monitor, touched, mode, onUpdate) {
18503
- let lastCmd;
18504
- let lastArg = rawState.lastArgument ?? "";
17948
+ execSyncLoopSteps(steps, rawState, io, monitor, touched, mode, progress, deferredMask = 0) {
18505
17949
  for (let b = 0; b < steps.length; b++) {
18506
17950
  const step = steps[b];
18507
17951
  if (step.listOperator !== undefined && ((step.listOperator === "&&" && rawState.status !== 0) || (step.listOperator === "||" && rawState.status === 0)))
18508
17952
  continue;
18509
- if (step.caseClauses === undefined && step.ifBranches === undefined && step.nestedLoop === undefined)
18510
- lastCmd = step.cmd;
18511
17953
  this.budget.tick();
17954
+ // Compound commands return their body's status, but only executed pipelines
17955
+ // update PIPESTATUS. Share progress so empty branches and loops preserve it.
17956
+ if (step.nestedLoop !== undefined || step.fnCall !== undefined || step.caseClauses !== undefined || step.ifBranches !== undefined) {
17957
+ this.flushSyncStdoutBatch(io);
17958
+ if (step.nestedLoop !== undefined)
17959
+ this.execSyncNestedLoopStep(step, rawState, io, monitor, touched, mode, progress);
17960
+ else if (step.fnCall !== undefined)
17961
+ this.execSyncFnStep(step, rawState, io, monitor, touched, mode, progress);
17962
+ else if (step.caseClauses !== undefined)
17963
+ this.execSyncCaseStep(step, rawState, io, monitor, touched, mode, progress);
17964
+ else
17965
+ this.execSyncIfStep(step, rawState, io, monitor, touched, mode, progress);
17966
+ if (this._syncLoopAction !== undefined)
17967
+ break;
17968
+ continue;
17969
+ }
17970
+ progress.lastCmd = step.cmd;
17971
+ let status = 0;
18512
17972
  if (step.loopAction !== undefined) {
18513
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
18514
- rawState.status = 0;
17973
+ progress.lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
18515
17974
  this._syncLoopAction = step.loopAction;
18516
- onUpdate({ lastCmd, lastArg });
18517
- break;
18518
17975
  }
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 });
18529
- continue;
17976
+ else if (step.unsetVars !== undefined) {
17977
+ progress.lastArg = this.execSyncUnsetStep(step, rawState, monitor, touched);
18530
17978
  }
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;
17979
+ else if (step.localDecl !== undefined) {
17980
+ progress.lastArg = this.execSyncLocalDeclStep(step.localDecl, rawState, io, monitor, touched, step.line);
18537
17981
  }
18538
- if (step.readHereString !== undefined) {
18539
- lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
18540
- onUpdate({ lastCmd, lastArg });
18541
- continue;
17982
+ else if (step.shiftCount !== undefined) {
17983
+ const result = this.execSyncShiftStep(step.shiftCount, step.cmd, rawState);
17984
+ progress.lastArg = result.lastArg;
17985
+ status = result.status;
18542
17986
  }
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;
17987
+ else if (step.readHereString !== undefined) {
17988
+ progress.lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
17989
+ status = rawState.status;
18546
17990
  }
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;
18550
- }
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;
18556
- }
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;
17991
+ else if (deferredMask & (1 << b)) {
17992
+ progress.lastArg = "";
18562
17993
  }
18563
17994
  else if (step.condStmt !== undefined) {
18564
- const cStatus = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
17995
+ status = this.tryEvalConditionalSync(step.condStmt, rawState, monitor, arrayStore(rawState), io, step.line) ?? 1;
18565
17996
  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 });
17997
+ progress.lastArg = this.fastValueWord(step.cmd.words[step.cmd.words.length - 1], rawState, io, false, false, false, true);
18568
17998
  }
18569
- rawState.status = cStatus;
18570
- continue;
18571
17999
  }
18572
18000
  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;
18001
+ status = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line) ? 0 : 1;
18576
18002
  }
18577
18003
  else if (step.coalesceNext) {
18578
18004
  const nextStep = steps[++b];
@@ -18582,8 +18008,8 @@ export class Runtime {
18582
18008
  this.budget.fileSystemOperation();
18583
18009
  this.budget.fileSystemOperation();
18584
18010
  this.budget.bytes += encoded.byteLength;
18585
- lastCmd = nextStep.cmd;
18586
- lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io);
18011
+ progress.lastCmd = nextStep.cmd;
18012
+ progress.lastArg = this.evalSyncRedirectWord(nextStep.value, rawState, io);
18587
18013
  }
18588
18014
  else if (step.targetWord !== undefined && step.value !== undefined) {
18589
18015
  if (this.isSimpleRedirectEchoWord(step.value)) {
@@ -18591,7 +18017,7 @@ export class Runtime {
18591
18017
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18592
18018
  this.budget.fileSystemOperation();
18593
18019
  this.budget.bytes += encoded.byteLength;
18594
- lastArg = this.evalSyncRedirectWord(step.value, rawState, io);
18020
+ progress.lastArg = this.evalSyncRedirectWord(step.value, rawState, io);
18595
18021
  }
18596
18022
  else {
18597
18023
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -18599,31 +18025,31 @@ export class Runtime {
18599
18025
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18600
18026
  this.budget.fileSystemOperation();
18601
18027
  this.budget.bytes += encoded.byteLength;
18602
- lastArg = val;
18028
+ progress.lastArg = val;
18603
18029
  }
18604
18030
  }
18605
18031
  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");
18032
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18607
18033
  const encoded = fastSharedTextEncoder.encode(formatted);
18608
18034
  this.writeSyncRedirectStep(step, encoded, step.append, mode, rawState, io);
18609
18035
  this.budget.fileSystemOperation();
18610
18036
  this.budget.bytes += encoded.byteLength;
18611
- lastArg = pLastArg;
18037
+ progress.lastArg = lastArg;
18612
18038
  }
18613
18039
  else if (step.arrayAssign !== undefined) {
18614
18040
  if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, undefined, undefined, true)) {
18615
18041
  throw new Error("Synchronous loop array assignment was not executable");
18616
18042
  }
18617
- lastArg = "";
18043
+ progress.lastArg = "";
18618
18044
  }
18619
18045
  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");
18046
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18621
18047
  rawState.variables[step.name] = formatted;
18622
18048
  touched.add(step.name);
18623
- lastArg = pLastArg;
18049
+ progress.lastArg = lastArg;
18624
18050
  }
18625
18051
  else if (step.isDiscardDevNull && step.discardWords !== undefined) {
18626
- lastArg = this.runSyncDiscardStep(step, rawState, io);
18052
+ progress.lastArg = this.runSyncDiscardStep(step, rawState, io);
18627
18053
  }
18628
18054
  else if (step.name !== undefined && step.value !== undefined) {
18629
18055
  rawState.substitutionStatus = 0;
@@ -18636,179 +18062,37 @@ export class Runtime {
18636
18062
  else
18637
18063
  rawState.variables[step.name] = val;
18638
18064
  touched.add(step.name);
18639
- lastArg = "";
18065
+ progress.lastArg = "";
18066
+ status = rawState.substitutionStatus;
18640
18067
  }
18641
18068
  else if (step.isStdoutEcho && step.value !== undefined) {
18642
18069
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
18643
18070
  this.writeSyncStdoutText(this.formatSyncEchoLine(val), io);
18644
- lastArg = val;
18071
+ progress.lastArg = val;
18645
18072
  }
18646
18073
  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");
18074
+ const { formatted, lastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
18648
18075
  this.writeSyncStdoutText(formatted, io);
18649
- lastArg = pLastArg;
18076
+ progress.lastArg = lastArg;
18650
18077
  }
18651
18078
  else {
18652
- lastArg = step.cmd.words[0].plain;
18079
+ progress.lastArg = step.cmd.words[0].plain;
18653
18080
  }
18654
- rawState.status = step.name !== undefined && step.value !== undefined ? rawState.substitutionStatus : 0;
18655
- onUpdate({ lastCmd, lastArg });
18081
+ rawState.status = status;
18082
+ progress.pipelineStatus = status;
18083
+ if (this._syncLoopAction !== undefined)
18084
+ break;
18656
18085
  }
18657
18086
  }
18658
18087
  runSyncForFallback(varName, fastLoopWords, bodyAssignments, rawState, io, monitor, touched, mode) {
18659
- let lastCmd;
18660
- let lastArg = rawState.lastArgument ?? "";
18088
+ const progress = { lastCmd: undefined, lastArg: rawState.lastArgument ?? "", pipelineStatus: undefined };
18661
18089
  let loopTurn = 0;
18662
18090
  for (let idx = 0; idx < fastLoopWords.length; idx++) {
18663
18091
  this.budget.loop();
18664
18092
  if ((++loopTurn & 127) === 0)
18665
18093
  runYieldCheckpoint(this.signal);
18666
18094
  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
- }
18095
+ this.execSyncLoopSteps(bodyAssignments, rawState, io, monitor, touched, mode, progress);
18812
18096
  if (this._syncLoopAction !== undefined) {
18813
18097
  const act = this._syncLoopAction;
18814
18098
  this._syncLoopAction = undefined;
@@ -18817,7 +18101,7 @@ export class Runtime {
18817
18101
  }
18818
18102
  }
18819
18103
  this.flushSyncStdoutBatch(io);
18820
- return { lastCmd, lastArg };
18104
+ return progress;
18821
18105
  }
18822
18106
  async script(script, state, io, startListIndex = 0, startPipelineIndex = 0, skipFirstSync = false) {
18823
18107
  if (state.extensions?.syntax.indexedDeclarations?.includes("readonly"))
@@ -19138,13 +18422,11 @@ export class Runtime {
19138
18422
  const isFastPure = isPureStage || runtime.isPureExternalStageCommand(command, rawStateForChild);
19139
18423
  const forkedExt = isFastPure ? forkExtensions(state.extensions, "pipeline") : undefined;
19140
18424
  const child = isFastPure
19141
- ? Object.assign(new RootShellState(rawStateForChild.cwd, rawStateForChild.variables, rawStateForChild.exported, forkedExt), rawStateForChild, {
18425
+ ? Object.assign(cloneRawState(rawStateForChild, false), {
19142
18426
  extensions: forkedExt, isolated: true, _readOnlyStage: true,
19143
18427
  })
19144
18428
  : (tryCloneStateSync(state) ?? await cloneState(state, this.signal));
19145
18429
  preparedChild = child;
19146
- if (child._readOnlyStage)
19147
- child.variables = { ...child.variables };
19148
18430
  child.variables.BASH_SUBSHELL = String(Number(state.variables.BASH_SUBSHELL ?? 0) + 1);
19149
18431
  if (!child._readOnlyStage) {
19150
18432
  child.extensions = undefined;
@@ -19440,7 +18722,7 @@ export class Runtime {
19440
18722
  }
19441
18723
  }
19442
18724
  }
19443
- const extDef = this.getExternalCommand(firstName);
18725
+ const extDef = this.commands.get(firstName);
19444
18726
  return extDef !== undefined && !customRegisteredCommands.has(extDef.execute) && !customRegisteredRegistries.has(this.commands);
19445
18727
  }
19446
18728
  publishStatus(state, statuses, io, terminal) {
@@ -19758,7 +19040,7 @@ export class Runtime {
19758
19040
  }
19759
19041
  for (let pIdx = 0; pIdx < clause.patterns.length; pIdx++) {
19760
19042
  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);
19043
+ const pStr = this.tryBuildSyncPatternWord(pw, state, originalIO, diagnosticLine);
19762
19044
  if (pStr === undefined) {
19763
19045
  allFast = false;
19764
19046
  break;
@@ -21697,7 +20979,7 @@ export class Runtime {
21697
20979
  }
21698
20980
  }
21699
20981
  const scope = io[invocationScope].child();
21700
- const externalDef = typeof name === "string" ? this.getExternalCommand(name) : undefined;
20982
+ const externalDef = typeof name === "string" ? this.commands.get(name) : undefined;
21701
20983
  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
20984
  if (fastInline && externalDef !== undefined && values.every(value => typeof value === "string") && !implementedBuiltins.has(name) && !(name === "printf" && externalDef.execute === printfCommand.execute && args[0]?.startsWith("-v"))) {
21703
20985
  try {
@@ -22155,7 +21437,7 @@ export class Runtime {
22155
21437
  return { exitCode: builtin };
22156
21438
  }
22157
21439
  }
22158
- const definition = this.getExternalCommand(context.command);
21440
+ const definition = this.commands.get(context.command);
22159
21441
  if (context.command === "printf" && definition?.execute === printfCommand.execute && context.args[0]?.startsWith("-v")) {
22160
21442
  ensureRuntimeContext();
22161
21443
  return { exitCode: await this.printfVariable(context, state, assignments) };
@@ -22249,7 +21531,7 @@ export class Runtime {
22249
21531
  matches.push({ kind: "function", name });
22250
21532
  if (implementedBuiltins.has(name) || state.extensions?.builtins.has(name))
22251
21533
  matches.push({ kind: "builtin", name });
22252
- else if (this.hasExternalCommand(name))
21534
+ else if (this.commands.has(name))
22253
21535
  matches.push({ kind: "command", name });
22254
21536
  else if (name === "bash" || name === "sh")
22255
21537
  matches.push({ kind: "interpreter", name });
@@ -22298,23 +21580,12 @@ export class Runtime {
22298
21580
  return "function";
22299
21581
  if (isBuiltin)
22300
21582
  return "builtin";
22301
- if (this.hasExternalCommand(name))
21583
+ if (this.commands.has(name))
22302
21584
  return "command";
22303
21585
  if (name === "bash" || name === "sh")
22304
21586
  return "interpreter";
22305
21587
  return undefined;
22306
21588
  }
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
21589
  async discoveryBuiltin(context, state, io, assignments, inheritedDefaultPath = false) {
22319
21590
  const args = [...context.args];
22320
21591
  const command = context.command === "command";
@@ -26119,7 +25390,7 @@ export class Runtime {
26119
25390
  const name = this.referenceName(state, part.name);
26120
25391
  const binding = arrayStore(state)?.get(name);
26121
25392
  const index = binding?.associative ? binding.keys.get("30")?.index ?? -1 : 0;
26122
- retained = binding?.getValue(index) ?? stateMonitor(state)?.values.get(name, value) ?? value;
25393
+ retained = name === "RANDOM" || name === "SECONDS" || name === "LINENO" ? value : binding?.getValue(index) ?? stateMonitor(state)?.values.get(name, value) ?? value;
26123
25394
  }
26124
25395
  else if (/^0+$/u.test(part.name))
26125
25396
  retained = stateMonitor(state)?.positionals.get(zeroPositionKey, value) ?? value;
@@ -26523,6 +25794,8 @@ export class Runtime {
26523
25794
  let out = "";
26524
25795
  for (let i = 0; i < word.parts.length; i++) {
26525
25796
  let resolvedPart = word.parts[i];
25797
+ if (resolvedPart.kind === "variable" && (resolveSyncNameref(rawState, resolvedPart.name) === "RANDOM" || resolveSyncNameref(rawState, resolvedPart.name) === "SECONDS"))
25798
+ return undefined;
26526
25799
  if (resolvedPart.kind === "variable" && !resolvedPart.prefixNames && rawState.variableAttributes?.get(resolvedPart.name)?.includes("n")) {
26527
25800
  if (resolvedPart.indirect)
26528
25801
  return undefined;
@@ -27273,7 +26546,7 @@ export class Runtime {
27273
26546
  if (!patQuoted && hasGlobOrEscape(pat, !!rawState.extglob)) {
27274
26547
  if (rawState.nocasematch || byteLocale(rawVars))
27275
26548
  return undefined;
27276
- if (isPrefixTrim && pat.charCodeAt(0) === 42 && !hasGlobOrEscape(pat.slice(1), !!rawState.extglob))
26549
+ if (isPrefixTrim && pat.charCodeAt(0) === 42 && !(rawState.extglob && pat.charCodeAt(1) === 40) && !hasGlobOrEscape(pat.slice(1), !!rawState.extglob))
27277
26550
  starWildcardLit = pat.slice(1);
27278
26551
  else if (!isPrefixTrim && pat.charCodeAt(pat.length - 1) === 42 && !hasGlobOrEscape(pat.slice(0, -1), !!rawState.extglob))
27279
26552
  starWildcardLit = pat.slice(0, -1);
@@ -27478,6 +26751,11 @@ export class Runtime {
27478
26751
  else if (part.kind === "substitution") {
27479
26752
  if (split && !part.quoted)
27480
26753
  return undefined;
26754
+ // General word probes may be replayed by a caller after another word or
26755
+ // command guard declines. Run substitutions at the committed valuePart
26756
+ // boundary; only pre-admitted loop invariants belong in this path.
26757
+ if (!this._syncLoopInvariantSubMap?.has(part))
26758
+ return undefined;
27481
26759
  const substVal = this.tryFastPureSubstitution(part, state, rawState, io);
27482
26760
  if (substVal === undefined)
27483
26761
  return undefined;
@@ -36171,7 +35449,7 @@ export class Runtime {
36171
35449
  if (p.kind === "text")
36172
35450
  continue;
36173
35451
  if (p.kind === "variable") {
36174
- if (p.name === "BASH_SUBSHELL")
35452
+ if (p.name === "BASH_SUBSHELL" || p.name === "RANDOM" || p.name === "SECONDS")
36175
35453
  return false;
36176
35454
  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
35455
  const activePos = this._fastSubPositional ?? rawState.positional;
@@ -36189,17 +35467,19 @@ export class Runtime {
36189
35467
  continue;
36190
35468
  }
36191
35469
  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;
35470
+ // Even read-only arithmetic can fail (including through variable values).
35471
+ // Its diagnostic and exit status belong to the substitution's child shell.
35472
+ return false;
36197
35473
  }
36198
35474
  return false;
36199
35475
  }
36200
35476
  return true;
36201
35477
  }
36202
35478
  tryFastPureSubstitution(part, state, rawState, io) {
35479
+ // Synchronous evaluators do not expose cumulative source-read accounting.
35480
+ // Use the command context whenever the caller has set an input ceiling.
35481
+ if (this.budget.limits.maxInputBytes !== Infinity)
35482
+ return undefined;
36203
35483
  const cachedInv = this._syncLoopInvariantSubMap?.get(part);
36204
35484
  if (cachedInv !== undefined && !cachedInv.dynamic) {
36205
35485
  const nextTotalBytes = this.budget.bytes + cachedInv.outBytes;
@@ -36243,7 +35523,7 @@ export class Runtime {
36243
35523
  continue;
36244
35524
  if (name === "fmt" && command === pipeline.commands[0] && command.redirects.length === 0 && !io.stdinIsDefault)
36245
35525
  return undefined;
36246
- const definition = this.getExternalCommand(name);
35526
+ const definition = this.commands.get(name);
36247
35527
  if (definition && customRegisteredCommands.has(definition.execute))
36248
35528
  return undefined;
36249
35529
  if (name === "uname" || name === "nproc" || name === "hostname" || name === "id" || name === "whoami") {
@@ -36285,7 +35565,7 @@ export class Runtime {
36285
35565
  return undefined;
36286
35566
  if (!cmd0StdinRedir && !cmd0HereStringRedir && w0Plain0 === "cat" && cmd0.words.length < 2)
36287
35567
  return undefined;
36288
- const def0 = (w0Plain0 === "printf" || w0Plain0 === "echo" || w0Plain0 === "cat" || w0Plain0 === "pwd" || w0Plain0 === "dirname" || w0Plain0 === "basename") ? this.commands.get(w0Plain0) : this.getExternalCommand(w0Plain0);
35568
+ const def0 = this.commands.get(w0Plain0);
36289
35569
  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
35570
  return undefined;
36291
35571
  if (!this.arePureArgWords(cmd0.words, rawState))
@@ -36302,7 +35582,7 @@ export class Runtime {
36302
35582
  const sName = sCmd.words[0].plain;
36303
35583
  if (!sName || hasShellFunction(rawState, sName) || rawState.extensions?.builtins.has(sName))
36304
35584
  return undefined;
36305
- const extDef = this.getExternalCommand(sName);
35585
+ const extDef = this.commands.get(sName);
36306
35586
  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
35587
  return undefined;
36308
35588
  if ((sName === "xxd" || sName === "od") && !builtInDirectContextExecutors.has(extDef.execute))
@@ -36633,8 +35913,10 @@ export class Runtime {
36633
35913
  if (stage0Formatted === undefined || stage0Formatted.length > 8192)
36634
35914
  return undefined;
36635
35915
  const stage0ByteLen = shellValueByteLength(stage0Formatted);
36636
- if (stage0ByteLen > sharedSyncPipeBuf0.byteLength)
35916
+ if (stage0ByteLen > 65536)
36637
35917
  return undefined;
35918
+ const sharedSyncPipeBuf0 = new Uint8Array(65536);
35919
+ const sharedSyncPipeBuf1 = new Uint8Array(65536);
36638
35920
  const nextBytes0 = this.budget.bytes + stage0ByteLen;
36639
35921
  if (nextBytes0 > this.budget.maxOutputBytesSmi && stage0ByteLen > this.budget.limits.maxOutputBytes - this.budget.bytes)
36640
35922
  this.budget.fail("maxOutputBytes");
@@ -37839,7 +37121,7 @@ export class Runtime {
37839
37121
  for (const cl of cmd.clauses) {
37840
37122
  let matched = false;
37841
37123
  for (const pw of cl.patterns) {
37842
- if (pw.plain !== undefined && tryMatchesPatternSync(pw.plain, subj, work, false, false) === true) {
37124
+ if (pw.plain !== undefined && !pw.plain.startsWith("~") && tryMatchesPatternSync(pw.plain, subj, work, false, false) === true) {
37843
37125
  matched = true;
37844
37126
  break;
37845
37127
  }
@@ -37879,14 +37161,14 @@ export class Runtime {
37879
37161
  if (w0Plain === "fmt" && !hasSingleStdinRedir && !hasSingleHereStringRedir && !io.stdinIsDefault)
37880
37162
  return undefined;
37881
37163
  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);
37164
+ const definition = this.commands.get(w0Plain);
37883
37165
  if (!definition || !builtInDirectContextExecutors.has(definition.execute))
37884
37166
  return undefined;
37885
37167
  }
37886
37168
  if (cmd.words.length === 2 && cmd.redirects.length === 0 && (cmd.words[1]?.plain === "--help" || cmd.words[1]?.plain === "--version")) {
37887
37169
  const gnuInfo = gnuInformationSync(w0Plain, [cmd.words[1].plain], false, (rawState.exported.has("POSIXLY_CORRECT") || rawState.allexport) && rawState.variables.POSIXLY_CORRECT !== undefined);
37888
37170
  if (gnuInfo !== undefined) {
37889
- const extDef = this.getExternalCommand(w0Plain);
37171
+ const extDef = this.commands.get(w0Plain);
37890
37172
  if (!extDef || !builtInDirectContextExecutors.has(extDef.execute))
37891
37173
  return undefined;
37892
37174
  return gnuInfo.replace(/\n+$/, "");
@@ -37907,7 +37189,7 @@ export class Runtime {
37907
37189
  w0Plain === "uniq" ||
37908
37190
  w0Plain === "tr" ||
37909
37191
  (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))))) {
37192
+ 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
37193
  const allArgs = [];
37912
37194
  let fOk = true;
37913
37195
  for (let i = 1; i < cmd.words.length; i++) {
@@ -38039,7 +37321,7 @@ export class Runtime {
38039
37321
  }
38040
37322
  }
38041
37323
  if (fOk && (w0Plain === "date" || w0Plain === "printenv" || w0Plain === "env") && !hasSingleStdinRedir && !hasSingleHereStringRedir) {
38042
- const ext = this.getExternalCommand(w0Plain);
37324
+ const ext = this.commands.get(w0Plain);
38043
37325
  const dpOut = w0Plain === "date"
38044
37326
  ? 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
37327
  : w0Plain === "env"
@@ -38067,7 +37349,7 @@ export class Runtime {
38067
37349
  const inspectNode = (p) => this.tryInspectMemoryNodeSync(p, true);
38068
37350
  const inspectStat = (p, follow) => this.tryInspectMemoryNodeSync(p, true, follow);
38069
37351
  const vfsOut = w0Plain === "df"
38070
- ? evalSyncDf(allArgs, rawState.cwd, rawState.variables, inspectNode, this.getExternalCommand("df")?.execute)
37352
+ ? evalSyncDf(allArgs, rawState.cwd, rawState.variables, inspectNode, this.commands.get("df")?.execute)
38071
37353
  : w0Plain === "du"
38072
37354
  ? evalSyncDu(allArgs, rawState.cwd, rawState.variables, inspectNode)
38073
37355
  : w0Plain === "tree"
@@ -38327,7 +37609,7 @@ export class Runtime {
38327
37609
  return false;
38328
37610
  } })
38329
37611
  : w0Plain === "gh"
38330
- ? syncCommandEvaluators.evalSyncGh?.(this.getExternalCommand("gh").execute, allArgs, rawState.variables, rawState.cwd, readFile)
37612
+ ? syncCommandEvaluators.evalSyncGh?.(this.commands.get("gh").execute, allArgs, rawState.variables, rawState.cwd, readFile)
38331
37613
  : w0Plain === "pdftoppm"
38332
37614
  ? syncCommandEvaluators.evalSyncPdftoppm?.(optInBytes, allArgs, readFile, (p, b) => { try {
38333
37615
  if (this._inSyncLoopPreflight)
@@ -38389,7 +37671,7 @@ export class Runtime {
38389
37671
  return false;
38390
37672
  } })
38391
37673
  : w0Plain === "ssconvert"
38392
- ? syncCommandEvaluators.evalSyncSsconvert?.(this.getExternalCommand("ssconvert").execute, allArgs, optInBytes, readFile, (p, b) => { try {
37674
+ ? syncCommandEvaluators.evalSyncSsconvert?.(this.commands.get("ssconvert").execute, allArgs, optInBytes, readFile, (p, b) => { try {
38393
37675
  if (this._inSyncLoopPreflight)
38394
37676
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
38395
37677
  const fp = resolvePath(rawState.cwd, p);
@@ -38413,9 +37695,9 @@ export class Runtime {
38413
37695
  return false;
38414
37696
  } })
38415
37697
  : w0Plain === "op"
38416
- ? syncCommandEvaluators.evalSyncOp?.(this.getExternalCommand("op").execute, allArgs, rawState.variables)
37698
+ ? syncCommandEvaluators.evalSyncOp?.(this.commands.get("op").execute, allArgs, rawState.variables)
38417
37699
  : 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 {
37700
+ ? 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
37701
  if (this._inSyncLoopPreflight)
38420
37702
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
38421
37703
  const dir = p.slice(0, p.lastIndexOf("/")) || "/";
@@ -39287,7 +38569,7 @@ export class Runtime {
39287
38569
  } });
39288
38570
  }
39289
38571
  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));
38572
+ fileRes = syncCommandEvaluators.evalSyncGh?.(this.commands.get("gh").execute, opArgs, rawState.variables, rawState.cwd, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), false));
39291
38573
  }
39292
38574
  else if (w0Plain === "pdftoppm") {
39293
38575
  const readFile = (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true);
@@ -39360,7 +38642,7 @@ export class Runtime {
39360
38642
  } });
39361
38643
  }
39362
38644
  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 {
38645
+ fileRes = syncCommandEvaluators.evalSyncSsconvert?.(this.commands.get("ssconvert").execute, opArgs, view, (p) => this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, p), true, true), (p, b) => { try {
39364
38646
  if (this._inSyncLoopPreflight)
39365
38647
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
39366
38648
  const fp = resolvePath(rawState.cwd, p);
@@ -39387,10 +38669,10 @@ export class Runtime {
39387
38669
  } });
39388
38670
  }
39389
38671
  else if (w0Plain === "op") {
39390
- fileRes = syncCommandEvaluators.evalSyncOp?.(this.getExternalCommand("op").execute, opArgs, rawState.variables);
38672
+ fileRes = syncCommandEvaluators.evalSyncOp?.(this.commands.get("op").execute, opArgs, rawState.variables);
39391
38673
  }
39392
38674
  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 {
38675
+ 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
38676
  if (this._inSyncLoopPreflight)
39395
38677
  return Boolean(this.canFastMemoryRedirect && this._isMemoryBackingFs);
39396
38678
  const dir = p.slice(0, p.lastIndexOf("/")) || "/";
@@ -39869,6 +39151,8 @@ export class Runtime {
39869
39151
  }
39870
39152
  let fnPositional;
39871
39153
  if (rawState.functions.has(w0Plain)) {
39154
+ if (rawState.functionDepth >= this.budget.limits.maxFunctionDepth)
39155
+ return undefined;
39872
39156
  if (rawState.depth + 1 >= this.budget.limits.maxSubstitutionDepth)
39873
39157
  return undefined;
39874
39158
  const fnBody = rawState.functions.get(w0Plain);
@@ -39906,7 +39190,7 @@ export class Runtime {
39906
39190
  const disc = typeof targetName === "string" ? this.tryResolveSyncDiscovery(w0Plain === "command" ? "name" : "kind", targetName, rawState) : undefined;
39907
39191
  if (disc !== undefined && (disc.status === 0 || !rawState.errexit)) {
39908
39192
  if (disc.status === 0) {
39909
- const byteLength = (disc.text.length * 3 > 127 ? shellValueByteLength(disc.text) : disc.text.length) + 1;
39193
+ const byteLength = shellValueByteLength(disc.text) + 1;
39910
39194
  const nextBytes = this.budget.bytes + byteLength;
39911
39195
  if (nextBytes > this.budget.maxOutputBytesSmi && byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes)
39912
39196
  this.budget.fail("maxOutputBytes");
@@ -39924,7 +39208,7 @@ export class Runtime {
39924
39208
  let res = rawState.cwd;
39925
39209
  while (res.endsWith("\n"))
39926
39210
  res = res.slice(0, -1);
39927
- const byteLength = (res.length * 3 > 127 ? shellValueByteLength(res) : res.length) + 1;
39211
+ const byteLength = shellValueByteLength(res) + 1;
39928
39212
  const nextBytes = this.budget.bytes + byteLength;
39929
39213
  if (nextBytes > this.budget.maxOutputBytesSmi && byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes)
39930
39214
  this.budget.fail("maxOutputBytes");
@@ -39938,7 +39222,7 @@ export class Runtime {
39938
39222
  }
39939
39223
  if (w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq")
39940
39224
  return undefined;
39941
- const def = w0Plain === "seq" ? this.getExternalCommand(w0Plain) : this.commands.get(w0Plain);
39225
+ const def = this.commands.get(w0Plain);
39942
39226
  if (!def)
39943
39227
  return undefined;
39944
39228
  if (w0Plain === "printf" && def.execute !== printfCommand.execute)
@@ -41001,6 +40285,7 @@ export class RootShellState {
41001
40285
  this.status = 0;
41002
40286
  this.substitutionStatus = 0;
41003
40287
  this.lastArgument = "";
40288
+ this.secondsOrigin = Date.now();
41004
40289
  }
41005
40290
  get exported() {
41006
40291
  const raw = stateMonitor(this)?.raw;