@poe-platform/safe-bash 0.1.630 → 0.1.631

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 (357) hide show
  1. package/README.md +1 -0
  2. package/dist/office-package/compression.d.ts +19 -0
  3. package/dist/office-package/compression.js +186 -0
  4. package/dist/office-package/runtime.d.ts +11 -0
  5. package/dist/office-package/runtime.js +28 -0
  6. package/dist/safe-bash/chunks/{bz2-B2RXT4EX.js → bz2-ACU4EOVE.js} +2 -2
  7. package/dist/safe-bash/chunks/chunk-2E4KBFO6.js +239 -0
  8. package/dist/safe-bash/chunks/chunk-2E4KBFO6.js.map +7 -0
  9. package/dist/safe-bash/chunks/chunk-3E5M2WEL.js +33 -0
  10. package/dist/safe-bash/chunks/chunk-3E5M2WEL.js.map +7 -0
  11. package/dist/safe-bash/chunks/{chunk-KQ6J7JHQ.js → chunk-3LD67SER.js} +12 -10
  12. package/dist/safe-bash/chunks/{chunk-KQ6J7JHQ.js.map → chunk-3LD67SER.js.map} +1 -1
  13. package/dist/safe-bash/chunks/{chunk-6LSSEOG7.js → chunk-6HNK7Q66.js} +11 -7
  14. package/dist/safe-bash/chunks/{chunk-6LSSEOG7.js.map → chunk-6HNK7Q66.js.map} +1 -1
  15. package/dist/safe-bash/chunks/{chunk-AD7UAP5B.js → chunk-7EEWZY5S.js} +10 -8
  16. package/dist/safe-bash/chunks/{chunk-AD7UAP5B.js.map → chunk-7EEWZY5S.js.map} +1 -1
  17. package/dist/safe-bash/chunks/{chunk-RNKTWFEM.js → chunk-CDBQXRWL.js} +3 -3
  18. package/dist/safe-bash/chunks/{chunk-UYX72YHY.js → chunk-CHHAB5SS.js} +10 -74
  19. package/dist/safe-bash/chunks/{chunk-UYX72YHY.js.map → chunk-CHHAB5SS.js.map} +3 -3
  20. package/dist/safe-bash/chunks/{chunk-6YSBXTTJ.js → chunk-EI4X5ETX.js} +12 -10
  21. package/dist/safe-bash/chunks/{chunk-6YSBXTTJ.js.map → chunk-EI4X5ETX.js.map} +1 -1
  22. package/dist/safe-bash/chunks/{chunk-KZ7QCYNT.js → chunk-GIBLUW2U.js} +13 -9
  23. package/dist/safe-bash/chunks/{chunk-KZ7QCYNT.js.map → chunk-GIBLUW2U.js.map} +1 -1
  24. package/dist/safe-bash/chunks/chunk-GPV7ZFYS.js +1528 -0
  25. package/dist/safe-bash/chunks/chunk-GPV7ZFYS.js.map +7 -0
  26. package/dist/safe-bash/chunks/{chunk-N5CYTGBN.js → chunk-H3E67KTZ.js} +13 -9
  27. package/dist/safe-bash/chunks/{chunk-N5CYTGBN.js.map → chunk-H3E67KTZ.js.map} +1 -1
  28. package/dist/safe-bash/chunks/{chunk-AFH57PPL.js → chunk-IEKESMO4.js} +3 -3
  29. package/dist/safe-bash/chunks/{chunk-DPJWEGIX.js → chunk-JLBIUYT3.js} +2 -2
  30. package/dist/safe-bash/chunks/chunk-JZDO5MC3.js +77 -0
  31. package/dist/safe-bash/chunks/chunk-JZDO5MC3.js.map +7 -0
  32. package/dist/safe-bash/chunks/{chunk-GFZKQIPL.js → chunk-LA6BX562.js} +8 -6
  33. package/dist/safe-bash/chunks/{chunk-GFZKQIPL.js.map → chunk-LA6BX562.js.map} +1 -1
  34. package/dist/safe-bash/chunks/{chunk-PVJJFCGA.js → chunk-M3GPCYSP.js} +2 -2
  35. package/dist/safe-bash/chunks/{chunk-FWDMJTQO.js → chunk-NDCZ3UBP.js} +13 -9
  36. package/dist/safe-bash/chunks/{chunk-FWDMJTQO.js.map → chunk-NDCZ3UBP.js.map} +1 -1
  37. package/dist/safe-bash/chunks/{chunk-2KL6W6NB.js → chunk-O2EVBRKF.js} +1 -2
  38. package/dist/safe-bash/chunks/chunk-OFT77XIB.js +389 -0
  39. package/dist/safe-bash/chunks/chunk-OFT77XIB.js.map +7 -0
  40. package/dist/safe-bash/chunks/{chunk-PCLOK32J.js → chunk-PC6BEIAF.js} +13 -9
  41. package/dist/safe-bash/chunks/{chunk-PCLOK32J.js.map → chunk-PC6BEIAF.js.map} +1 -1
  42. package/dist/safe-bash/chunks/{chunk-3M5F7LD5.js → chunk-QWKP7ZU7.js} +13 -9
  43. package/dist/safe-bash/chunks/{chunk-3M5F7LD5.js.map → chunk-QWKP7ZU7.js.map} +1 -1
  44. package/dist/safe-bash/chunks/chunk-THXJ6CLF.js +53 -0
  45. package/dist/safe-bash/chunks/chunk-THXJ6CLF.js.map +7 -0
  46. package/dist/safe-bash/chunks/{chunk-K7W6Q6FN.js → chunk-V73A742N.js} +58 -16
  47. package/dist/safe-bash/chunks/chunk-V73A742N.js.map +7 -0
  48. package/dist/safe-bash/chunks/{chunk-4BYUV5PA.js → chunk-VN3ZGME3.js} +12 -8
  49. package/dist/safe-bash/chunks/{chunk-4BYUV5PA.js.map → chunk-VN3ZGME3.js.map} +1 -1
  50. package/dist/safe-bash/chunks/{chunk-3BZ5NQ73.js → chunk-WECHUK3Y.js} +369 -36
  51. package/dist/safe-bash/chunks/chunk-WECHUK3Y.js.map +7 -0
  52. package/dist/safe-bash/chunks/{chunk-X55AMTNM.js → chunk-WIOEUR7D.js} +14 -10
  53. package/dist/safe-bash/chunks/{chunk-X55AMTNM.js.map → chunk-WIOEUR7D.js.map} +1 -1
  54. package/dist/safe-bash/chunks/chunk-WPIOO4NX.js +443 -0
  55. package/dist/safe-bash/chunks/chunk-WPIOO4NX.js.map +7 -0
  56. package/dist/safe-bash/chunks/{chunk-C7QNJ3D4.js → chunk-WYTI64IU.js} +2 -2
  57. package/dist/safe-bash/chunks/{xz-AVXFDXW4.js → xz-U4QDTPZL.js} +2 -2
  58. package/dist/safe-bash/chunks/{zstd-R6RPHJYO.js → zstd-OG5RPYXO.js} +2 -2
  59. package/dist/safe-bash/commands/archive/zip/crc.d.ts +2 -0
  60. package/dist/safe-bash/commands/archive/zip/crc.d.ts.map +1 -0
  61. package/dist/safe-bash/commands/archive/zip/crc.js +7 -0
  62. package/dist/safe-bash/commands/archive/zip/crc.js.map +1 -0
  63. package/dist/safe-bash/commands/archive/zip/crypto.d.ts +4 -0
  64. package/dist/safe-bash/commands/archive/zip/crypto.d.ts.map +1 -0
  65. package/dist/safe-bash/commands/archive/zip/crypto.js +34 -0
  66. package/dist/safe-bash/commands/archive/zip/crypto.js.map +1 -0
  67. package/dist/safe-bash/commands/archive/zip/help.d.ts +3 -0
  68. package/dist/safe-bash/commands/archive/zip/help.d.ts.map +1 -0
  69. package/dist/safe-bash/commands/archive/zip/help.js +87 -0
  70. package/dist/safe-bash/commands/archive/zip/help.js.map +1 -0
  71. package/dist/safe-bash/commands/archive/zip/move.d.ts +12 -0
  72. package/dist/safe-bash/commands/archive/zip/move.d.ts.map +1 -0
  73. package/dist/safe-bash/commands/archive/zip/move.js +60 -0
  74. package/dist/safe-bash/commands/archive/zip/move.js.map +1 -0
  75. package/dist/safe-bash/commands/archive/zip/options.js +5 -5
  76. package/dist/safe-bash/commands/archive/zip/options.js.map +1 -1
  77. package/dist/safe-bash/commands/archive/zip-format.d.ts +1 -1
  78. package/dist/safe-bash/commands/archive/zip-format.d.ts.map +1 -1
  79. package/dist/safe-bash/commands/archive/zip-format.js +14 -17
  80. package/dist/safe-bash/commands/archive/zip-format.js.map +1 -1
  81. package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -1
  82. package/dist/safe-bash/commands/archive/zip.js +45 -15
  83. package/dist/safe-bash/commands/archive/zip.js.map +1 -1
  84. package/dist/safe-bash/commands/bytes/compression/bounded-codec.d.ts +2 -0
  85. package/dist/safe-bash/commands/bytes/compression/bounded-codec.d.ts.map +1 -1
  86. package/dist/safe-bash/commands/bytes/compression/bounded-codec.js +4 -0
  87. package/dist/safe-bash/commands/bytes/compression/bounded-codec.js.map +1 -1
  88. package/dist/safe-bash/commands/bytes/compression/codec.d.ts +4 -24
  89. package/dist/safe-bash/commands/bytes/compression/codec.d.ts.map +1 -1
  90. package/dist/safe-bash/commands/bytes/compression/codec.js +12 -168
  91. package/dist/safe-bash/commands/bytes/compression/codec.js.map +1 -1
  92. package/dist/safe-bash/commands/cmp.js +1 -1
  93. package/dist/safe-bash/commands/cmp.js.map +1 -1
  94. package/dist/safe-bash/commands/csplit/index.browser.js +10 -7
  95. package/dist/safe-bash/commands/docx/index.browser.js +54 -0
  96. package/dist/safe-bash/commands/docx/index.browser.js.map +7 -0
  97. package/dist/safe-bash/commands/docx/index.d.ts +25 -0
  98. package/dist/safe-bash/commands/docx/index.d.ts.map +1 -0
  99. package/dist/safe-bash/commands/docx/index.js +42 -0
  100. package/dist/safe-bash/commands/docx/index.js.map +1 -0
  101. package/dist/safe-bash/commands/docx/io.d.ts +15 -0
  102. package/dist/safe-bash/commands/docx/io.d.ts.map +1 -0
  103. package/dist/safe-bash/commands/docx/io.js +16 -0
  104. package/dist/safe-bash/commands/docx/io.js.map +1 -0
  105. package/dist/safe-bash/commands/factor/index.browser.js +7 -5
  106. package/dist/safe-bash/commands/filesystem.d.ts.map +1 -1
  107. package/dist/safe-bash/commands/filesystem.js +9 -1
  108. package/dist/safe-bash/commands/filesystem.js.map +1 -1
  109. package/dist/safe-bash/commands/getopt/index.browser.js +7 -5
  110. package/dist/safe-bash/commands/hexdump/index.browser.js +8 -6
  111. package/dist/safe-bash/commands/iconv/index.browser.js +8 -6
  112. package/dist/safe-bash/commands/line-endings/index.browser.js +10 -7
  113. package/dist/safe-bash/commands/llm/index.browser.js +10 -8
  114. package/dist/safe-bash/commands/llm/providers/index.browser.js +3 -3
  115. package/dist/safe-bash/commands/network/index.browser.js +11 -8
  116. package/dist/safe-bash/commands/node/index.browser.js +8 -6
  117. package/dist/safe-bash/commands/op/index.browser.js +3 -3
  118. package/dist/safe-bash/commands/op/index.js +0 -1
  119. package/dist/safe-bash/commands/op/index.js.map +2 -2
  120. package/dist/safe-bash/commands/pptx/index.d.ts +29 -0
  121. package/dist/safe-bash/commands/pptx/index.d.ts.map +1 -0
  122. package/dist/safe-bash/commands/pptx/index.js +153 -0
  123. package/dist/safe-bash/commands/pptx/index.js.map +1 -0
  124. package/dist/safe-bash/commands/pr/index.browser.js +8 -6
  125. package/dist/safe-bash/commands/predicates.js +1 -1
  126. package/dist/safe-bash/commands/python/execution.d.ts +3 -0
  127. package/dist/safe-bash/commands/python/execution.d.ts.map +1 -0
  128. package/dist/safe-bash/commands/python/execution.js +193 -0
  129. package/dist/safe-bash/commands/python/execution.js.map +1 -0
  130. package/dist/safe-bash/commands/python/index.browser.js +21 -0
  131. package/dist/safe-bash/commands/python/index.browser.js.map +7 -0
  132. package/dist/safe-bash/commands/python/index.d.ts +49 -0
  133. package/dist/safe-bash/commands/python/index.d.ts.map +1 -0
  134. package/dist/safe-bash/commands/python/index.js +317 -0
  135. package/dist/safe-bash/commands/python/index.js.map +1 -0
  136. package/dist/safe-bash/commands/python/installation.d.ts +9 -0
  137. package/dist/safe-bash/commands/python/installation.d.ts.map +1 -0
  138. package/dist/safe-bash/commands/python/installation.js +80 -0
  139. package/dist/safe-bash/commands/python/installation.js.map +1 -0
  140. package/dist/safe-bash/commands/python/invocation.d.ts +10 -0
  141. package/dist/safe-bash/commands/python/invocation.d.ts.map +1 -0
  142. package/dist/safe-bash/commands/python/invocation.js +81 -0
  143. package/dist/safe-bash/commands/python/invocation.js.map +1 -0
  144. package/dist/safe-bash/commands/python/node.d.ts +12 -0
  145. package/dist/safe-bash/commands/python/node.d.ts.map +1 -0
  146. package/dist/safe-bash/commands/python/node.js +33 -0
  147. package/dist/safe-bash/commands/python/node.js.map +1 -0
  148. package/dist/safe-bash/commands/python/provisioning-runtime.d.ts +5 -0
  149. package/dist/safe-bash/commands/python/provisioning-runtime.d.ts.map +1 -0
  150. package/dist/safe-bash/commands/python/provisioning-runtime.js +179 -0
  151. package/dist/safe-bash/commands/python/provisioning-runtime.js.map +1 -0
  152. package/dist/safe-bash/commands/python/provisioning.d.ts +49 -0
  153. package/dist/safe-bash/commands/python/provisioning.d.ts.map +1 -0
  154. package/dist/safe-bash/commands/python/provisioning.js +320 -0
  155. package/dist/safe-bash/commands/python/provisioning.js.map +1 -0
  156. package/dist/safe-bash/commands/python/reply.d.ts +3 -0
  157. package/dist/safe-bash/commands/python/reply.d.ts.map +1 -0
  158. package/dist/safe-bash/commands/python/reply.js +103 -0
  159. package/dist/safe-bash/commands/python/reply.js.map +1 -0
  160. package/dist/safe-bash/commands/python/worker.browser.js +736 -0
  161. package/dist/safe-bash/commands/python/worker.browser.js.map +7 -0
  162. package/dist/safe-bash/commands/python/worker.d.ts +47 -0
  163. package/dist/safe-bash/commands/python/worker.d.ts.map +1 -0
  164. package/dist/safe-bash/commands/python/worker.js +373 -0
  165. package/dist/safe-bash/commands/python/worker.js.map +1 -0
  166. package/dist/safe-bash/commands/tsort/index.browser.js +8 -6
  167. package/dist/safe-bash/commands/xml/index.browser.js +9 -7
  168. package/dist/safe-bash/commands/yq/index.browser.js +10 -8
  169. package/dist/safe-bash/commands/yq/index.d.ts.map +1 -1
  170. package/dist/safe-bash/commands/yq/index.js +32 -4
  171. package/dist/safe-bash/commands/yq/index.js.map +1 -1
  172. package/dist/safe-bash/commands/yq/parser.d.ts.map +1 -1
  173. package/dist/safe-bash/commands/yq/parser.js +21 -5
  174. package/dist/safe-bash/commands/yq/parser.js.map +1 -1
  175. package/dist/safe-bash/contracts/command.d.ts +2 -0
  176. package/dist/safe-bash/contracts/command.d.ts.map +1 -1
  177. package/dist/safe-bash/contracts/command.js +6 -2
  178. package/dist/safe-bash/contracts/command.js.map +1 -1
  179. package/dist/safe-bash/contracts/filesystem-descriptor.d.ts +13 -0
  180. package/dist/safe-bash/contracts/filesystem-descriptor.d.ts.map +1 -0
  181. package/dist/safe-bash/contracts/filesystem-descriptor.js +189 -0
  182. package/dist/safe-bash/contracts/filesystem-descriptor.js.map +1 -0
  183. package/dist/safe-bash/contracts/filesystem-output-budget.d.ts +15 -0
  184. package/dist/safe-bash/contracts/filesystem-output-budget.d.ts.map +1 -0
  185. package/dist/safe-bash/contracts/filesystem-output-budget.js +69 -0
  186. package/dist/safe-bash/contracts/filesystem-output-budget.js.map +1 -0
  187. package/dist/safe-bash/contracts/filesystem-output.d.ts +11 -5
  188. package/dist/safe-bash/contracts/filesystem-output.d.ts.map +1 -1
  189. package/dist/safe-bash/contracts/filesystem-output.js +229 -20
  190. package/dist/safe-bash/contracts/filesystem-output.js.map +1 -1
  191. package/dist/safe-bash/contracts/io.d.ts +29 -0
  192. package/dist/safe-bash/contracts/io.d.ts.map +1 -1
  193. package/dist/safe-bash/contracts/io.js +317 -37
  194. package/dist/safe-bash/contracts/io.js.map +1 -1
  195. package/dist/safe-bash/core.browser.js +5502 -2210
  196. package/dist/safe-bash/core.browser.js.map +4 -4
  197. package/dist/safe-bash/core.d.ts +1 -0
  198. package/dist/safe-bash/core.d.ts.map +1 -1
  199. package/dist/safe-bash/core.js +1 -0
  200. package/dist/safe-bash/core.js.map +1 -1
  201. package/dist/safe-bash/opt-in/commands/cmp/compare.js +95 -0
  202. package/dist/safe-bash/opt-in/commands/cmp/index.d.ts +6 -0
  203. package/dist/safe-bash/opt-in/commands/cmp/index.js +99 -0
  204. package/dist/safe-bash/opt-in/commands/cmp/io.js +218 -0
  205. package/dist/safe-bash/opt-in/commands/cmp/options.d.ts +24 -0
  206. package/dist/safe-bash/opt-in/commands/cmp/options.js +195 -0
  207. package/dist/safe-bash/opt-in/commands/dd/conversions.js +152 -0
  208. package/dist/safe-bash/opt-in/commands/dd/index.d.ts +18 -0
  209. package/dist/safe-bash/opt-in/commands/dd/index.js +561 -0
  210. package/dist/safe-bash/opt-in/commands/dd/io.d.ts +31 -0
  211. package/dist/safe-bash/opt-in/commands/dd/io.js +244 -0
  212. package/dist/safe-bash/opt-in/commands/dd/options.js +184 -0
  213. package/dist/safe-bash/opt-in/commands/dd/report.js +69 -0
  214. package/dist/safe-bash/opt-in/commands/install/arguments.js +224 -0
  215. package/dist/safe-bash/opt-in/commands/install/index.d.ts +6 -0
  216. package/dist/safe-bash/opt-in/commands/install/index.js +678 -0
  217. package/dist/safe-bash/opt-in/commands/install/mode.js +71 -0
  218. package/dist/safe-bash/opt-in/commands/install/options.d.ts +36 -0
  219. package/dist/safe-bash/opt-in/commands/install/options.js +27 -0
  220. package/dist/safe-bash/opt-in/commands/shuf/args.js +179 -0
  221. package/dist/safe-bash/opt-in/commands/shuf/index.d.ts +6 -0
  222. package/dist/safe-bash/opt-in/commands/shuf/index.js +20 -0
  223. package/dist/safe-bash/opt-in/commands/shuf/input.js +93 -0
  224. package/dist/safe-bash/opt-in/commands/shuf/options.d.ts +9 -0
  225. package/dist/safe-bash/opt-in/commands/shuf/options.js +8 -0
  226. package/dist/safe-bash/opt-in/commands/shuf/random.js +114 -0
  227. package/dist/safe-bash/opt-in/commands/shuf/shuf.d.ts +3 -0
  228. package/dist/safe-bash/opt-in/commands/shuf/shuf.js +230 -0
  229. package/dist/safe-bash/opt-in/commands/shuf/usage.js +24 -0
  230. package/dist/safe-bash/opt-in/commands/truncate/arguments.js +186 -0
  231. package/dist/safe-bash/opt-in/commands/truncate/index.d.ts +9 -0
  232. package/dist/safe-bash/opt-in/commands/truncate/index.js +244 -0
  233. package/dist/safe-bash/opt-in/commands/yes/index.d.ts +11 -0
  234. package/dist/safe-bash/opt-in/commands/yes/index.js +167 -0
  235. package/dist/safe-bash/opt-in/commands/yq/arguments.js +177 -0
  236. package/dist/safe-bash/opt-in/commands/yq/evaluate.js +564 -0
  237. package/dist/safe-bash/opt-in/commands/yq/expression.js +183 -0
  238. package/dist/safe-bash/opt-in/commands/yq/inplace.js +65 -0
  239. package/dist/safe-bash/opt-in/commands/yq/mike.d.ts +9 -0
  240. package/dist/safe-bash/opt-in/commands/yq/mike.js +192 -0
  241. package/dist/safe-bash/opt-in/commands/yq/native-encoder.js +165 -0
  242. package/dist/safe-bash/opt-in/commands/yq/native-work.d.ts +44 -0
  243. package/dist/safe-bash/opt-in/commands/yq/native-work.js +188 -0
  244. package/dist/safe-bash/opt-in/commands/yq/nodes.js +621 -0
  245. package/dist/safe-bash/opt-in/entrypoints/arrays.d.ts +1 -0
  246. package/dist/safe-bash/opt-in/entrypoints/arrays.js +1 -0
  247. package/dist/safe-bash/opt-in/entrypoints/cmp.d.ts +2 -0
  248. package/dist/safe-bash/opt-in/entrypoints/cmp.js +1 -0
  249. package/dist/safe-bash/opt-in/entrypoints/dd.d.ts +2 -0
  250. package/dist/safe-bash/opt-in/entrypoints/dd.js +1 -0
  251. package/dist/safe-bash/opt-in/entrypoints/devices.d.ts +2 -0
  252. package/dist/safe-bash/opt-in/entrypoints/devices.js +1 -0
  253. package/dist/safe-bash/opt-in/entrypoints/install.d.ts +2 -0
  254. package/dist/safe-bash/opt-in/entrypoints/install.js +1 -0
  255. package/dist/safe-bash/opt-in/entrypoints/jobs.d.ts +1 -0
  256. package/dist/safe-bash/opt-in/entrypoints/jobs.js +1 -0
  257. package/dist/safe-bash/opt-in/entrypoints/mapfile.d.ts +1 -0
  258. package/dist/safe-bash/opt-in/entrypoints/mapfile.js +1 -0
  259. package/dist/safe-bash/opt-in/entrypoints/read.d.ts +2 -0
  260. package/dist/safe-bash/opt-in/entrypoints/read.js +1 -0
  261. package/dist/safe-bash/opt-in/entrypoints/shuf.d.ts +2 -0
  262. package/dist/safe-bash/opt-in/entrypoints/shuf.js +1 -0
  263. package/dist/safe-bash/opt-in/entrypoints/trap.d.ts +2 -0
  264. package/dist/safe-bash/opt-in/entrypoints/trap.js +1 -0
  265. package/dist/safe-bash/opt-in/entrypoints/truncate.d.ts +2 -0
  266. package/dist/safe-bash/opt-in/entrypoints/truncate.js +1 -0
  267. package/dist/safe-bash/opt-in/entrypoints/yes.d.ts +2 -0
  268. package/dist/safe-bash/opt-in/entrypoints/yes.js +1 -0
  269. package/dist/safe-bash/opt-in/entrypoints/yq.d.ts +3 -0
  270. package/dist/safe-bash/opt-in/entrypoints/yq.js +1 -0
  271. package/dist/safe-bash/opt-in/fs/devices/index.d.ts +8 -0
  272. package/dist/safe-bash/opt-in/fs/devices/index.js +292 -0
  273. package/dist/safe-bash/opt-in/optional.d.ts +28 -0
  274. package/dist/safe-bash/opt-in/optional.js +14 -0
  275. package/dist/safe-bash/opt-in/shell/extensions/arrays/index.d.ts +2 -0
  276. package/dist/safe-bash/opt-in/shell/extensions/arrays/index.js +4 -0
  277. package/dist/safe-bash/opt-in/shell/extensions/jobs/index.d.ts +2 -0
  278. package/dist/safe-bash/opt-in/shell/extensions/jobs/index.js +291 -0
  279. package/dist/safe-bash/opt-in/shell/extensions/jobs/state.js +374 -0
  280. package/dist/safe-bash/opt-in/shell/extensions/mapfile/index.d.ts +24 -0
  281. package/dist/safe-bash/opt-in/shell/extensions/mapfile/index.js +338 -0
  282. package/dist/safe-bash/opt-in/shell/extensions/read/index.d.ts +5 -0
  283. package/dist/safe-bash/opt-in/shell/extensions/read/index.js +351 -0
  284. package/dist/safe-bash/opt-in/shell/extensions/trap/index.d.ts +9 -0
  285. package/dist/safe-bash/opt-in/shell/extensions/trap/index.js +210 -0
  286. package/dist/safe-bash/optional-host.d.ts +5 -0
  287. package/dist/safe-bash/optional-host.d.ts.map +1 -0
  288. package/dist/safe-bash/optional-host.js +3 -0
  289. package/dist/safe-bash/optional-host.js.map +1 -0
  290. package/dist/safe-bash/shell/arrays/bindings.d.ts +15 -5
  291. package/dist/safe-bash/shell/arrays/bindings.d.ts.map +1 -1
  292. package/dist/safe-bash/shell/arrays/bindings.js +131 -23
  293. package/dist/safe-bash/shell/arrays/bindings.js.map +1 -1
  294. package/dist/safe-bash/shell/arrays/ledger.d.ts +1 -0
  295. package/dist/safe-bash/shell/arrays/ledger.d.ts.map +1 -1
  296. package/dist/safe-bash/shell/arrays/ledger.js +19 -0
  297. package/dist/safe-bash/shell/arrays/ledger.js.map +1 -1
  298. package/dist/safe-bash/shell/arrays/state.d.ts.map +1 -1
  299. package/dist/safe-bash/shell/arrays/state.js +3 -1
  300. package/dist/safe-bash/shell/arrays/state.js.map +1 -1
  301. package/dist/safe-bash/shell/arrays/syntax.d.ts +4 -1
  302. package/dist/safe-bash/shell/arrays/syntax.d.ts.map +1 -1
  303. package/dist/safe-bash/shell/arrays/syntax.js +3 -3
  304. package/dist/safe-bash/shell/arrays/syntax.js.map +1 -1
  305. package/dist/safe-bash/shell/conditional.js +1 -1
  306. package/dist/safe-bash/shell/descriptors.d.ts +31 -0
  307. package/dist/safe-bash/shell/descriptors.d.ts.map +1 -0
  308. package/dist/safe-bash/shell/descriptors.js +234 -0
  309. package/dist/safe-bash/shell/descriptors.js.map +1 -0
  310. package/dist/safe-bash/shell/diagnostic-name-ranges.d.ts +2 -0
  311. package/dist/safe-bash/shell/diagnostic-name-ranges.d.ts.map +1 -0
  312. package/dist/safe-bash/shell/diagnostic-name-ranges.js +717 -0
  313. package/dist/safe-bash/shell/diagnostic-name-ranges.js.map +1 -0
  314. package/dist/safe-bash/shell/diagnostic-name.d.ts +3 -0
  315. package/dist/safe-bash/shell/diagnostic-name.d.ts.map +1 -0
  316. package/dist/safe-bash/shell/diagnostic-name.js +89 -0
  317. package/dist/safe-bash/shell/diagnostic-name.js.map +1 -0
  318. package/dist/safe-bash/shell/display.js +1 -1
  319. package/dist/safe-bash/shell/display.js.map +1 -1
  320. package/dist/safe-bash/shell/extensions.d.ts +188 -0
  321. package/dist/safe-bash/shell/extensions.d.ts.map +1 -0
  322. package/dist/safe-bash/shell/extensions.js +141 -0
  323. package/dist/safe-bash/shell/extensions.js.map +1 -0
  324. package/dist/safe-bash/shell/input.d.ts +66 -14
  325. package/dist/safe-bash/shell/input.d.ts.map +1 -1
  326. package/dist/safe-bash/shell/input.js +947 -173
  327. package/dist/safe-bash/shell/input.js.map +1 -1
  328. package/dist/safe-bash/shell/parser.d.ts +38 -6
  329. package/dist/safe-bash/shell/parser.d.ts.map +1 -1
  330. package/dist/safe-bash/shell/parser.js +339 -52
  331. package/dist/safe-bash/shell/parser.js.map +1 -1
  332. package/dist/safe-bash/shell/runtime.d.ts +92 -20
  333. package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
  334. package/dist/safe-bash/shell/runtime.js +2547 -689
  335. package/dist/safe-bash/shell/runtime.js.map +1 -1
  336. package/dist/safe-bash/shell/shell.d.ts.map +1 -1
  337. package/dist/safe-bash/shell/shell.js +52 -21
  338. package/dist/safe-bash/shell/shell.js.map +1 -1
  339. package/dist/safe-bash/shell/types.d.ts +4 -0
  340. package/dist/safe-bash/shell/types.d.ts.map +1 -1
  341. package/dist/safe-bash/shell/types.js.map +1 -1
  342. package/package.json +92 -4
  343. package/dist/safe-bash/chunks/chunk-3BZ5NQ73.js.map +0 -7
  344. package/dist/safe-bash/chunks/chunk-4DBWBEU7.js +0 -194
  345. package/dist/safe-bash/chunks/chunk-4DBWBEU7.js.map +0 -7
  346. package/dist/safe-bash/chunks/chunk-CXMIIXJA.js +0 -178
  347. package/dist/safe-bash/chunks/chunk-CXMIIXJA.js.map +0 -7
  348. package/dist/safe-bash/chunks/chunk-K7W6Q6FN.js.map +0 -7
  349. /package/dist/safe-bash/chunks/{bz2-B2RXT4EX.js.map → bz2-ACU4EOVE.js.map} +0 -0
  350. /package/dist/safe-bash/chunks/{chunk-RNKTWFEM.js.map → chunk-CDBQXRWL.js.map} +0 -0
  351. /package/dist/safe-bash/chunks/{chunk-AFH57PPL.js.map → chunk-IEKESMO4.js.map} +0 -0
  352. /package/dist/safe-bash/chunks/{chunk-DPJWEGIX.js.map → chunk-JLBIUYT3.js.map} +0 -0
  353. /package/dist/safe-bash/chunks/{chunk-PVJJFCGA.js.map → chunk-M3GPCYSP.js.map} +0 -0
  354. /package/dist/safe-bash/chunks/{chunk-2KL6W6NB.js.map → chunk-O2EVBRKF.js.map} +0 -0
  355. /package/dist/safe-bash/chunks/{chunk-C7QNJ3D4.js.map → chunk-WYTI64IU.js.map} +0 -0
  356. /package/dist/safe-bash/chunks/{xz-AVXFDXW4.js.map → xz-U4QDTPZL.js.map} +0 -0
  357. /package/dist/safe-bash/chunks/{zstd-R6RPHJYO.js.map → zstd-OG5RPYXO.js.map} +0 -0
@@ -5,10 +5,72 @@ import { arithmeticEnd, prepareArithmetic } from "./arithmetic.js";
5
5
  import { arraySelector, compoundEntry, compoundHead, elementAssignment, getArrayAssignment, getArraySelector, isQuoteMarker, prefixNameQuoteGroups, scalarAssignmentName, setArrayAssignment, setArraySelector, setQuoteMarker } from "./arrays/syntax.js";
6
6
  import { conditionalBinary, conditionalUnary } from "./conditional.js";
7
7
  import { concatShellValues, shellValueBytes, shellValueFromBytes, shellValueText } from "../contracts/value.js";
8
+ const capturedSyntax = new WeakSet();
9
+ function indexedDeclarations(input) {
10
+ if (input === undefined)
11
+ return Object.freeze([]);
12
+ if (!Array.isArray(input) || input.length > 1 || Reflect.ownKeys(input).some(name => name !== "length" && name !== "0")) {
13
+ throw new TypeError("Invalid or duplicate indexed declarations");
14
+ }
15
+ if (!input.length)
16
+ return Object.freeze([]);
17
+ const slot = Object.getOwnPropertyDescriptor(input, "0");
18
+ if (!slot || !("value" in slot) || slot.value !== "readonly")
19
+ throw new TypeError("Invalid indexed declaration");
20
+ return Object.freeze(["readonly"]);
21
+ }
22
+ function syntaxEntries(input, key, allowed) {
23
+ if (input === undefined)
24
+ return Object.freeze([]);
25
+ if (!Array.isArray(input) || input.length > 1 || Reflect.ownKeys(input).some(name => name !== "length" && name !== "0")) {
26
+ throw new TypeError("Invalid or duplicate shell syntax declarations");
27
+ }
28
+ const entries = [];
29
+ for (let index = 0; index < input.length; index++) {
30
+ const slot = Object.getOwnPropertyDescriptor(input, String(index));
31
+ const entry = slot && "value" in slot ? slot.value : undefined;
32
+ if (!entry || typeof entry !== "object" || Reflect.ownKeys(entry).length !== 1)
33
+ throw new TypeError("Invalid shell syntax declaration");
34
+ const property = Object.getOwnPropertyDescriptor(entry, key);
35
+ if (!property || !("value" in property) || property.value !== allowed)
36
+ throw new TypeError("Invalid or reserved shell syntax declaration");
37
+ entries.push(Object.freeze({ [key]: allowed }));
38
+ }
39
+ return Object.freeze(entries);
40
+ }
41
+ export function captureShellSyntax(declarations = defaultSyntax) {
42
+ if (!declarations || typeof declarations !== "object" || Array.isArray(declarations))
43
+ throw new TypeError("Invalid shell syntax declarations");
44
+ if (capturedSyntax.has(declarations))
45
+ return declarations;
46
+ const prototype = Object.getPrototypeOf(declarations);
47
+ if (prototype !== null && prototype !== Object.prototype)
48
+ throw new TypeError("Invalid shell syntax declarations");
49
+ const properties = Object.getOwnPropertyDescriptors(declarations);
50
+ if (Reflect.ownKeys(properties).some(key => key !== "listTerminators" && key !== "specialParameters" && key !== "arrayKeys" && key !== "indexedDeclarations" && key !== "indexedElementOperators")
51
+ || Object.values(properties).some(property => !("value" in property)))
52
+ throw new TypeError("Invalid shell syntax declarations");
53
+ if (properties.arrayKeys && properties.arrayKeys.value !== true)
54
+ throw new TypeError("Invalid shell syntax capability");
55
+ if (properties.indexedElementOperators && properties.indexedElementOperators.value !== true)
56
+ throw new TypeError("Invalid shell syntax capability");
57
+ const indexed = indexedDeclarations(properties.indexedDeclarations?.value);
58
+ const syntax = Object.freeze({
59
+ listTerminators: syntaxEntries(properties.listTerminators?.value, "operator", "&"),
60
+ specialParameters: syntaxEntries(properties.specialParameters?.value, "name", "!"),
61
+ ...(properties.arrayKeys ? { arrayKeys: true } : {}),
62
+ ...(properties.indexedElementOperators ? { indexedElementOperators: true } : {}),
63
+ ...(indexed.length ? { indexedDeclarations: indexed } : {}),
64
+ });
65
+ capturedSyntax.add(syntax);
66
+ return syntax;
67
+ }
68
+ const defaultSyntax = captureShellSyntax({});
8
69
  export const compoundEntryWords = new WeakMap();
9
70
  export const expansionSpellings = new WeakMap();
10
71
  const documentValues = new WeakMap();
11
72
  const documentDelimiters = new WeakMap();
73
+ const hereDocumentSyntax = new WeakMap();
12
74
  export class HereDocumentSyntaxError extends Error {
13
75
  diagnostic;
14
76
  constructor(diagnostic) {
@@ -16,6 +78,172 @@ export class HereDocumentSyntaxError extends Error {
16
78
  this.diagnostic = diagnostic;
17
79
  }
18
80
  }
81
+ const scriptSeparators = new WeakMap();
82
+ const functionLayouts = new WeakMap();
83
+ export function functionReprintedLines(script) {
84
+ if (functionLayouts.has(script))
85
+ return functionLayouts.get(script);
86
+ const lines = new Map();
87
+ let line = 1;
88
+ let found = false;
89
+ let endedWithDocument = false;
90
+ function words(values) {
91
+ for (const word of values) {
92
+ if (word.printedNewlines === undefined)
93
+ return false;
94
+ line += word.printedNewlines;
95
+ }
96
+ return true;
97
+ }
98
+ function redirects(values) {
99
+ if (!values.length)
100
+ return true;
101
+ endedWithDocument = false;
102
+ if (!words(values.map(redirect => redirect.target)))
103
+ return false;
104
+ const documents = values.flatMap(redirect => redirect.document ? [redirect.document] : []);
105
+ if (documents.length) {
106
+ line++;
107
+ for (const document of documents) {
108
+ line += document.body.split("\n").length - 1 + document.delimiter.split("\n").length;
109
+ }
110
+ endedWithDocument = true;
111
+ }
112
+ return true;
113
+ }
114
+ function commands(body, inFunction) {
115
+ const separators = scriptSeparators.get(body.lists);
116
+ if (!separators)
117
+ return false;
118
+ for (let index = 0; index < body.lists.length; index++) {
119
+ for (const pipeline of body.lists[index].pipelines) {
120
+ for (const command of pipeline.commands)
121
+ if (!visit(command, inFunction))
122
+ return false;
123
+ }
124
+ if (index < body.lists.length - 1) {
125
+ line += endedWithDocument ? Number(inFunction || separators[index]) : Number(separators[index]) + Number(inFunction);
126
+ endedWithDocument = false;
127
+ }
128
+ }
129
+ return true;
130
+ }
131
+ function conditional(expression) {
132
+ switch (expression.kind) {
133
+ case "nonempty":
134
+ case "unary": return words([expression.operand]);
135
+ case "binary": return words([expression.left, expression.right]);
136
+ case "not": return conditional(expression.operand);
137
+ case "and":
138
+ case "or": return conditional(expression.left) && conditional(expression.right);
139
+ }
140
+ }
141
+ function visit(command, inFunction) {
142
+ lines.set(command, line);
143
+ if (command.kind === "simple") {
144
+ if (command.words.length) {
145
+ const firstNewlines = command.words[0].printedNewlines;
146
+ if (firstNewlines === undefined)
147
+ return false;
148
+ lines.set(command, line + firstNewlines);
149
+ }
150
+ if (!words(command.words))
151
+ return false;
152
+ }
153
+ else if (command.kind === "function") {
154
+ found = true;
155
+ line += 2;
156
+ if (command.body.kind === "group") {
157
+ lines.set(command.body, line - 1);
158
+ if (!commands(command.body.body, true))
159
+ return false;
160
+ line++;
161
+ endedWithDocument = false;
162
+ if (!redirects(command.body.redirects))
163
+ return false;
164
+ }
165
+ else {
166
+ if (!visit(command.body, true))
167
+ return false;
168
+ line++;
169
+ endedWithDocument = false;
170
+ }
171
+ }
172
+ else if (command.kind === "group" || command.kind === "subshell") {
173
+ const expanded = inFunction && command.kind === "group";
174
+ line += Number(expanded);
175
+ if (!commands(command.body, inFunction))
176
+ return false;
177
+ line += Number(expanded);
178
+ endedWithDocument = false;
179
+ }
180
+ else if (command.kind === "if") {
181
+ for (let index = 0; index < command.branches.length; index++) {
182
+ if (index)
183
+ line += 2;
184
+ const branch = command.branches[index];
185
+ if (!commands(branch.condition, inFunction))
186
+ return false;
187
+ line++;
188
+ endedWithDocument = false;
189
+ if (!commands(branch.body, inFunction))
190
+ return false;
191
+ }
192
+ if (command.otherwise) {
193
+ line += 2;
194
+ if (!commands(command.otherwise, inFunction))
195
+ return false;
196
+ }
197
+ line += command.branches.length;
198
+ }
199
+ else if (command.kind === "for") {
200
+ if (command.words && !words(command.words))
201
+ return false;
202
+ line += 2;
203
+ if (!commands(command.body, inFunction))
204
+ return false;
205
+ line++;
206
+ }
207
+ else if (command.kind === "while" || command.kind === "until") {
208
+ if (!commands(command.condition, inFunction))
209
+ return false;
210
+ line++;
211
+ endedWithDocument = false;
212
+ if (!commands(command.body, inFunction))
213
+ return false;
214
+ line++;
215
+ }
216
+ else if (command.kind === "arithmetic") {
217
+ line += command.source.split("\n").length - 1;
218
+ }
219
+ else if (command.kind === "conditional") {
220
+ if (!conditional(command.expression))
221
+ return false;
222
+ }
223
+ else if (command.kind === "case") {
224
+ if (!words([command.subject]))
225
+ return false;
226
+ for (let index = 0; index < command.clauses.length; index++) {
227
+ if (index)
228
+ line++;
229
+ const clause = command.clauses[index];
230
+ if (!words(clause.patterns))
231
+ return false;
232
+ line++;
233
+ if (!commands(clause.body, inFunction))
234
+ return false;
235
+ line++;
236
+ }
237
+ line++;
238
+ }
239
+ else
240
+ return false;
241
+ return redirects(command.redirects);
242
+ }
243
+ const result = commands(script, false) && found ? lines : undefined;
244
+ functionLayouts.set(script, result);
245
+ return result;
246
+ }
19
247
  function printedSimpleLines(lists, separators, budget) {
20
248
  budget.admit();
21
249
  const printedLines = new Map();
@@ -54,6 +282,8 @@ class Lexer {
54
282
  sourceOffset;
55
283
  ordinaryBacktick;
56
284
  sourceValues;
285
+ byteSource;
286
+ syntax;
57
287
  position = 0;
58
288
  operandDepth = 0;
59
289
  printedNewlineReduction = 0;
@@ -63,7 +293,7 @@ class Lexer {
63
293
  conditionalPattern;
64
294
  braceReplay;
65
295
  documents = [];
66
- constructor(budget, source, depth, warnings = [], lineOffset = 0, byteLocale = false, documentLine, partial = false, lineIndex = new SourceLineIndex(source, budget), sourceOffset = 0, ordinaryBacktick = false, sourceValues) {
296
+ constructor(budget, source, depth, warnings = [], lineOffset = 0, byteLocale = false, documentLine, partial = false, lineIndex = new SourceLineIndex(source, budget), sourceOffset = 0, ordinaryBacktick = false, sourceValues, byteSource = false, syntax = defaultSyntax) {
67
297
  this.budget = budget;
68
298
  this.source = source;
69
299
  this.depth = depth;
@@ -76,6 +306,8 @@ class Lexer {
76
306
  this.sourceOffset = sourceOffset;
77
307
  this.ordinaryBacktick = ordinaryBacktick;
78
308
  this.sourceValues = sourceValues;
309
+ this.byteSource = byteSource;
310
+ this.syntax = syntax;
79
311
  if (depth > 64)
80
312
  throw new ShellSyntaxError("Syntax nesting exceeds 64", 0);
81
313
  }
@@ -122,7 +354,7 @@ class Lexer {
122
354
  }
123
355
  const operator = this.conditionalPattern ? undefined : /^(?:;;&|<<<|<<-|&>>|;&|&&|\|\||\|&|>>|>&|<&|>\||<<|;;|&>|[;\n|&()<>])/u.exec(logical)?.[0];
124
356
  if (operator) {
125
- if (operator === "&>>")
357
+ if (operator === "&>>" || operator === "&" && !this.syntax.listTerminators.length)
126
358
  this.error(`Unsupported operator ${operator}`);
127
359
  this.position = ends[operator.length - 1];
128
360
  if (operator === "<<" || operator === "<<-")
@@ -142,13 +374,14 @@ class Lexer {
142
374
  document = {
143
375
  delimiter: word.parts.map((part) => part.kind === "text" ? part.value : "").join(""),
144
376
  quoted: word.parts.some((part) => part.quoted), stripTabs: delimiterOperator === "<<-", offset,
145
- body: "", endLine: this.lineAt(offset), depth: this.depth,
377
+ body: "", endLine: this.lineAt(offset), depth: this.depth, ...(this.byteSource ? { byteSource: true } : {}),
146
378
  };
147
379
  if (this.sourceValues?.size) {
148
380
  this.budget.admit(word.parts.length + 1);
149
381
  documentDelimiters.set(document, shellValueBytes(concatShellValues(word.parts.map(part => part.kind === "text" ? part.byteValue ?? part.value : ""))));
150
382
  }
151
383
  this.documents.push(document);
384
+ hereDocumentSyntax.set(document, this.syntax);
152
385
  }
153
386
  this.budget.admit();
154
387
  return { kind: "word", value: word.plain ?? "", offset, end: this.position, word: { ...word, spelling: this.source.slice(offset, this.position) }, ...(document ? { document } : {}) };
@@ -235,7 +468,7 @@ class Lexer {
235
468
  if (opaque !== undefined) {
236
469
  if (text) {
237
470
  this.budget.admit(2);
238
- yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true }] };
471
+ yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true, ...(this.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(text, "latin1")) } : {}) }] };
239
472
  text = "";
240
473
  }
241
474
  this.budget.admit(2);
@@ -244,7 +477,7 @@ class Lexer {
244
477
  else if (current === "$" || current === "`") {
245
478
  if (text) {
246
479
  this.budget.admit(2);
247
- yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true }] };
480
+ yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true, ...(this.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(text, "latin1")) } : {}) }] };
248
481
  text = "";
249
482
  }
250
483
  const offset = this.position;
@@ -276,13 +509,13 @@ class Lexer {
276
509
  }
277
510
  if (text.length >= 1024) {
278
511
  this.budget.admit(2);
279
- yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true }] };
512
+ yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true, ...(this.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(text, "latin1")) } : {}) }] };
280
513
  text = "";
281
514
  }
282
515
  }
283
516
  if (text) {
284
517
  this.budget.admit(2);
285
- yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true }] };
518
+ yield { offset: 0, parts: [{ kind: "text", value: text, quoted: true, ...(this.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(text, "latin1")) } : {}) }] };
286
519
  }
287
520
  }
288
521
  documentSubstitutionError(source, error, backtick = false) {
@@ -374,6 +607,8 @@ class Lexer {
374
607
  const conditionalPattern = terminator === undefined ? this.conditionalPattern : undefined;
375
608
  let plain = true;
376
609
  const text = (value, quoted, synthetic = false, start = this.position, end = start + shellValueText(value).length, ansi = false) => {
610
+ if (this.byteSource && typeof value === "string" && [...value].some(character => character.charCodeAt(0) > 127))
611
+ value = shellValueFromBytes(Buffer.from(value, "latin1"));
377
612
  const projection = shellValueText(value);
378
613
  if (conditionalPattern === "regex" && regexBracket && quoted && projection.length) {
379
614
  regexBracketFirst = false;
@@ -598,6 +833,10 @@ class Lexer {
598
833
  if (character === "'") {
599
834
  const nul = bytes.indexOf(0);
600
835
  const raw = Uint8Array.from(nul < 0 ? bytes : bytes.slice(0, nul));
836
+ if (this.byteSource) {
837
+ this.budget.admit(2);
838
+ return shellValueFromBytes(raw);
839
+ }
601
840
  const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
602
841
  try {
603
842
  return decoder.decode(raw);
@@ -611,7 +850,7 @@ class Lexer {
611
850
  }
612
851
  }
613
852
  if (character !== "\\") {
614
- bytes.push(...encoder.encode(character));
853
+ bytes.push(...(this.byteSource ? Buffer.from(character, "latin1") : encoder.encode(character)));
615
854
  continue;
616
855
  }
617
856
  const escape = this.source[this.position++];
@@ -684,7 +923,7 @@ class Lexer {
684
923
  this.error("Unterminated command substitution");
685
924
  this.position++;
686
925
  try {
687
- parts.push({ kind: "substitution", script: parseSource(source, this.depth + this.operandDepth + 1, this.warnings, line - 1, this.byteLocale, this.budget, this.documentLine === undefined, sourceValues), line, quoted });
926
+ parts.push({ kind: "substitution", form: "backtick", script: parseSource(source, this.depth + this.operandDepth + 1, this.warnings, line - 1, this.byteLocale, this.budget, this.documentLine === undefined, sourceValues, this.byteSource, this.syntax), line, quoted });
688
927
  }
689
928
  catch (error) {
690
929
  if (this.documentLine === undefined || !(error instanceof ShellSyntaxError) || /nesting|exceeds/u.test(error.reason))
@@ -699,7 +938,8 @@ class Lexer {
699
938
  return;
700
939
  }
701
940
  this.position++;
702
- if (this.source[this.position] === "$" || (!quoted && ["'", '"'].includes(this.source[this.position] ?? "")))
941
+ if (this.source[this.position] === "$" || this.source[this.position] === "!" && !this.syntax.specialParameters.length
942
+ || (!quoted && ["'", '"'].includes(this.source[this.position] ?? "")))
703
943
  this.error("Unsupported shell quoting or special parameter");
704
944
  if (this.source.startsWith("((", this.position)) {
705
945
  const start = this.position + 2;
@@ -714,7 +954,7 @@ class Lexer {
714
954
  let script;
715
955
  try {
716
956
  this.budget.admit();
717
- nested = new Parser(this.budget, this.source.slice(start), this.depth + this.operandDepth + 1, this.warnings, this.lineAt(start) - 1, undefined, this.byteLocale, false, this.lineIndex, this.sourceOffset + start, false, this.sourceValues);
957
+ nested = new Parser(this.budget, this.source.slice(start), this.depth + this.operandDepth + 1, this.warnings, this.lineAt(start) - 1, undefined, this.byteLocale, false, this.lineIndex, this.sourceOffset + start, false, this.sourceValues, this.byteSource, this.syntax);
718
958
  script = nested.script(new Set([")"]));
719
959
  }
720
960
  catch (error) {
@@ -736,18 +976,20 @@ class Lexer {
736
976
  this.unprintedWords++;
737
977
  else
738
978
  this.printedNewlineReduction += this.source.slice(start, this.position - 1).split("\n").length - 1 - script.printedNewlines;
739
- parts.push({ kind: "substitution", script, line, sourceLine: script.line ?? line, quoted });
979
+ parts.push({ kind: "substitution", form: "dollar-parenthesis", script, line, sourceLine: script.line ?? line, quoted });
740
980
  }
741
981
  else if (this.source[this.position] === "{") {
742
982
  this.position++;
743
983
  const parameterStart = this.position - 2;
744
- const listing = this.source[this.position] === "!" && /[a-zA-Z_]/u.test(this.source[this.position + 1] ?? "");
984
+ const listing = this.source[this.position] === "!" && /[a-zA-Z_0-9]/u.test(this.source[this.position + 1] ?? "");
745
985
  if (listing)
746
986
  this.position++;
747
- const length = !listing && this.source[this.position] === "#" && /[a-zA-Z_!]/u.test(this.source[this.position + 1] ?? "");
987
+ const length = !listing && this.source[this.position] === "#" && (/[a-zA-Z_0-9]/u.test(this.source[this.position + 1] ?? "")
988
+ || this.syntax.specialParameters.some(parameter => parameter.name === this.source[this.position + 1]));
748
989
  if (length)
749
990
  this.position++;
750
- const name = /^(?:[a-zA-Z_][a-zA-Z_0-9]*|[0-9]+|[?@*#!-])/u.exec(this.source.slice(this.position))?.[0];
991
+ const specialParameter = this.syntax.specialParameters.find(parameter => parameter.name === this.source[this.position]);
992
+ const name = specialParameter?.name ?? /^(?:[a-zA-Z_][a-zA-Z_0-9]*|[0-9]+|[?@*#-])/u.exec(this.source.slice(this.position))?.[0];
751
993
  if (!name)
752
994
  this.error("Unsupported parameter expansion");
753
995
  this.position += name.length;
@@ -770,11 +1012,16 @@ class Lexer {
770
1012
  this.error("Unterminated indexed-array subscript");
771
1013
  selector = arraySelector(this.source.slice(start, end), start, this.budget, keyWord);
772
1014
  this.position = end + 1;
773
- if (this.source[this.position] !== "}" && this.source[this.position] !== "@")
1015
+ if (this.source[this.position] !== "}" && this.source[this.position] !== "@" && !(this.syntax.indexedElementOperators && !length && selector.kind === "element"
1016
+ && (this.source[this.position] === "-" || this.source[this.position] === "+")))
774
1017
  this.error("Unsupported indexed-array operator");
775
1018
  }
776
1019
  if (listing && selector?.kind === "element")
777
1020
  this.error("Unsupported indirect parameter expansion");
1021
+ if (listing && selector?.kind === "members" && this.syntax.arrayKeys) {
1022
+ this.budget.admit();
1023
+ selector = { kind: "keys", separator: selector.separator };
1024
+ }
778
1025
  let transform;
779
1026
  if (this.source[this.position] === "@") {
780
1027
  const operation = this.source[this.position + 1];
@@ -834,7 +1081,7 @@ class Lexer {
834
1081
  }
835
1082
  else {
836
1083
  this.position++;
837
- const part = { kind: "variable", name, quoted, line, ...(prefixNames ? { prefixNames } : {}), ...(transform ? { transform } : {}), ...(length ? { length } : {}), ...(operator ? { operator, alternate: alternate } : {}), ...(replacement ? { replacement } : {}), ...(substring ? { substring } : {}) };
1084
+ const part = { kind: "variable", name, quoted, line, ...(specialParameter ? { specialParameter } : {}), ...(prefixNames ? { prefixNames } : {}), ...(transform ? { transform } : {}), ...(length ? { length } : {}), ...(operator ? { operator, alternate: alternate } : {}), ...(replacement ? { replacement } : {}), ...(substring ? { substring } : {}) };
838
1085
  if (listing && selector)
839
1086
  part.keys = true;
840
1087
  if (selector)
@@ -843,10 +1090,11 @@ class Lexer {
843
1090
  }
844
1091
  }
845
1092
  else {
846
- const name = /^(?:[a-zA-Z_][a-zA-Z_0-9]*|[?@*#!0-9-])/u.exec(this.source.slice(this.position))?.[0];
1093
+ const specialParameter = this.syntax.specialParameters.find(parameter => parameter.name === this.source[this.position]);
1094
+ const name = specialParameter?.name ?? /^(?:[a-zA-Z_][a-zA-Z_0-9]*|[?@*#0-9-])/u.exec(this.source.slice(this.position))?.[0];
847
1095
  if (name) {
848
1096
  this.position += name.length;
849
- parts.push({ kind: "variable", name, quoted, line });
1097
+ parts.push({ kind: "variable", name, quoted, line, ...(specialParameter ? { specialParameter } : {}) });
850
1098
  }
851
1099
  else
852
1100
  parts.push({ kind: "text", value: "$", quoted });
@@ -865,12 +1113,12 @@ class Parser {
865
1113
  nesting = 0;
866
1114
  openCommands = [];
867
1115
  completedInput;
868
- constructor(budget, source, depth, warnings = [], lineOffset = 0, position, byteLocale = false, partial = false, lineIndex = new SourceLineIndex(source, budget), sourceOffset = 0, ordinaryBacktick = false, sourceValues) {
1116
+ constructor(budget, source, depth, warnings = [], lineOffset = 0, position, byteLocale = false, partial = false, lineIndex = new SourceLineIndex(source, budget), sourceOffset = 0, ordinaryBacktick = false, sourceValues, byteSource = false, syntax = defaultSyntax) {
869
1117
  this.budget = budget;
870
1118
  if (position === undefined && depth === 0 && source.includes("\0"))
871
1119
  throw new ShellSyntaxError("NUL bytes are not valid shell source", source.indexOf("\0"));
872
1120
  budget.admit();
873
- this.lexer = new Lexer(budget, source, depth, warnings, lineOffset, byteLocale, undefined, partial, lineIndex, sourceOffset, ordinaryBacktick, sourceValues);
1121
+ this.lexer = new Lexer(budget, source, depth, warnings, lineOffset, byteLocale, undefined, partial, lineIndex, sourceOffset, ordinaryBacktick, sourceValues, byteSource, syntax);
874
1122
  this.lexer.position = position ?? 0;
875
1123
  this.current = this.lexer.next();
876
1124
  }
@@ -915,13 +1163,14 @@ class Parser {
915
1163
  this.newlines();
916
1164
  pipelines.push(this.pipeline());
917
1165
  }
918
- lists.push({ pipelines, operators, ...(this.is("&") ? { background: true } : {}) });
1166
+ const terminator = this.is("&") ? Object.freeze({ operator: "&", offset: this.current.offset, line: this.lexer.lineAt(this.current.offset) }) : undefined;
1167
+ lists.push({ pipelines, operators, ...(terminator ? { terminator } : {}) });
919
1168
  separators.push(this.is("\n"));
920
1169
  if (captureInputUnits && this.is("\n"))
921
1170
  this.completedInput.count = lists.length;
922
1171
  if (inputUnit && this.is("\n"))
923
1172
  break;
924
- if (this.is(";") || this.is("&") || this.is("\n")) {
1173
+ if (terminator || this.is(";") || this.is("\n")) {
925
1174
  this.advance();
926
1175
  if (captureInputUnits && this.is("\n"))
927
1176
  this.completedInput.count = lists.length;
@@ -933,6 +1182,7 @@ class Parser {
933
1182
  this.error("Expected command separator");
934
1183
  }
935
1184
  const printed = printedSimpleLines(lists, separators, this.budget);
1185
+ scriptSeparators.set(lists, Object.freeze(separators));
936
1186
  return { lists, line, ...printed };
937
1187
  }
938
1188
  pipeline() {
@@ -1229,6 +1479,12 @@ class Parser {
1229
1479
  this.error(`Unexpected or unsupported keyword ${this.current.value}`);
1230
1480
  const words = [];
1231
1481
  const redirects = [];
1482
+ const indexedDeclaration = () => {
1483
+ let index = 0;
1484
+ while (words[index] && scalarAssignmentName(words[index]))
1485
+ index++;
1486
+ return this.lexer.syntax.indexedDeclarations?.some(name => name === words[index]?.plain) === true;
1487
+ };
1232
1488
  let line;
1233
1489
  while (true) {
1234
1490
  const wordLine = this.lexer.lineAt(Math.max(this.current.offset, this.current.end - 1));
@@ -1263,7 +1519,7 @@ class Parser {
1263
1519
  setArrayAssignment(word, { kind: "compound", ...head, entries });
1264
1520
  }
1265
1521
  else {
1266
- const assignment = words.every(previous => getArrayAssignment(previous) || scalarAssignmentName(previous)) ? elementAssignment(word, this.budget, source => parseArraySubscript(source, this.budget, this.lexer.byteLocale, this.lexer.depth), (source, start) => { const lexer = new Lexer(this.budget, source, this.lexer.depth, [], 0, this.lexer.byteLocale); lexer.position = start; lexer.word("]"); return lexer.source[lexer.position] === "]" ? lexer.position : -1; }) : undefined;
1522
+ const assignment = words.every(previous => getArrayAssignment(previous) || scalarAssignmentName(previous)) ? elementAssignment(word, this.budget, source => parseArraySubscript(source, this.budget, this.lexer.byteLocale, this.lexer.depth, this.lexer.byteSource, this.lexer.syntax), (source, start) => { const lexer = new Lexer(this.budget, source, this.lexer.depth, [], 0, this.lexer.byteLocale, undefined, false, undefined, 0, false, undefined, this.lexer.byteSource, this.lexer.syntax); lexer.position = start; lexer.word("]"); return lexer.source[lexer.position] === "]" ? lexer.position : -1; }) : undefined;
1267
1523
  if (assignment)
1268
1524
  setArrayAssignment(word, assignment);
1269
1525
  }
@@ -1274,7 +1530,7 @@ class Parser {
1274
1530
  }
1275
1531
  if (!words.length && !redirects.length)
1276
1532
  this.error("Expected command");
1277
- if (words.some(word => getArrayAssignment(word)) && words.some(word => !getArrayAssignment(word) && !scalarAssignmentName(word)))
1533
+ if (words.some(word => getArrayAssignment(word)) && words.some(word => !getArrayAssignment(word) && !scalarAssignmentName(word)) && !indexedDeclaration())
1278
1534
  this.error("Indexed-array command prefixes are unsupported");
1279
1535
  return { kind: "simple", words, redirects, ...(line === undefined ? {} : { line }) };
1280
1536
  }
@@ -1309,15 +1565,35 @@ class Parser {
1309
1565
  return { descriptor, operator, target: target.word, line: this.lexer.lineAt(Math.max(target.offset, target.end - 1)), ...((operator === "<&" || operator === ">&") && this.lexer.source[target.end - 1] === "-" ? { move: true } : {}), ...(target.document ? { document: target.document } : {}) };
1310
1566
  }
1311
1567
  }
1312
- export function parseShell(source, depth = 0, options = {}) {
1313
- const budget = new ParseBudget(options.maxParseUnits);
1568
+ export function parseCompoundArrayValue(source, byteLocale, byteSource, syntax = defaultSyntax, budget = new ParseBudget()) {
1569
+ const lexer = new Lexer(budget, source, 0, [], 0, byteLocale, undefined, false, undefined, 0, false, undefined, byteSource, syntax);
1570
+ if (lexer.next().value !== "(")
1571
+ throw new ShellSyntaxError("Expected indexed-array compound value", 0);
1572
+ const entries = [];
1573
+ for (let token = lexer.next(); token.kind !== "end" && token.value !== ")"; token = lexer.next()) {
1574
+ if (token.value === "\n")
1575
+ continue;
1576
+ if (token.kind !== "word")
1577
+ throw new ShellSyntaxError("Unsupported indexed-array compound value", token.offset);
1578
+ const entry = compoundEntry(token.word, budget);
1579
+ if (entry.index) {
1580
+ budget.admit();
1581
+ compoundEntryWords.set(entry, token.word);
1582
+ }
1583
+ entries.push(entry);
1584
+ }
1585
+ return entries;
1586
+ }
1587
+ export function parseShell(source, depth = 0, options = {}, syntax) {
1588
+ const budget = new ParseBudget("maxParseUnits" in options ? options.maxParseUnits : undefined);
1589
+ const captured = captureShellSyntax(syntax === undefined ? ("maxParseUnits" in options ? undefined : options) : syntax);
1314
1590
  const warnings = [];
1315
- const script = parseSource(source, depth, warnings, 0, false, budget);
1591
+ const script = parseSource(source, depth, warnings, 0, false, budget, false, undefined, false, captured);
1316
1592
  budget.admit();
1317
1593
  return { ...script, ...(warnings.length ? { warnings } : {}) };
1318
1594
  }
1319
- export function parseArraySubscript(source, budget, byteLocale = false, depth = 0) {
1320
- const lexer = new Lexer(budget, source, depth, [], 0, byteLocale);
1595
+ export function parseArraySubscript(source, budget, byteLocale = false, depth = 0, byteSource = false, syntax = defaultSyntax) {
1596
+ const lexer = new Lexer(budget, source, depth, [], 0, byteLocale, undefined, false, undefined, 0, false, undefined, byteSource, syntax);
1321
1597
  return lexer.word("\0");
1322
1598
  }
1323
1599
  export function parseBraceWord(source, opaque, budget) {
@@ -1326,31 +1602,39 @@ export function parseBraceWord(source, opaque, budget) {
1326
1602
  lexer.braceReplay = opaque;
1327
1603
  return lexer.word();
1328
1604
  }
1329
- export function* hereDocumentWords(document, line, byteLocale, warnings, budget = new ParseBudget()) {
1605
+ export function hereDocumentWords(document, line, byteLocale, warnings, budgetOrSyntax = new ParseBudget(), syntax) {
1606
+ const budget = budgetOrSyntax instanceof ParseBudget ? budgetOrSyntax : new ParseBudget();
1607
+ const captured = captureShellSyntax(syntax === undefined ? (budgetOrSyntax instanceof ParseBudget ? hereDocumentSyntax.get(document) : budgetOrSyntax) : syntax);
1330
1608
  const values = documentValues.get(document);
1331
- if (document.quoted) {
1332
- let start = 0;
1333
- for (const [position, value] of values ?? []) {
1334
- budget.admit(4);
1335
- if (start < position)
1336
- yield { offset: document.offset, parts: [{ kind: "text", value: document.body.slice(start, position), quoted: true }] };
1337
- yield { offset: document.offset, parts: [{ kind: "text", value: shellValueText(value), byteValue: value, quoted: true }] };
1338
- start = position + 1;
1609
+ return (function* () {
1610
+ if (document.quoted) {
1611
+ let start = 0;
1612
+ for (const [position, value] of values ?? []) {
1613
+ budget.admit(4);
1614
+ if (start < position)
1615
+ yield { offset: document.offset, parts: [{ kind: "text", value: document.body.slice(start, position), quoted: true, ...(document.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(document.body.slice(start, position), "latin1")) } : {}) }] };
1616
+ yield { offset: document.offset, parts: [{ kind: "text", value: shellValueText(value), byteValue: value, quoted: true }] };
1617
+ start = position + 1;
1618
+ }
1619
+ budget.admit(2);
1620
+ yield { offset: document.offset, parts: [{ kind: "text", value: document.body.slice(start), quoted: true, ...(document.byteSource ? { byteValue: shellValueFromBytes(Buffer.from(document.body.slice(start), "latin1")) } : {}) }] };
1339
1621
  }
1340
- budget.admit(2);
1341
- yield { offset: document.offset, parts: [{ kind: "text", value: document.body.slice(start), quoted: true }] };
1342
- }
1343
- else {
1344
- budget.admit();
1345
- yield* new Lexer(budget, document.body, document.depth, warnings, line - 1, byteLocale, line, false, undefined, 0, false, values).documentWords();
1346
- }
1622
+ else {
1623
+ budget.admit();
1624
+ yield* new Lexer(budget, document.body, document.depth, warnings, line - 1, byteLocale, line, false, undefined, 0, false, values, document.byteSource, captured).documentWords();
1625
+ }
1626
+ })();
1347
1627
  }
1348
- export function parseShellUnit(source, position = 0, byteLocale = false, budget = new ParseBudget(), lineIndex = new SourceLineIndex(source, budget), sourceValues) {
1628
+ export function parseShellUnit(source, position = 0, byteLocale = false, budgetOrByteSource = new ParseBudget(), lineIndexOrSyntax, sourceValues, byteSource = false, syntax) {
1629
+ const budget = budgetOrByteSource instanceof ParseBudget ? budgetOrByteSource : new ParseBudget();
1630
+ const lineIndex = lineIndexOrSyntax instanceof SourceLineIndex ? lineIndexOrSyntax : new SourceLineIndex(source, budget);
1631
+ const captured = captureShellSyntax(syntax === undefined ? (lineIndexOrSyntax instanceof SourceLineIndex ? undefined : lineIndexOrSyntax) : syntax);
1632
+ const raw = typeof budgetOrByteSource === "boolean" ? budgetOrByteSource : byteSource;
1349
1633
  const warnings = [];
1350
1634
  budget.admit();
1351
1635
  if (lineIndex.source !== source || lineIndex.budget !== budget)
1352
1636
  throw new TypeError("Source line index belongs to a different source or parse budget");
1353
- const parser = new Parser(budget, source, 0, warnings, 0, position, byteLocale, false, lineIndex, 0, false, sourceValues);
1637
+ const parser = new Parser(budget, source, 0, warnings, 0, position, byteLocale, false, lineIndex, 0, false, sourceValues, raw, captured);
1354
1638
  const script = parser.script(new Set(), true);
1355
1639
  const next = parser.current.end;
1356
1640
  const nul = source.indexOf("\0", position);
@@ -1359,13 +1643,16 @@ export function parseShellUnit(source, position = 0, byteLocale = false, budget
1359
1643
  budget.admit(2);
1360
1644
  return { script: { ...script, ...(warnings.length ? { warnings } : {}) }, next };
1361
1645
  }
1362
- export function parseShellInputUnit(source, byteLocale = false, budget = new ParseBudget(), lineIndex = new SourceLineIndex(source, budget)) {
1646
+ export function parseShellInputUnit(source, byteLocale = false, budgetOrSyntax = new ParseBudget(), suppliedLineIndex, syntax) {
1647
+ const budget = budgetOrSyntax instanceof ParseBudget ? budgetOrSyntax : new ParseBudget();
1648
+ const lineIndex = suppliedLineIndex ?? new SourceLineIndex(source, budget);
1649
+ const captured = captureShellSyntax(syntax === undefined ? (budgetOrSyntax instanceof ParseBudget ? undefined : budgetOrSyntax) : syntax);
1363
1650
  const warnings = [];
1364
1651
  try {
1365
1652
  budget.admit();
1366
1653
  if (lineIndex.source !== source || lineIndex.budget !== budget)
1367
1654
  throw new TypeError("Source line index belongs to a different source or parse budget");
1368
- const parser = new Parser(budget, source, 0, warnings, 0, 0, byteLocale, true, lineIndex);
1655
+ const parser = new Parser(budget, source, 0, warnings, 0, 0, byteLocale, true, lineIndex, 0, false, undefined, false, captured);
1369
1656
  const script = parser.script(new Set(), true);
1370
1657
  budget.admit(2);
1371
1658
  return { script: { ...script, ...(warnings.length ? { warnings } : {}) }, next: parser.current.end };
@@ -1378,10 +1665,10 @@ export function parseShellInputUnit(source, byteLocale = false, budget = new Par
1378
1665
  throw error;
1379
1666
  }
1380
1667
  }
1381
- function parseSource(source, depth, warnings, lineOffset, byteLocale, budget, ordinaryBacktick = false, sourceValues) {
1668
+ function parseSource(source, depth, warnings, lineOffset, byteLocale, budget, ordinaryBacktick = false, sourceValues, byteSource = false, syntax = defaultSyntax) {
1382
1669
  budget.admit();
1383
1670
  const warningCount = warnings.length;
1384
- const parser = new Parser(budget, source, depth, warnings, lineOffset, undefined, byteLocale, false, undefined, 0, ordinaryBacktick, sourceValues);
1671
+ const parser = new Parser(budget, source, depth, warnings, lineOffset, undefined, byteLocale, false, undefined, 0, ordinaryBacktick, sourceValues, byteSource, syntax);
1385
1672
  try {
1386
1673
  const script = parser.script(new Set(), false, ordinaryBacktick);
1387
1674
  if (parser.current.kind !== "end")