wsemi 1.9.13 → 1.9.15

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 (516) hide show
  1. package/README.md +1 -1
  2. package/dist/wsemi.umd.js +7 -7
  3. package/dist/wsemi.umd.js.map +1 -1
  4. package/docs/-_class.mjs.html +1 -1
  5. package/docs/-_const.mjs.html +1 -1
  6. package/docs/-_detector.mjs.html +1 -1
  7. package/docs/-_optNum.mjs.html +1 -1
  8. package/docs/ab2blob.mjs.html +1 -1
  9. package/docs/ab2u8arr.mjs.html +1 -1
  10. package/docs/addExcelWorksheetFromData.mjs.html +1 -1
  11. package/docs/addMonth.mjs.html +1 -1
  12. package/docs/aes2str.mjs.html +1 -1
  13. package/docs/alive.mjs.html +106 -5
  14. package/docs/arr2dt.mjs.html +1 -1
  15. package/docs/arrAccum.mjs.html +1 -1
  16. package/docs/arrAdd.mjs.html +1 -1
  17. package/docs/arrAt.mjs.html +1 -1
  18. package/docs/arrDiff.mjs.html +1 -1
  19. package/docs/arrFilterByKeywords.mjs.html +1 -1
  20. package/docs/arrFilterByNum.mjs.html +1 -1
  21. package/docs/arrFilterByPnum.mjs.html +1 -1
  22. package/docs/arrFilterByPnumAndToLog.mjs.html +1 -1
  23. package/docs/arrFind.mjs.html +1 -1
  24. package/docs/arrGroupByMaxmin.mjs.html +1 -1
  25. package/docs/arrHas.mjs.html +1 -1
  26. package/docs/arrInsert.mjs.html +1 -1
  27. package/docs/arrLookupByMaxmin.mjs.html +1 -1
  28. package/docs/arrMax.mjs.html +1 -1
  29. package/docs/arrMin.mjs.html +1 -1
  30. package/docs/arrMulti.mjs.html +1 -1
  31. package/docs/arrNorm.mjs.html +1 -1
  32. package/docs/arrProduct.mjs.html +1 -1
  33. package/docs/arrPull.mjs.html +1 -1
  34. package/docs/arrPullAt.mjs.html +1 -1
  35. package/docs/arrReduce.mjs.html +1 -1
  36. package/docs/arrReverse.mjs.html +1 -1
  37. package/docs/arrSep.mjs.html +1 -1
  38. package/docs/arrSort.mjs.html +1 -1
  39. package/docs/asind.mjs.html +1 -1
  40. package/docs/atan2d.mjs.html +1 -1
  41. package/docs/atand.mjs.html +1 -1
  42. package/docs/attstr.mjs.html +1 -1
  43. package/docs/b642obj.mjs.html +1 -1
  44. package/docs/b642str.mjs.html +1 -1
  45. package/docs/b642u16arr.mjs.html +1 -1
  46. package/docs/b642u8arr.mjs.html +1 -1
  47. package/docs/binstr.mjs.html +1 -1
  48. package/docs/blob2ab.mjs.html +1 -1
  49. package/docs/blob2b64.mjs.html +1 -1
  50. package/docs/blob2str.mjs.html +1 -1
  51. package/docs/blob2u8arr.mjs.html +1 -1
  52. package/docs/blobs2b64s.mjs.html +1 -1
  53. package/docs/blobs2u8arrs.mjs.html +1 -1
  54. package/docs/bodyLog.mjs.html +1 -1
  55. package/docs/browserView.mjs.html +1 -1
  56. package/docs/browserViewFromBlob.mjs.html +1 -1
  57. package/docs/browserViewFromText.mjs.html +1 -1
  58. package/docs/browserViewFromU8arr.mjs.html +1 -1
  59. package/docs/bs2u8arr.mjs.html +1 -1
  60. package/docs/bufRead.mjs.html +1 -1
  61. package/docs/bufReadDbl.mjs.html +1 -1
  62. package/docs/bufWrite.mjs.html +1 -1
  63. package/docs/bufWriteDbl.mjs.html +1 -1
  64. package/docs/cache.mjs.html +3 -3
  65. package/docs/cacheBd.mjs.html +1 -1
  66. package/docs/cacheSt.mjs.html +2 -2
  67. package/docs/cbol.mjs.html +1 -1
  68. package/docs/cdbl.mjs.html +1 -1
  69. package/docs/ceil.mjs.html +1 -1
  70. package/docs/cfilesize.mjs.html +1 -1
  71. package/docs/cfinancial.mjs.html +1 -1
  72. package/docs/cint.mjs.html +1 -1
  73. package/docs/clearXSS.mjs.html +1 -1
  74. package/docs/clearXSSDyn.mjs.html +1 -1
  75. package/docs/color.mjs.html +1 -1
  76. package/docs/composeToTree.mjs.html +1 -1
  77. package/docs/convertToTree.mjs.html +1 -1
  78. package/docs/copyStrToClipboard.mjs.html +1 -1
  79. package/docs/cosd.mjs.html +1 -1
  80. package/docs/cotd.mjs.html +1 -1
  81. package/docs/createExcelWorkbook.mjs.html +1 -1
  82. package/docs/cscd.mjs.html +1 -1
  83. package/docs/cstr.mjs.html +1 -1
  84. package/docs/day2cht.mjs.html +1 -1
  85. package/docs/debounce.mjs.html +1 -1
  86. package/docs/delay.mjs.html +1 -1
  87. package/docs/detectXSS.mjs.html +1 -1
  88. package/docs/detectXSSDyn.mjs.html +1 -1
  89. package/docs/dig.mjs.html +1 -1
  90. package/docs/digExp.mjs.html +1 -1
  91. package/docs/domAlert.mjs.html +1 -1
  92. package/docs/domAppend.mjs.html +1 -1
  93. package/docs/domCancelEvent.mjs.html +1 -1
  94. package/docs/domCompareText.mjs.html +1 -1
  95. package/docs/domConvertToPic.mjs.html +1 -1
  96. package/docs/domConvertToPicDyn.mjs.html +1 -1
  97. package/docs/domDetect.mjs.html +1 -1
  98. package/docs/domDrag.mjs.html +1 -1
  99. package/docs/domDragBarAndScroll.mjs.html +1 -1
  100. package/docs/domDragPointer.mjs.html +1 -1
  101. package/docs/domDragPreview.mjs.html +1 -1
  102. package/docs/domDropFiles.mjs.html +1 -1
  103. package/docs/domElementsFromPoint.mjs.html +1 -1
  104. package/docs/domFadeIn.mjs.html +1 -1
  105. package/docs/domFadeOut.mjs.html +1 -1
  106. package/docs/domFind.mjs.html +1 -1
  107. package/docs/domFinds.mjs.html +1 -1
  108. package/docs/domGetAttr.mjs.html +1 -1
  109. package/docs/domGetBoudRect.mjs.html +1 -1
  110. package/docs/domGetBoudRectRefSelf.mjs.html +1 -1
  111. package/docs/domGetFileAccept.mjs.html +1 -1
  112. package/docs/domGetFiles.mjs.html +1 -1
  113. package/docs/domGetParents.mjs.html +1 -1
  114. package/docs/domGetPointFromEvent.mjs.html +1 -1
  115. package/docs/domGetScrollableParent.mjs.html +1 -1
  116. package/docs/domGetWindowSize.mjs.html +1 -1
  117. package/docs/domIsClientXYIn.mjs.html +1 -1
  118. package/docs/domIsFocused.mjs.html +1 -1
  119. package/docs/domIsRendered.mjs.html +1 -1
  120. package/docs/domIsStable.mjs.html +1 -1
  121. package/docs/domIsVisible.mjs.html +1 -1
  122. package/docs/domPrepend.mjs.html +1 -1
  123. package/docs/domRemove.mjs.html +1 -1
  124. package/docs/domRenderMarkdownMind.mjs.html +1 -1
  125. package/docs/domRenderMarkdownMindDyn.mjs.html +1 -1
  126. package/docs/domRipple.mjs.html +1 -1
  127. package/docs/domScrollIntoView.mjs.html +1 -1
  128. package/docs/domScrollTo.mjs.html +1 -1
  129. package/docs/domSetAttr.mjs.html +1 -1
  130. package/docs/domShowImages.mjs.html +1 -1
  131. package/docs/domShowImagesDyn.mjs.html +1 -1
  132. package/docs/domShowInputAndGetFiles.mjs.html +1 -1
  133. package/docs/domShowInputAndGetFilesU8Arrs.mjs.html +1 -1
  134. package/docs/domShowInputDatatime.mjs.html +1 -1
  135. package/docs/domTooltip.mjs.html +1 -1
  136. package/docs/domTriggerEvent.mjs.html +1 -1
  137. package/docs/domVirtualCreate.mjs.html +1 -1
  138. package/docs/domVirtualCreateQueue.mjs.html +1 -1
  139. package/docs/downloadExcelFileFromData.mjs.html +1 -1
  140. package/docs/downloadExcelFileFromDataDyn.mjs.html +1 -1
  141. package/docs/downloadFileFromB64.mjs.html +1 -1
  142. package/docs/downloadFileFromBlob.mjs.html +1 -1
  143. package/docs/downloadFileFromText.mjs.html +1 -1
  144. package/docs/downloadFileFromU8Arr.mjs.html +1 -1
  145. package/docs/dtmapping.mjs.html +1 -1
  146. package/docs/dtpick.mjs.html +1 -1
  147. package/docs/estimateTicks.mjs.html +1 -1
  148. package/docs/evEmit.mjs.html +2 -2
  149. package/docs/evEmitDelay.mjs.html +1 -1
  150. package/docs/evem.mjs.html +1 -1
  151. package/docs/examples/ex-blob2b64.html +1 -1
  152. package/docs/examples/ex-clearXSS.html +1 -1
  153. package/docs/examples/ex-clearXSSDyn.html +1 -1
  154. package/docs/examples/ex-colorConverter.html +1 -1
  155. package/docs/examples/ex-detectXSS.html +1 -1
  156. package/docs/examples/ex-detectXSSDyn.html +1 -1
  157. package/docs/examples/ex-domCompareText.html +1 -1
  158. package/docs/examples/ex-domConvertToPic.html +1 -1
  159. package/docs/examples/ex-domDrag.html +1 -1
  160. package/docs/examples/ex-domDropFiles.html +1 -1
  161. package/docs/examples/ex-domIsVisible.html +1 -1
  162. package/docs/examples/ex-domRenderMarkdownMind.html +1 -1
  163. package/docs/examples/ex-domRenderMarkdownMindDyn.html +1 -1
  164. package/docs/examples/ex-domRipple.html +1 -1
  165. package/docs/examples/ex-domScrollIntoView.html +1 -1
  166. package/docs/examples/ex-domScrollTo.html +1 -1
  167. package/docs/examples/ex-domShowImages.html +1 -1
  168. package/docs/examples/ex-domShowImagesDyn.html +1 -1
  169. package/docs/examples/ex-domShowInputAndGetFiles.html +1 -1
  170. package/docs/examples/ex-domTooltip.html +1 -1
  171. package/docs/examples/ex-getFileHash.html +1 -1
  172. package/docs/examples/ex-getUserAgent.html +1 -1
  173. package/docs/examples/ex-getUserAgentDyn.html +1 -1
  174. package/docs/examples/ex-html2str.html +1 -1
  175. package/docs/examples/ex-obj2u8arr-u8arr2obj.html +1 -1
  176. package/docs/examples/ex-openLink.html +1 -1
  177. package/docs/examples/ex-str2aes-aes2str.html +1 -1
  178. package/docs/examples/ex-str2b64-b642str.html +1 -1
  179. package/docs/examples/ex-strFindFuzz.html +1 -1
  180. package/docs/examples/ex-timeTZ2expire-timeTZ2past.html +1 -1
  181. package/docs/examples/ex-xlsx.html +1 -1
  182. package/docs/execCli.mjs.html +67 -33
  183. package/docs/execCliCore.mjs.html +4 -1
  184. package/docs/execCliJsonRpc.mjs.html +3 -3
  185. package/docs/execCliSession.mjs.html +24 -12
  186. package/docs/execJsCode.mjs.html +1 -1
  187. package/docs/execProcess.mjs.html +58 -35
  188. package/docs/execProcessKillPid.mjs.html +5 -3
  189. package/docs/filepathToTree.mjs.html +1 -1
  190. package/docs/files2data.mjs.html +1 -1
  191. package/docs/flattenToConn.mjs.html +1 -1
  192. package/docs/flattenTree.mjs.html +1 -1
  193. package/docs/floor.mjs.html +1 -1
  194. package/docs/fsBuildReadStreamText.mjs.html +1 -1
  195. package/docs/fsBuildWriteStreamText.mjs.html +1 -1
  196. package/docs/fsCleanFolder.mjs.html +1 -1
  197. package/docs/fsCleanFolderCore.mjs.html +1 -1
  198. package/docs/fsCopyFile.mjs.html +1 -1
  199. package/docs/fsCopyFileCore.mjs.html +1 -1
  200. package/docs/fsCopyFolder.mjs.html +1 -1
  201. package/docs/fsCopyFolderCore.mjs.html +1 -1
  202. package/docs/fsCreateFile.mjs.html +1 -1
  203. package/docs/fsCreateFileCore.mjs.html +1 -1
  204. package/docs/fsCreateFolder.mjs.html +1 -1
  205. package/docs/fsCreateFolderCore.mjs.html +1 -1
  206. package/docs/fsDeleteFile.mjs.html +1 -1
  207. package/docs/fsDeleteFileCore.mjs.html +1 -1
  208. package/docs/fsDeleteFileSafe.mjs.html +1 -1
  209. package/docs/fsDeleteFileSafeCore.mjs.html +1 -1
  210. package/docs/fsDeleteFolder.mjs.html +1 -1
  211. package/docs/fsDeleteFolderCore.mjs.html +1 -1
  212. package/docs/fsDeleteFolderSafe.mjs.html +1 -1
  213. package/docs/fsDeleteFolderSafeCore.mjs.html +1 -1
  214. package/docs/fsDownloadFile.mjs.html +1 -1
  215. package/docs/fsDownloadFileCore.mjs.html +1 -1
  216. package/docs/fsEvem.mjs.html +1 -1
  217. package/docs/fsExists.mjs.html +1 -1
  218. package/docs/fsExistsCore.mjs.html +1 -1
  219. package/docs/fsGetFileBasicHash.mjs.html +1 -1
  220. package/docs/fsGetFileBasicHashCore.mjs.html +1 -1
  221. package/docs/fsGetFileHash.mjs.html +1 -1
  222. package/docs/fsGetFileHashCore.mjs.html +1 -1
  223. package/docs/fsGetFileXxHash.mjs.html +1 -1
  224. package/docs/fsGetFileXxHashCore.mjs.html +1 -1
  225. package/docs/fsGetFilesInFolder.mjs.html +1 -1
  226. package/docs/fsGetFilesInFolderCore.mjs.html +1 -1
  227. package/docs/fsGetFilesWithHashInFolder.mjs.html +1 -1
  228. package/docs/fsGetFilesWithHashInFolderCore.mjs.html +1 -1
  229. package/docs/fsGetFolderBasicHash.mjs.html +1 -1
  230. package/docs/fsGetFolderBasicHashCore.mjs.html +1 -1
  231. package/docs/fsGetFoldersInFolder.mjs.html +1 -1
  232. package/docs/fsGetFoldersInFolderCore.mjs.html +1 -1
  233. package/docs/fsIsFile.mjs.html +1 -1
  234. package/docs/fsIsFileCore.mjs.html +1 -1
  235. package/docs/fsIsFolder.mjs.html +1 -1
  236. package/docs/fsIsFolderCore.mjs.html +1 -1
  237. package/docs/fsMergeFiles.mjs.html +1 -1
  238. package/docs/fsMergeFilesCore.mjs.html +1 -1
  239. package/docs/fsReadJson.mjs.html +1 -1
  240. package/docs/fsReadText.mjs.html +1 -1
  241. package/docs/fsReadTextCore.mjs.html +1 -1
  242. package/docs/fsRenameFile.mjs.html +1 -1
  243. package/docs/fsRenameFileCore.mjs.html +1 -1
  244. package/docs/fsRenameFolder.mjs.html +1 -1
  245. package/docs/fsRenameFolderCore.mjs.html +1 -1
  246. package/docs/fsSrlog.mjs.html +1 -1
  247. package/docs/fsSyncFolder.mjs.html +1 -1
  248. package/docs/fsSyncFolderCore.mjs.html +1 -1
  249. package/docs/fsTask.mjs.html +1 -1
  250. package/docs/fsTaskCp.mjs.html +1 -1
  251. package/docs/fsTreeFolder.mjs.html +1 -1
  252. package/docs/fsTreeFolderCore.mjs.html +1 -1
  253. package/docs/fsTreeFolderWithHash.mjs.html +1 -1
  254. package/docs/fsTreeFolderWithHashCore.mjs.html +1 -1
  255. package/docs/fsWatchFile.mjs.html +1 -1
  256. package/docs/fsWatchFolder.mjs.html +1 -1
  257. package/docs/fsWriteJson.mjs.html +1 -1
  258. package/docs/fsWriteText.mjs.html +1 -1
  259. package/docs/fsWriteTextCore.mjs.html +1 -1
  260. package/docs/genGradientColor.mjs.html +1 -1
  261. package/docs/genID.mjs.html +1 -1
  262. package/docs/genIDSeq.mjs.html +1 -1
  263. package/docs/genPm.mjs.html +1 -1
  264. package/docs/getBufferSize.mjs.html +1 -1
  265. package/docs/getClearPathName.mjs.html +1 -1
  266. package/docs/getCsvStrFromData.mjs.html +1 -1
  267. package/docs/getDataFromExcelFileU8Arr.mjs.html +1 -1
  268. package/docs/getDataFromExcelFileU8ArrDyn.mjs.html +1 -1
  269. package/docs/getEnv.mjs.html +1 -1
  270. package/docs/getErrorMessage.mjs.html +1 -1
  271. package/docs/getExcelU8ArrFromData.mjs.html +1 -1
  272. package/docs/getExcelU8ArrFromWorkbook.mjs.html +1 -1
  273. package/docs/getExcelWorkbookFromData.mjs.html +1 -1
  274. package/docs/getExcelWorkbookFromWorksheet.mjs.html +1 -1
  275. package/docs/getExcelWorksheetFromData.mjs.html +1 -1
  276. package/docs/getFileAccept.mjs.html +1 -1
  277. package/docs/getFileBasicHash.mjs.html +1 -1
  278. package/docs/getFileHash.mjs.html +1 -1
  279. package/docs/getFileName.mjs.html +1 -1
  280. package/docs/getFileNameExt.mjs.html +1 -1
  281. package/docs/getFileTrueName.mjs.html +1 -1
  282. package/docs/getFileType.mjs.html +1 -1
  283. package/docs/getFileXxHash.mjs.html +1 -1
  284. package/docs/getGlobal.mjs.html +1 -1
  285. package/docs/getObjSize.mjs.html +1 -1
  286. package/docs/getPathParent.mjs.html +1 -1
  287. package/docs/getTimeBetween.mjs.html +1 -1
  288. package/docs/getTimeFromUnit.mjs.html +1 -1
  289. package/docs/getTimeHp.mjs.html +1 -1
  290. package/docs/getTimeObject.mjs.html +1 -1
  291. package/docs/getTimeRange.mjs.html +1 -1
  292. package/docs/getUserAgent.mjs.html +1 -1
  293. package/docs/getUserAgentDyn.mjs.html +1 -1
  294. package/docs/getltdtkeys.mjs.html +1 -1
  295. package/docs/global.html +7 -7
  296. package/docs/haskey.mjs.html +1 -1
  297. package/docs/html2str.mjs.html +1 -1
  298. package/docs/htmlDecode.mjs.html +1 -1
  299. package/docs/htmlEncode.mjs.html +1 -1
  300. package/docs/importResources.mjs.html +1 -1
  301. package/docs/index.html +1 -1
  302. package/docs/interp1.mjs.html +1 -1
  303. package/docs/isDate.mjs.html +1 -1
  304. package/docs/isDev.mjs.html +1 -1
  305. package/docs/isEle.mjs.html +1 -1
  306. package/docs/isEleExistByID.mjs.html +1 -1
  307. package/docs/isEmail.mjs.html +1 -1
  308. package/docs/isErr.mjs.html +1 -1
  309. package/docs/isIE.mjs.html +1 -1
  310. package/docs/isNarrow.mjs.html +1 -1
  311. package/docs/isStrHasCapital.mjs.html +1 -1
  312. package/docs/isStrHasLetter.mjs.html +1 -1
  313. package/docs/isStrHasLowerCase.mjs.html +1 -1
  314. package/docs/isStrHasNumber.mjs.html +1 -1
  315. package/docs/isStrHasSpace.mjs.html +1 -1
  316. package/docs/isStrHasSymbol.mjs.html +1 -1
  317. package/docs/isUserIdentify.mjs.html +1 -1
  318. package/docs/isUserName.mjs.html +1 -1
  319. package/docs/isUserPw.mjs.html +1 -1
  320. package/docs/isWindow.mjs.html +1 -1
  321. package/docs/isab.mjs.html +1 -1
  322. package/docs/isarr.mjs.html +1 -1
  323. package/docs/isarr0.mjs.html +1 -1
  324. package/docs/isarr1.mjs.html +1 -1
  325. package/docs/isbigint.mjs.html +1 -1
  326. package/docs/isblob.mjs.html +1 -1
  327. package/docs/isbol.mjs.html +1 -1
  328. package/docs/isday.mjs.html +1 -1
  329. package/docs/isearr.mjs.html +1 -1
  330. package/docs/iseobj.mjs.html +1 -1
  331. package/docs/iser.mjs.html +1 -1
  332. package/docs/isernot.mjs.html +1 -1
  333. package/docs/isestr.mjs.html +1 -1
  334. package/docs/isfile.mjs.html +1 -1
  335. package/docs/isfun.mjs.html +1 -1
  336. package/docs/isint.mjs.html +1 -1
  337. package/docs/ismonth.mjs.html +1 -1
  338. package/docs/isn0int.mjs.html +1 -1
  339. package/docs/isn0num.mjs.html +1 -1
  340. package/docs/isnan.mjs.html +1 -1
  341. package/docs/isnbr.mjs.html +1 -1
  342. package/docs/isnint.mjs.html +1 -1
  343. package/docs/isnnum.mjs.html +1 -1
  344. package/docs/isnull.mjs.html +1 -1
  345. package/docs/isnum.mjs.html +1 -1
  346. package/docs/isobj.mjs.html +1 -1
  347. package/docs/isobj0.mjs.html +1 -1
  348. package/docs/isp0int.mjs.html +1 -1
  349. package/docs/isp0num.mjs.html +1 -1
  350. package/docs/ispint.mjs.html +1 -1
  351. package/docs/ispm.mjs.html +1 -1
  352. package/docs/ispnum.mjs.html +1 -1
  353. package/docs/isstr.mjs.html +1 -1
  354. package/docs/isstr0.mjs.html +1 -1
  355. package/docs/istime.mjs.html +1 -1
  356. package/docs/istimeTZ.mjs.html +1 -1
  357. package/docs/istimems.mjs.html +1 -1
  358. package/docs/istimemsTZ.mjs.html +1 -1
  359. package/docs/isu16arr.mjs.html +1 -1
  360. package/docs/isu8arr.mjs.html +1 -1
  361. package/docs/isundefined.mjs.html +1 -1
  362. package/docs/j2o.mjs.html +1 -1
  363. package/docs/judge.mjs.html +1 -1
  364. package/docs/keysmat2ltdt.mjs.html +1 -1
  365. package/docs/ltdt2vrtsable.mjs.html +1 -1
  366. package/docs/ltdtDiff.mjs.html +1 -1
  367. package/docs/ltdtDiffByKey.mjs.html +1 -1
  368. package/docs/ltdtkeys2mat.mjs.html +1 -1
  369. package/docs/ltdtkeysheads2mat.mjs.html +1 -1
  370. package/docs/ltdtmapping.mjs.html +1 -1
  371. package/docs/ltdtmerge.mjs.html +1 -1
  372. package/docs/ltdtpick.mjs.html +1 -1
  373. package/docs/ltdtpull.mjs.html +1 -1
  374. package/docs/mat2ltdt.mjs.html +1 -1
  375. package/docs/matConcat.mjs.html +1 -1
  376. package/docs/matDiff.mjs.html +1 -1
  377. package/docs/matat.mjs.html +1 -1
  378. package/docs/now2str.mjs.html +1 -1
  379. package/docs/now2strp.mjs.html +1 -1
  380. package/docs/nowDay2str.mjs.html +1 -1
  381. package/docs/nowms2str.mjs.html +1 -1
  382. package/docs/nowms2strp.mjs.html +1 -1
  383. package/docs/o2j.mjs.html +1 -1
  384. package/docs/obj2b64.mjs.html +1 -1
  385. package/docs/obj2pb64.mjs.html +1 -1
  386. package/docs/obj2str.mjs.html +1 -1
  387. package/docs/obj2stru8arr.mjs.html +1 -1
  388. package/docs/obj2u8arr.mjs.html +1 -1
  389. package/docs/objSortBy.mjs.html +1 -1
  390. package/docs/objSortByKeys.mjs.html +1 -1
  391. package/docs/oo.mjs.html +1 -1
  392. package/docs/openLink.mjs.html +1 -1
  393. package/docs/pb642obj.mjs.html +1 -1
  394. package/docs/pmChain.mjs.html +1 -1
  395. package/docs/pmConvertResolve.mjs.html +1 -1
  396. package/docs/pmDebounce.mjs.html +1 -1
  397. package/docs/pmHook.mjs.html +1 -1
  398. package/docs/pmHookReject.mjs.html +1 -1
  399. package/docs/pmIni.mjs.html +1 -1
  400. package/docs/pmInvResolve.mjs.html +1 -1
  401. package/docs/pmKeyMutex.mjs.html +1 -1
  402. package/docs/pmMap.mjs.html +1 -1
  403. package/docs/pmQueue.mjs.html +1 -1
  404. package/docs/pmSeries.mjs.html +1 -1
  405. package/docs/pmThrottle.mjs.html +1 -1
  406. package/docs/pmTimeout.mjs.html +1 -1
  407. package/docs/preciseNum.mjs.html +1 -1
  408. package/docs/pseudoRandom.mjs.html +1 -1
  409. package/docs/pseudoRandomIntRange.mjs.html +1 -1
  410. package/docs/pseudoRandomIntsNdpRange.mjs.html +1 -1
  411. package/docs/pseudoRandomIntsRange.mjs.html +1 -1
  412. package/docs/pseudoRandomRange.mjs.html +1 -1
  413. package/docs/pseudoRandomsRange.mjs.html +1 -1
  414. package/docs/queue.mjs.html +1 -1
  415. package/docs/random.mjs.html +1 -1
  416. package/docs/randomIntRange.mjs.html +1 -1
  417. package/docs/randomIntsNdpRange.mjs.html +1 -1
  418. package/docs/randomIntsRange.mjs.html +1 -1
  419. package/docs/randomRange.mjs.html +1 -1
  420. package/docs/randomsRange.mjs.html +1 -1
  421. package/docs/rang.mjs.html +1 -1
  422. package/docs/rep.mjs.html +1 -1
  423. package/docs/repObj.mjs.html +1 -1
  424. package/docs/replace.mjs.html +1 -1
  425. package/docs/replaceObj.mjs.html +1 -1
  426. package/docs/replacePlus.mjs.html +1 -1
  427. package/docs/round.mjs.html +1 -1
  428. package/docs/secd.mjs.html +1 -1
  429. package/docs/sep.mjs.html +1 -1
  430. package/docs/sepInt.mjs.html +1 -1
  431. package/docs/setIntervalHp.mjs.html +1 -1
  432. package/docs/setTimeoutHp.mjs.html +1 -1
  433. package/docs/sind.mjs.html +1 -1
  434. package/docs/split.mjs.html +1 -1
  435. package/docs/str2aes.mjs.html +1 -1
  436. package/docs/str2b64.mjs.html +1 -1
  437. package/docs/str2hint.mjs.html +1 -1
  438. package/docs/str2md5.mjs.html +1 -1
  439. package/docs/str2obj.mjs.html +1 -1
  440. package/docs/str2sha.mjs.html +1 -1
  441. package/docs/str2sha512.mjs.html +1 -1
  442. package/docs/str2u8arr.mjs.html +1 -1
  443. package/docs/strCompare.mjs.html +1 -1
  444. package/docs/strCompareForVersion.mjs.html +1 -1
  445. package/docs/strDiff.mjs.html +1 -1
  446. package/docs/strDiffToHtml.mjs.html +1 -1
  447. package/docs/strFindFuzz.mjs.html +1 -1
  448. package/docs/strFindSimilar.mjs.html +1 -1
  449. package/docs/strTruncate.mjs.html +1 -1
  450. package/docs/strdelleft.mjs.html +1 -1
  451. package/docs/strdelright.mjs.html +1 -1
  452. package/docs/strleft.mjs.html +1 -1
  453. package/docs/strmid.mjs.html +1 -1
  454. package/docs/strright.mjs.html +1 -1
  455. package/docs/stru8arr2obj.mjs.html +1 -1
  456. package/docs/tand.mjs.html +1 -1
  457. package/docs/time2day.mjs.html +1 -1
  458. package/docs/time2hour.mjs.html +1 -1
  459. package/docs/time2min.mjs.html +1 -1
  460. package/docs/timeTZ2day.mjs.html +1 -1
  461. package/docs/timeTZ2expire.mjs.html +1 -1
  462. package/docs/timeTZ2hour.mjs.html +1 -1
  463. package/docs/timeTZ2min.mjs.html +1 -1
  464. package/docs/timeTZ2past.mjs.html +1 -1
  465. package/docs/timems2day.mjs.html +1 -1
  466. package/docs/timems2hour.mjs.html +1 -1
  467. package/docs/timems2min.mjs.html +1 -1
  468. package/docs/timems2time.mjs.html +1 -1
  469. package/docs/timemsTZ2day.mjs.html +1 -1
  470. package/docs/timemsTZ2expire.mjs.html +1 -1
  471. package/docs/timemsTZ2hour.mjs.html +1 -1
  472. package/docs/timemsTZ2min.mjs.html +1 -1
  473. package/docs/timemsTZ2past.mjs.html +1 -1
  474. package/docs/timemsTZ2time.mjs.html +1 -1
  475. package/docs/treeObj.mjs.html +1 -1
  476. package/docs/treeToFilepath.mjs.html +1 -1
  477. package/docs/trim.mjs.html +1 -1
  478. package/docs/u16arr2b64.mjs.html +1 -1
  479. package/docs/u16arr2u8arr.mjs.html +1 -1
  480. package/docs/u8arr2ab.mjs.html +1 -1
  481. package/docs/u8arr2b64.mjs.html +1 -1
  482. package/docs/u8arr2blob.mjs.html +1 -1
  483. package/docs/u8arr2bs.mjs.html +1 -1
  484. package/docs/u8arr2obj.mjs.html +1 -1
  485. package/docs/u8arr2str.mjs.html +1 -1
  486. package/docs/u8arr2u16arr.mjs.html +1 -1
  487. package/docs/urlParse.mjs.html +1 -1
  488. package/docs/verifyValue.mjs.html +1 -1
  489. package/docs/waitFun.mjs.html +1 -1
  490. package/docs/wsemi.html +24 -23
  491. package/package.json +2 -2
  492. package/script.txt +1 -1
  493. package/src/_execSpawnError.mjs +41 -0
  494. package/src/alive.mjs +105 -4
  495. package/src/cache.mjs +2 -2
  496. package/src/cacheSt.mjs +1 -1
  497. package/src/evEmit.mjs +1 -1
  498. package/src/execCli.mjs +66 -32
  499. package/src/execCliCore.mjs +3 -0
  500. package/src/execCliJsonRpc.mjs +2 -2
  501. package/src/execCliSession.mjs +23 -11
  502. package/src/execProcess.mjs +57 -34
  503. package/src/execProcessKillPid.mjs +4 -2
  504. package/test/_execSpawnError.test.mjs +81 -0
  505. package/test/alive.test.mjs +201 -0
  506. package/test/cache.test.mjs +26 -0
  507. package/test/cacheSt.test.mjs +40 -0
  508. package/test/execCli.test.mjs +95 -0
  509. package/test/execCliJsonRpc.test.mjs +27 -0
  510. package/test/execCliSession.test.mjs +82 -0
  511. package/test/execProcess.test.mjs +135 -3
  512. package/test/execProcessKillPid.test.mjs +34 -0
  513. package/test/tools/spawnEmfileRunner.mjs +55 -0
  514. package/toolfp/dist/wsemip.umd.js +1 -1
  515. package/toolparfor/dist/wpf.umd.js +1 -1
  516. package/toolparfor/dist/wpf_pmSeries.umd.js +1 -1
package/src/alive.mjs CHANGED
@@ -2,7 +2,7 @@ import get from 'lodash-es/get.js'
2
2
  import each from 'lodash-es/each.js'
3
3
  import cloneDeep from 'lodash-es/cloneDeep.js'
4
4
  import size from 'lodash-es/size.js'
5
- import cst from './_const.mjs'
5
+ import cst from './_const.mjs'
6
6
  import evem from './evem.mjs'
7
7
  import evEmit from './evEmit.mjs'
8
8
  import ispint from './ispint.mjs'
@@ -19,7 +19,7 @@ import cint from './cint.mjs'
19
19
  * @memberOf wsemi
20
20
  * @param {Integer} [timeAlive=10000] 輸入判斷單元是否斷線之延時整數,單位為毫秒ms,預設為10000
21
21
  * @param {Integer} [timeDetect=50] 輸入偵測佇列間隔時間整數,單位為毫秒ms,預設為50
22
- * @returns {Object} 回傳事件物件,可呼叫函數on、trigger、get。trigger給予單元的唯一key字串與攜帶數據data物件,on為監聽事件,需自行監聽message事件取得單元進出事件。get事件可取得alive內視為存活的單元清單。事件物件為原生EventEmitter(eventemitter3)。本模組於派發處以try攔截監聽器之同步拋錯,故其不會使行程崩潰,會改以error事件回報{ fun: 'listener', name, msg, args },無error監聽者則console.error;惟依EventEmitter規範,同一次派發中先拋錯之監聽器會中止該次派發,其後之監聽器不再被呼叫。async監聽器之reject不被攔截(規範上emit不觀察監聽器回傳值),須由監聽器自行處理,否則為unhandledRejection
22
+ * @returns {Object} 回傳事件物件,可呼叫函數on、trigger、get、clear。trigger給予單元的唯一key字串與攜帶數據data物件,on為監聽事件,需自行監聽message事件取得單元進出事件。get事件可取得alive內視為存活的單元清單(含剛trigger而尚未發出enter者)。clear為釋放:立即清除偵測計時器、取消尚未發出之enter、清空佇列,本身不發事件,其後不再發出任何事件、trigger無效、get回傳[],可重複呼叫(釋放為終態,需重新偵測者另建alive);clear回傳已發出enter且尚未leave之單元陣列[{ key, data }],供使用端補發離線通知,再次呼叫回傳[];監聽器於派發中呼叫clear亦安全,同一輪尚未處理之單元不再派發。事件物件為原生EventEmitter(eventemitter3)。本模組於派發處以try攔截監聽器之同步拋錯,故其不會使行程崩潰,會改以error事件回報{ fun: 'listener', name, msg, args },無error監聽者則console.error;惟依EventEmitter規範,同一次派發中先拋錯之監聽器會中止該次派發,其後之監聽器不再被呼叫。async監聽器之reject不被攔截(規範上emit不觀察監聽器回傳值),須由監聽器自行處理,否則為unhandledRejection
23
23
  * @example
24
24
  *
25
25
  * async function topAsync() {
@@ -81,14 +81,47 @@ import cint from './cint.mjs'
81
81
  * // 4544ms { eventName: 'leave', key: 'b', data: { data: '34.56' }, now: 0 }
82
82
  * // ["enter|a","enter|b","leave|b","enter|b","leave|a","leave|b"]
83
83
  *
84
+ * function test2() {
85
+ * return new Promise((resolve, reject) => {
86
+ * let ms = []
87
+ *
88
+ * let oAL = alive({ timeAlive: 1500 })
89
+ *
90
+ * oAL.on('message', function({ eventName, key }) {
91
+ * ms.push(eventName + '|' + key)
92
+ * })
93
+ *
94
+ * oAL.trigger('a', { data: 123 })
95
+ *
96
+ * setTimeout(() => {
97
+ * oAL.trigger('b', { data: '34.56' })
98
+ * let r = oAL.clear() //b剛trigger尚未發出enter, 故只回傳a, 且b之enter不再發出
99
+ * ms.push('clear|' + r.map((v) => v.key).join(','))
100
+ * }, 500)
101
+ *
102
+ * setTimeout(() => {
103
+ * resolve(ms)
104
+ * }, 2500)
105
+ *
106
+ * })
107
+ * }
108
+ * console.log('test2')
109
+ * let r2 = await test2()
110
+ * console.log(JSON.stringify(r2))
111
+ * // test2
112
+ * // ["enter|a","clear|a"]
113
+ *
84
114
  * }
85
115
  * topAsync().catch(() => {})
86
116
  *
87
117
  */
88
118
  function alive(opt = {}) {
89
119
  let ev = evem() //message事件於timer內派發, 監聽器出錯不得殺行程, 故派發處以evEmit攔截
90
- let q = {} //queue
120
+ let q = Object.create(null) //queue, 以trigger之key為鍵; 用無原型物件使任意字串皆為一般鍵, 一般物件時__proto__會改掉佇列之原型、constructor等原型屬性名會被haskey誤判為已存在而不發enter
91
121
  let t = null //timer
122
+ let tEnters = new Set() //尚未發出enter之計時器, 供clear取消
123
+ let entered = new Set() //已發出enter且尚未leave之單元key, 供clear回傳
124
+ let cleared = false //是否已clear, clear為終態
92
125
 
93
126
  //timeAlive
94
127
  let timeAlive = get(opt, 'timeAlive')
@@ -107,6 +140,9 @@ function alive(opt = {}) {
107
140
  timeDetect = Math.min(timeDetect, cst.TIMER_TIME_MAX) //同上
108
141
 
109
142
  function detect() {
143
+ if (cleared) {
144
+ return
145
+ }
110
146
  if (t !== null) {
111
147
  return
112
148
  }
@@ -127,13 +163,25 @@ function alive(opt = {}) {
127
163
 
128
164
  //刪除佇列內key紀錄
129
165
  delete q[key]
166
+ entered.delete(key)
130
167
 
131
168
  //emit leave
132
169
  evEmit(ev, 'message', [{ eventName: 'leave', key, data: r.data, now: size(q) }], { tag: 'alive' })
133
170
 
171
+ //監聽器於派發中呼叫clear時須立即停止本輪, 不再處理或派發
172
+ // each走的是本輪開始時之鍵清單, 而clear已清空佇列, 續走會讀到不存在之單元而拋錯
173
+ if (cleared) {
174
+ return false
175
+ }
176
+
134
177
  }
135
178
  })
136
179
 
180
+ //已clear者計時器已於clear內清除
181
+ if (cleared) {
182
+ return
183
+ }
184
+
137
185
  //clear, 當無任何訊息存在
138
186
  if (!iseobj(q)) {
139
187
  clearInterval(t)
@@ -145,6 +193,11 @@ function alive(opt = {}) {
145
193
 
146
194
  function trigger(key, data) {
147
195
 
196
+ //已clear為終態, 不建立計時器亦不發事件
197
+ if (cleared) {
198
+ return
199
+ }
200
+
148
201
  //check
149
202
  if (!isestr(key)) {
150
203
  console.log('trigger need key')
@@ -153,12 +206,23 @@ function alive(opt = {}) {
153
206
 
154
207
  //check
155
208
  if (!haskey(q, key)) {
156
- setTimeout(() => { //因需判斷是否為新單元故需放於update前, 而emit內可能會被存取q, 故需要用setTimeout脫勾使q為被更新資訊, 才能正確取得當前單元數量
209
+ //因需判斷是否為新單元故需放於update前, 而emit內可能會被存取q, 故需要用setTimeout脫勾使q為被更新資訊, 才能正確取得當前單元數量
210
+ //不用evEmitDelay, 因其參數於呼叫時即求值, now會少計本單元; 計時器存入tEnters供clear取消
211
+ let te = setTimeout(() => {
212
+
213
+ //已發出, 移出待取消清單
214
+ tEnters.delete(te)
215
+
216
+ //派發前即標記已enter, 使監聽器於派發中呼叫clear時能回傳本單元, 以與其leave配對
217
+ if (haskey(q, key)) {
218
+ entered.add(key)
219
+ }
157
220
 
158
221
  //emit enter
159
222
  evEmit(ev, 'message', [{ eventName: 'enter', key, data, now: size(q) }], { tag: 'alive' })
160
223
 
161
224
  }, 1)
225
+ tEnters.add(te)
162
226
  }
163
227
 
164
228
  //update
@@ -178,9 +242,46 @@ function alive(opt = {}) {
178
242
  return rs
179
243
  }
180
244
 
245
+ function clear() {
246
+
247
+ //已clear則回傳[], 可重複呼叫
248
+ if (cleared) {
249
+ return []
250
+ }
251
+ cleared = true
252
+
253
+ //清除偵測計時器
254
+ if (t !== null) {
255
+ clearInterval(t)
256
+ t = null
257
+ }
258
+
259
+ //取消尚未發出之enter
260
+ for (let te of tEnters) {
261
+ clearTimeout(te)
262
+ }
263
+ tEnters.clear()
264
+
265
+ //已發出enter且尚未leave之單元, 形狀同get; get含尚未發出enter者, 使用端拿其配對leave會出現有leave無enter
266
+ let rs = []
267
+ each(q, (v, k) => {
268
+ if (entered.has(k)) {
269
+ rs.push({ key: k, data: v.data })
270
+ }
271
+ })
272
+ rs = cloneDeep(rs) //使用cloneDeep避免外部修改內部數據
273
+
274
+ //清空佇列, 同建立時用無原型物件
275
+ q = Object.create(null)
276
+ entered.clear()
277
+
278
+ return rs
279
+ }
280
+
181
281
  //save
182
282
  ev.trigger = trigger
183
283
  ev.get = _get
284
+ ev.clear = clear
184
285
 
185
286
  return ev
186
287
  }
package/src/cache.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import loGet from 'lodash-es/get.js'
2
2
  import cloneDeep from 'lodash-es/cloneDeep.js'
3
3
  import evem from './evem.mjs'
4
- import evEmitDelay from './evEmitDelay.mjs'
4
+ import evEmitDelay from './evEmitDelay.mjs'
5
5
  import isfun from './isfun.mjs'
6
6
  import isbol from './isbol.mjs'
7
7
  import haskey from './haskey.mjs'
@@ -538,7 +538,7 @@ import cint from './cint.mjs'
538
538
  */
539
539
  function cache() {
540
540
  let ev = evem() //事件以timer脫勾派發, 監聽器出錯不得殺行程, 故派發處以evEmit攔截
541
- let data = {} //快取資料
541
+ let data = Object.create(null) //快取資料, 以呼叫端之key為鍵; 用無原型物件使任意字串皆為一般鍵, 一般物件時__proto__會改掉其原型、constructor等原型屬性名會被haskey誤判為已存在, 對其update會寫到Object本身
542
542
 
543
543
  function emit(mode, data) {
544
544
  evEmitDelay(ev, mode, [data], { tag: 'cache' }) //用timer脫勾, 並於該新堆疊內攔截監聽器之同步拋錯
package/src/cacheSt.mjs CHANGED
@@ -112,7 +112,7 @@ function cacheSt(opt = {}) {
112
112
 
113
113
  let ev = evem() //detect事件於setInterval內派發, 其餘於呼叫端同步堆疊或await之後派發且監聽器可能為async, 監聽器出錯不得殺行程, 故派發處以evEmit攔截
114
114
 
115
- let _gs = {}
115
+ let _gs = Object.create(null) //以呼叫端之key為鍵; 用無原型物件使任意字串皆為一般鍵, 一般物件時__proto__會改掉其原型(且不會過期)、constructor等原型屬性名會被haskey誤判為已存在
116
116
 
117
117
  let _set = async (key, value = true) => {
118
118
  _gs[key] = {
package/src/evEmit.mjs CHANGED
@@ -16,7 +16,7 @@ import isfun from './isfun.mjs'
16
16
  *
17
17
  * setTimeout會開一個「沒有呼叫者」的堆疊,監聽器之同步拋錯於該處即為uncaughtException,
18
18
  * 且呼叫端無論如何try都攔不到(此與監聽器是否為async無關,純同步監聽器亦然)。
19
- * 於呼叫端之堆疊上派發,一個普通的try即可攔下。確實需要脫勾者請改用evEmitDefer,
19
+ * 於呼叫端之堆疊上派發,一個普通的try即可攔下。確實需要脫勾者請改用evEmitDelay,
20
20
  * 其內部即以本函數派發,故仍有攔截。
21
21
  *
22
22
  * 【為何不處理async監聽器之reject】
package/src/execCli.mjs CHANGED
@@ -16,12 +16,17 @@ import strdelleft from './strdelleft.mjs'
16
16
  import strTruncate from './strTruncate.mjs'
17
17
  import execProcessKillPid from './execProcessKillPid.mjs'
18
18
  import execCliCore from './execCliCore.mjs'
19
+ import execSpawnError from './_execSpawnError.mjs'
19
20
 
20
21
 
21
22
  //buildSpawnArgs, buildSpawnEnv, 共用核心已抽至execCliCore
22
23
  let { buildSpawnArgs, buildSpawnEnv } = execCliCore
23
24
 
24
25
 
26
+ //kNoRetry, 無法啟動子進程之同步錯誤所產生之結果物件(確定性失敗, 重試無意義), 供execCli判定不重試, 不擴充對外之結果物件欄位
27
+ let kNoRetry = new WeakSet()
28
+
29
+
25
30
  //optTruncate, 供strTruncate裁切失敗結果之stdout與stderr時, 於刪節號後標註原始總長度
26
31
  let optTruncate = {
27
32
  funWithMsg: (str) => `(truncated, total ${str.length} chars)`,
@@ -126,15 +131,33 @@ function execCliOnce(command, args = [], opt = {}) {
126
131
  //每次attempt於此重新求值並僅作用於該次子進程, 不動本進程process.env, 故並行調用可各自帶不同值
127
132
  let envSpawn = buildSpawnEnv(envExtra)
128
133
 
129
- //spawn
130
- let winSpawn = buildSpawnArgs(command, args)
131
- let proc = spawn(winSpawn.file, winSpawn.args, {
132
- cwd,
133
- stdio: ['pipe', 'pipe', 'pipe'],
134
- windowsHide: true, //執行的主程序若沒有主控台調用執行程序就不會有視窗, 但若通過pm2執行會有, 須設定windowsHide=true
135
- env: envSpawn,
136
- ...winSpawn.opt,
137
- })
134
+ //spawn, 同步拋錯(EPERM、UNKNOWN、ENAMETOOLONG、參數檢查錯誤等)以結果物件回報而不reject, 且屬確定性失敗不重試; buildSpawnArgs之拋錯亦同
135
+ let proc
136
+ try {
137
+ let winSpawn = buildSpawnArgs(command, args)
138
+ proc = spawn(winSpawn.file, winSpawn.args, {
139
+ cwd,
140
+ stdio: ['pipe', 'pipe', 'pipe'],
141
+ windowsHide: true, //執行的主程序若沒有主控台調用執行程序就不會有視窗, 但若通過pm2執行會有, 須設定windowsHide=true
142
+ env: envSpawn,
143
+ ...winSpawn.opt,
144
+ })
145
+ }
146
+ catch (err) {
147
+ let e = execSpawnError(err)
148
+ let r = {
149
+ ok: false,
150
+ stdout: '',
151
+ stderr: '',
152
+ code: null,
153
+ error: `${e.code}: ${e.message}`,
154
+ durationMs: Date.now() - startTime,
155
+ pid: undefined, //與'error'事件(如ENOENT)之結果一致
156
+ }
157
+ kNoRetry.add(r)
158
+ pm.resolve(r)
159
+ return pm
160
+ }
138
161
 
139
162
  let stdout = ''
140
163
  let stderr = ''
@@ -146,6 +169,32 @@ function execCliOnce(command, args = [], opt = {}) {
146
169
 
147
170
  let settled = false
148
171
  let timedOut = false
172
+ let timer = null
173
+
174
+ //error, 須於存取stdio前監聽: node對EMFILE、ENFILE不建立stdio即於nextTick發出'error', 先存取會拋TypeError且'error'無人監聽而拉倒程序
175
+ // 可能為'找不到可執行檔'(ENOENT), '權限不足', '系統資源用盡'等, 訊息經execSpawnError去除參數值
176
+ proc.on('error', (err) => {
177
+ if (settled) {
178
+ return
179
+ }
180
+ settled = true
181
+ clearTimeout(timer)
182
+ let e = execSpawnError(err)
183
+ pm.resolve({
184
+ ok: false,
185
+ stdout: '',
186
+ stderr: '',
187
+ code: null,
188
+ error: `${e.code}: ${e.message}`,
189
+ durationMs: Date.now() - startTime,
190
+ pid: proc.pid,
191
+ })
192
+ })
193
+
194
+ //stdio, EMFILE、ENFILE時node未建立(undefined), 由上方error回報
195
+ if (!proc.stdout || !proc.stderr || !proc.stdin) {
196
+ return pm
197
+ }
149
198
 
150
199
  //stdout data, 經TextDecoder跨chunk解碼
151
200
  proc.stdout.on('data', (chunk) => {
@@ -183,7 +232,7 @@ function execCliOnce(command, args = [], opt = {}) {
183
232
  proc.stdin.end()
184
233
 
185
234
  //timer, 逾時觸發時調用execProcessKillPid殺整棵程序樹
186
- let timer = setTimeout(() => {
235
+ timer = setTimeout(() => {
187
236
  if (settled) {
188
237
  return
189
238
  }
@@ -213,24 +262,6 @@ function execCliOnce(command, args = [], opt = {}) {
213
262
 
214
263
  }, timeoutMs)
215
264
 
216
- //error, 監聽(例如執行spawn本身)錯誤訊息, 可能為'找不到可執行檔'(ENOENT), '權限不足', '系統資源用盡'等
217
- proc.on('error', (err) => {
218
- if (settled) {
219
- return
220
- }
221
- settled = true
222
- clearTimeout(timer)
223
- pm.resolve({
224
- ok: false,
225
- stdout: '',
226
- stderr: '',
227
- code: null,
228
- error: `${err.code || 'UNKNOWN'}: ${err.message}`,
229
- durationMs: Date.now() - startTime,
230
- pid: proc.pid,
231
- })
232
- })
233
-
234
265
  //close
235
266
  proc.on('close', (code, signal) => {
236
267
  if (settled) {
@@ -314,7 +345,7 @@ function execCliOnce(command, args = [], opt = {}) {
314
345
  * 通用CLI子程序調用,封裝逾時、進程樹清理、輸出驗證、結構化錯誤回報與自動重試
315
346
  * 各參數原樣傳遞給目標CLI,支援中文
316
347
  * Windows下npm全域安裝之命令為.cmd批次檔,Node.js spawn無法直接執行(CVE-2024-27980安全修正後回EINVAL),內部已參考cross-spawn自動解析.cmd入口並繞過cmd.exe,故可支援含多行文字之參數
317
- * 本函數不throw,一律以結果物件之ok與error欄位回報成敗
348
+ * 本函數不throw,一律以結果物件之ok與error欄位回報成敗,error不含args與env之值(子程序自身之輸出另見stdout、stderr)
318
349
  *
319
350
  * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/execCli.test.mjs Github}
320
351
  * @memberOf wsemi
@@ -326,10 +357,10 @@ function execCliOnce(command, args = [], opt = {}) {
326
357
  * @param {String} [opt.input=undefined] 輸入傳入子進程stdin之字串,預設undefined代表不寫入stdin
327
358
  * @param {String|Function} [opt.validate=undefined] 輸入stdout驗證規則字串或自訂驗證函數,規則字串支援'nonempty'(非空)、'json'(可JSON.parse)、'min:100'(長度下限),多規則可用逗號串接例如'nonempty,json',自訂函數為(stdout)=>Boolean,預設undefined代表不驗證
328
359
  * @param {Number} [opt.maxBuffer=10485760] 輸入stdout與stderr各自累積之最大字元數正整數,超過部分將不再累積,預設10485760(10MB)
329
- * @param {Function} [opt.onStdout=undefined] 輸入stdout串流回調函數,格式為(chunk)=>{},預設undefined
330
- * @param {Function} [opt.onStderr=undefined] 輸入stderr串流回調函數,格式為(chunk)=>{},預設undefined
360
+ * @param {Function} [opt.onStdout=undefined] 輸入stdout串流回調函數,格式為(chunk)=>{},回調內拋出之錯誤不會被攔截,將成為未捕捉例外,請於回調內自行處理,預設undefined
361
+ * @param {Function} [opt.onStderr=undefined] 輸入stderr串流回調函數,格式為(chunk)=>{},行為同onStdout,預設undefined
331
362
  * @param {Object} [opt.env=undefined] 輸入本次調用額外注入之環境變數物件,會併入process.env之後(同名以此為準,含PYTHONIOENCODING),僅作用於該次子進程而不影響本進程之process.env,故並行調用可各自帶不同值;值為undefined代表移除該變數(可遮蔽繼承值),值為null會成為字面字串'null'故建議勿傳;Windows下環境變數大小寫不敏感,同名不同大小寫(如Path與PATH)亦視為同名覆蓋,預設undefined代表不覆寫任何變數
332
- * @param {Number} [opt.maxRetries=0] 輸入失敗後最大重試次數非負整數,遇ENOENT(命令不存在)或exit code 2(參數錯誤)視為不可重試而立即中止,預設0
363
+ * @param {Number} [opt.maxRetries=0] 輸入失敗後最大重試次數非負整數,遇ENOENT(命令不存在)、exit code 2(參數錯誤)或無法啟動子進程之同步錯誤(如參數過長、權限不足、非有效執行檔、參數含空字元)視為不可重試而立即中止,預設0
333
364
  * @param {Number} [opt.retryDelayMs=5000] 輸入重試間隔毫秒正整數,實際間隔為retryDelayMs乘以重試次數且上限15000ms,預設5000
334
365
  * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否成功布林值)、stdout(標準輸出字串)、stderr(標準錯誤字串)、code(離開碼)、error(錯誤訊息字串,成功時為空字串)、durationMs(耗時毫秒)、pid(子進程pid)、attempts(實際嘗試次數)
335
366
  * @example
@@ -508,6 +539,9 @@ async function execCli(command, args = [], opt = {}) {
508
539
  }
509
540
 
510
541
  //不可重試的錯誤
542
+ if (kNoRetry.has(lastResult)) {
543
+ break //無法啟動子進程之同步錯誤(參數過長、權限不足、非有效執行檔、參數檢查錯誤等), 重試無意義
544
+ }
511
545
  if (lastResult.error.includes('ENOENT')) {
512
546
  break //命令不存在, 重試無意義
513
547
  }
@@ -78,6 +78,9 @@ function resolveCommand(cmd) {
78
78
  */
79
79
  function escapeWinArg(arg) {
80
80
 
81
+ //String, 非字串元素比照node之spawn轉為字串(否則.replace拋TypeError)
82
+ arg = String(arg)
83
+
81
84
  //轉義反斜線 + 雙引號 組合
82
85
  arg = arg.replace(/(\\*)"/g, '$1$1\\"')
83
86
 
@@ -12,7 +12,7 @@ import execCliSession from './execCliSession.mjs'
12
12
  /**
13
13
  * 對stdio協定型CLI依序送出一行一則JSON之請求並收集回應(疊於execCliSession之上),適用codex app-server、MCP之stdio伺服器等以換行分隔JSON之協定(LSP為Content-Length分幀,不適用)
14
14
  * 不內建任何協定知識,initialize/initialized等握手由呼叫端以請求陣列表達
15
- * 本函數不throw,一律以結果物件之ok與error、errorType欄位回報成敗
15
+ * 本函數不throw,一律以結果物件之ok與error、errorType欄位回報成敗,error不含args與env之值
16
16
  *
17
17
  * 規則:
18
18
  * - 請求物件含method者為請求,自動配id(自0遞增)並等待同id之回應;含notify者為通知,不配id,送出即繼續
@@ -34,7 +34,7 @@ import execCliSession from './execCliSession.mjs'
34
34
  * @param {Boolean} [opt.continueOnError=false] 輸入回應含error時是否繼續送出後續請求布林值,預設false
35
35
  * @param {Function} [opt.onNotify=undefined] 輸入伺服器通知(無id訊息)回調函數,格式為(msg)=>{},預設undefined
36
36
  * @param {Function} [opt.onServerRequest=undefined] 輸入伺服器發給客戶端之請求(帶id且含method)回調函數,格式為(msg, session)=>{},可用session.writeLine回覆,預設undefined
37
- * @param {Function} [opt.onStderr=undefined] 輸入stderr片段回調函數,格式為(chunk)=>{},預設undefined
37
+ * @param {Function} [opt.onStderr=undefined] 輸入stderr片段回調函數,格式為(chunk)=>{},預設undefined。onNotify、onServerRequest、onStderr內拋出之錯誤不會被攔截,將成為未捕捉例外,請於回調內自行處理
38
38
  * @returns {Promise} 回傳Promise,resolve回傳結果物件,內含ok(是否全部成功布林值)、results(以method為鍵之result物件,失敗者為null)、responses(依序之回應陣列,每項為{ id, method, result, error })、error(錯誤訊息字串,成功時為空字串)、errorType(錯誤類型字串: params(參數錯誤)、notfound(命令不存在)、timeout(逾時)、exit(子進程於回應前結束)、rpc(回應含error),成功時為空字串)、durationMs(耗時毫秒)、exitCode(子進程離開碼)
39
39
  * @example
40
40
  * //need test in nodejs
@@ -10,6 +10,7 @@ import ispint from './ispint.mjs'
10
10
  import isp0int from './isp0int.mjs'
11
11
  import execProcessKillPid from './execProcessKillPid.mjs'
12
12
  import execCliCore from './execCliCore.mjs'
13
+ import execSpawnError from './_execSpawnError.mjs'
13
14
 
14
15
 
15
16
  //buildSpawnArgs, buildSpawnEnv, 共用核心
@@ -19,7 +20,7 @@ let { buildSpawnArgs, buildSpawnEnv } = execCliCore
19
20
  /**
20
21
  * 建立互動式stdio工作階段(session),用於stdio協定型之長駐CLI(如MCP之stdio伺服器、codex app-server等一行一則JSON之程式),與execCli「寫完input即關閉stdin並等待結束」之一次性契約不同,本函數維持stdin開啟,由呼叫端逐次write,直到呼叫stop()才關閉stdin並等待子進程自行退出,逾寬限期則以execProcessKillPid樹殺
21
22
  * Windows下npm全域安裝之命令為.cmd批次檔,內部經execCliCore.buildSpawnArgs解析為以node執行其JS入口,不使用shell:true,故樹殺可確實涵蓋子孫程序
22
- * 本函數不throw亦不reject,spawn失敗(如ENOENT)以onExit與stop()之結果物件回報
23
+ * 本函數不throw亦不reject,spawn失敗(如ENOENT)以onExit與stop()之結果物件回報,其error不含args與env之值
23
24
  *
24
25
  * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/execCliSession.test.mjs Github}
25
26
  * @memberOf wsemi
@@ -35,7 +36,7 @@ let { buildSpawnArgs, buildSpawnEnv } = execCliCore
35
36
  * @param {Function} [opt.onLine=undefined] 輸入stdout逐行回調函數,格式為(line)=>{},line不含換行(\\r\\n與\\n皆視為換行),子進程結束時殘餘之不完整行亦會發出,預設undefined
36
37
  * @param {Function} [opt.onStdout=undefined] 輸入stdout原始片段回調函數,格式為(chunk)=>{},已經UTF-8跨chunk解碼,供非行式協定(如LSP之Content-Length分幀)自行分幀,預設undefined
37
38
  * @param {Function} [opt.onStderr=undefined] 輸入stderr片段回調函數,格式為(chunk)=>{},預設undefined
38
- * @param {Function} [opt.onExit=undefined] 輸入子進程結束回調函數,格式為(result)=>{},result同stop()之回傳,預設undefined
39
+ * @param {Function} [opt.onExit=undefined] 輸入子進程結束回調函數,格式為(result)=>{},result同stop()之回傳,預設undefined。onLine、onStdout、onStderr、onExit內拋出之錯誤不會被攔截,將成為未捕捉例外,請於回調內自行處理
39
40
  * @returns {Object} 回傳工作階段物件s,內含pid(子進程pid,spawn失敗為null)、exited(是否已結束布林值)、write(str)(寫入stdin,回傳Promise,resolve為是否寫入成功布林值,子進程已結束時靜默resolve(false))、writeLine(str)(補換行後寫入)、stop()(關閉stdin並等待結束,回傳Promise,resolve回傳結果物件,內含code、signal、exited、timeout、killed、error、stderr、durationMs、pid;多次呼叫回傳同一Promise)
40
41
  * @example
41
42
  * //need test in nodejs
@@ -212,10 +213,10 @@ function execCliSession(command, args = [], opt = {}) {
212
213
  return s
213
214
  }
214
215
 
215
- //spawn
216
- let sp = buildSpawnArgs(command, args)
216
+ //spawn, buildSpawnArgs之拋錯亦於此回報
217
217
  let proc
218
218
  try {
219
+ let sp = buildSpawnArgs(command, args)
219
220
  proc = spawn(sp.file, sp.args, {
220
221
  cwd,
221
222
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -225,17 +226,33 @@ function execCliSession(command, args = [], opt = {}) {
225
226
  })
226
227
  }
227
228
  catch (err) {
228
- //spawn同步拋錯(如參數無效EINVAL)
229
+ //spawn同步拋錯(如EPERM、ENAMETOOLONG、參數檢查錯誤), 訊息經execSpawnError去除參數值
230
+ let e = execSpawnError(err)
229
231
  s.write = async () => false
230
232
  s.writeLine = async () => false
231
233
  s.stop = stopNoProc
232
234
  setTimeout(() => {
233
- settle({ error: `${err.code || 'UNKNOWN'}: ${err.message}` }) //待確認用err.toString()還是err.message更佳 bbb
235
+ settle({ error: `${e.code}: ${e.message}` })
234
236
  }, 1)
235
237
  return s
236
238
  }
237
239
  s.pid = proc.pid || null
238
240
 
241
+ //error, 須於存取stdio前監聽: node對EMFILE、ENFILE不建立stdio即於nextTick發出'error', 先存取會拋TypeError且'error'無人監聽而拉倒程序
242
+ // 可能為'找不到可執行檔'(ENOENT), '權限不足', '系統資源用盡'等, 訊息經execSpawnError去除參數值
243
+ proc.on('error', (err) => {
244
+ let e = execSpawnError(err)
245
+ settle({ error: `${e.code}: ${e.message}` })
246
+ })
247
+
248
+ //stdio, EMFILE、ENFILE時node未建立(undefined), 由上方error回報
249
+ if (!proc.stdout || !proc.stderr || !proc.stdin) {
250
+ s.write = async () => false
251
+ s.writeLine = async () => false
252
+ s.stop = stopNoProc
253
+ return s
254
+ }
255
+
239
256
  //TextDecoder, 跨chunk邊界正確解碼UTF-8, 避免多位元組中文字元被切成亂碼(U+FFFD)
240
257
  let stdoutDecoder = new TextDecoder('utf-8')
241
258
  let stderrDecoder = new TextDecoder('utf-8')
@@ -327,11 +344,6 @@ function execCliSession(command, args = [], opt = {}) {
327
344
  }, timeoutMs)
328
345
  }
329
346
 
330
- //error, 監聽(例如執行spawn本身)錯誤訊息, 可能為'找不到可執行檔'(ENOENT), '權限不足', '系統資源用盡'等
331
- proc.on('error', (err) => {
332
- settle({ error: `${err.code || 'UNKNOWN'}: ${err.message}` }) //待確認用err.toString()還是err.message更佳 bbb
333
- })
334
-
335
347
  //close
336
348
  proc.on('close', (code, signal) => {
337
349
  if (settled) {