execbro 0.0.1-reserve → 1.10.12

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 (475) hide show
  1. package/LICENSE +32 -0
  2. package/README.md +496 -0
  3. package/build/__tests__/helpers/fake-cdp-server.d.ts +56 -0
  4. package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -0
  5. package/build/__tests__/helpers/fake-cdp-server.js +120 -0
  6. package/build/__tests__/helpers/fake-cdp-server.js.map +1 -0
  7. package/build/__tests__/helpers/tap-test-helpers.d.ts +36 -0
  8. package/build/__tests__/helpers/tap-test-helpers.d.ts.map +1 -0
  9. package/build/__tests__/helpers/tap-test-helpers.js +130 -0
  10. package/build/__tests__/helpers/tap-test-helpers.js.map +1 -0
  11. package/build/__tests__/integration/auto-reconnect.test.d.ts +2 -0
  12. package/build/__tests__/integration/auto-reconnect.test.d.ts.map +1 -0
  13. package/build/__tests__/integration/auto-reconnect.test.js +118 -0
  14. package/build/__tests__/integration/auto-reconnect.test.js.map +1 -0
  15. package/build/__tests__/integration/connection-health.test.d.ts +2 -0
  16. package/build/__tests__/integration/connection-health.test.d.ts.map +1 -0
  17. package/build/__tests__/integration/connection-health.test.js +157 -0
  18. package/build/__tests__/integration/connection-health.test.js.map +1 -0
  19. package/build/__tests__/integration/execute-in-app.test.d.ts +2 -0
  20. package/build/__tests__/integration/execute-in-app.test.d.ts.map +1 -0
  21. package/build/__tests__/integration/execute-in-app.test.js +124 -0
  22. package/build/__tests__/integration/execute-in-app.test.js.map +1 -0
  23. package/build/__tests__/integration/per-call-timeout.test.d.ts +2 -0
  24. package/build/__tests__/integration/per-call-timeout.test.d.ts.map +1 -0
  25. package/build/__tests__/integration/per-call-timeout.test.js +103 -0
  26. package/build/__tests__/integration/per-call-timeout.test.js.map +1 -0
  27. package/build/__tests__/integration/tap-strategies.test.d.ts +2 -0
  28. package/build/__tests__/integration/tap-strategies.test.d.ts.map +1 -0
  29. package/build/__tests__/integration/tap-strategies.test.js +330 -0
  30. package/build/__tests__/integration/tap-strategies.test.js.map +1 -0
  31. package/build/__tests__/integration/tools.test.d.ts +2 -0
  32. package/build/__tests__/integration/tools.test.d.ts.map +1 -0
  33. package/build/__tests__/integration/tools.test.js +227 -0
  34. package/build/__tests__/integration/tools.test.js.map +1 -0
  35. package/build/__tests__/setup.d.ts +2 -0
  36. package/build/__tests__/setup.d.ts.map +1 -0
  37. package/build/__tests__/setup.js +15 -0
  38. package/build/__tests__/setup.js.map +1 -0
  39. package/build/__tests__/unit/androidEmulatorAvds.test.d.ts +2 -0
  40. package/build/__tests__/unit/androidEmulatorAvds.test.d.ts.map +1 -0
  41. package/build/__tests__/unit/androidEmulatorAvds.test.js +98 -0
  42. package/build/__tests__/unit/androidEmulatorAvds.test.js.map +1 -0
  43. package/build/__tests__/unit/buildToken.test.d.ts +2 -0
  44. package/build/__tests__/unit/buildToken.test.d.ts.map +1 -0
  45. package/build/__tests__/unit/buildToken.test.js +22 -0
  46. package/build/__tests__/unit/buildToken.test.js.map +1 -0
  47. package/build/__tests__/unit/bundle.test.d.ts +2 -0
  48. package/build/__tests__/unit/bundle.test.d.ts.map +1 -0
  49. package/build/__tests__/unit/bundle.test.js +53 -0
  50. package/build/__tests__/unit/bundle.test.js.map +1 -0
  51. package/build/__tests__/unit/burst.test.d.ts +2 -0
  52. package/build/__tests__/unit/burst.test.d.ts.map +1 -0
  53. package/build/__tests__/unit/burst.test.js +54 -0
  54. package/build/__tests__/unit/burst.test.js.map +1 -0
  55. package/build/__tests__/unit/connection-health.test.d.ts +2 -0
  56. package/build/__tests__/unit/connection-health.test.d.ts.map +1 -0
  57. package/build/__tests__/unit/connection-health.test.js +38 -0
  58. package/build/__tests__/unit/connection-health.test.js.map +1 -0
  59. package/build/__tests__/unit/debugGlobals.test.d.ts +2 -0
  60. package/build/__tests__/unit/debugGlobals.test.d.ts.map +1 -0
  61. package/build/__tests__/unit/debugGlobals.test.js +14 -0
  62. package/build/__tests__/unit/debugGlobals.test.js.map +1 -0
  63. package/build/__tests__/unit/deviceDiscovery.test.d.ts +2 -0
  64. package/build/__tests__/unit/deviceDiscovery.test.d.ts.map +1 -0
  65. package/build/__tests__/unit/deviceDiscovery.test.js +119 -0
  66. package/build/__tests__/unit/deviceDiscovery.test.js.map +1 -0
  67. package/build/__tests__/unit/deviceResolver.test.d.ts +2 -0
  68. package/build/__tests__/unit/deviceResolver.test.d.ts.map +1 -0
  69. package/build/__tests__/unit/deviceResolver.test.js +261 -0
  70. package/build/__tests__/unit/deviceResolver.test.js.map +1 -0
  71. package/build/__tests__/unit/escapeNonAscii.test.d.ts +2 -0
  72. package/build/__tests__/unit/escapeNonAscii.test.d.ts.map +1 -0
  73. package/build/__tests__/unit/escapeNonAscii.test.js +76 -0
  74. package/build/__tests__/unit/escapeNonAscii.test.js.map +1 -0
  75. package/build/__tests__/unit/exec.test.d.ts +2 -0
  76. package/build/__tests__/unit/exec.test.d.ts.map +1 -0
  77. package/build/__tests__/unit/exec.test.js +54 -0
  78. package/build/__tests__/unit/exec.test.js.map +1 -0
  79. package/build/__tests__/unit/executor.test.d.ts +2 -0
  80. package/build/__tests__/unit/executor.test.d.ts.map +1 -0
  81. package/build/__tests__/unit/executor.test.js +220 -0
  82. package/build/__tests__/unit/executor.test.js.map +1 -0
  83. package/build/__tests__/unit/failureArtifact.test.d.ts +2 -0
  84. package/build/__tests__/unit/failureArtifact.test.d.ts.map +1 -0
  85. package/build/__tests__/unit/failureArtifact.test.js +207 -0
  86. package/build/__tests__/unit/failureArtifact.test.js.map +1 -0
  87. package/build/__tests__/unit/fastRefreshRecorder.test.d.ts +2 -0
  88. package/build/__tests__/unit/fastRefreshRecorder.test.d.ts.map +1 -0
  89. package/build/__tests__/unit/fastRefreshRecorder.test.js +68 -0
  90. package/build/__tests__/unit/fastRefreshRecorder.test.js.map +1 -0
  91. package/build/__tests__/unit/fastRefreshTools.test.d.ts +2 -0
  92. package/build/__tests__/unit/fastRefreshTools.test.d.ts.map +1 -0
  93. package/build/__tests__/unit/fastRefreshTools.test.js +112 -0
  94. package/build/__tests__/unit/fastRefreshTools.test.js.map +1 -0
  95. package/build/__tests__/unit/fiberMatch.test.d.ts +2 -0
  96. package/build/__tests__/unit/fiberMatch.test.d.ts.map +1 -0
  97. package/build/__tests__/unit/fiberMatch.test.js +114 -0
  98. package/build/__tests__/unit/fiberMatch.test.js.map +1 -0
  99. package/build/__tests__/unit/fingerprint.test.d.ts +2 -0
  100. package/build/__tests__/unit/fingerprint.test.d.ts.map +1 -0
  101. package/build/__tests__/unit/fingerprint.test.js +99 -0
  102. package/build/__tests__/unit/fingerprint.test.js.map +1 -0
  103. package/build/__tests__/unit/focusedInput.test.d.ts +2 -0
  104. package/build/__tests__/unit/focusedInput.test.d.ts.map +1 -0
  105. package/build/__tests__/unit/focusedInput.test.js +58 -0
  106. package/build/__tests__/unit/focusedInput.test.js.map +1 -0
  107. package/build/__tests__/unit/focusedInputTools.test.d.ts +2 -0
  108. package/build/__tests__/unit/focusedInputTools.test.d.ts.map +1 -0
  109. package/build/__tests__/unit/focusedInputTools.test.js +79 -0
  110. package/build/__tests__/unit/focusedInputTools.test.js.map +1 -0
  111. package/build/__tests__/unit/iconSemantics.test.d.ts +2 -0
  112. package/build/__tests__/unit/iconSemantics.test.d.ts.map +1 -0
  113. package/build/__tests__/unit/iconSemantics.test.js +80 -0
  114. package/build/__tests__/unit/iconSemantics.test.js.map +1 -0
  115. package/build/__tests__/unit/imageBuffer.test.d.ts +2 -0
  116. package/build/__tests__/unit/imageBuffer.test.d.ts.map +1 -0
  117. package/build/__tests__/unit/imageBuffer.test.js +128 -0
  118. package/build/__tests__/unit/imageBuffer.test.js.map +1 -0
  119. package/build/__tests__/unit/logs.test.d.ts +2 -0
  120. package/build/__tests__/unit/logs.test.d.ts.map +1 -0
  121. package/build/__tests__/unit/logs.test.js +90 -0
  122. package/build/__tests__/unit/logs.test.js.map +1 -0
  123. package/build/__tests__/unit/measureComponent.test.d.ts +2 -0
  124. package/build/__tests__/unit/measureComponent.test.d.ts.map +1 -0
  125. package/build/__tests__/unit/measureComponent.test.js +66 -0
  126. package/build/__tests__/unit/measureComponent.test.js.map +1 -0
  127. package/build/__tests__/unit/measureComponentTools.test.d.ts +2 -0
  128. package/build/__tests__/unit/measureComponentTools.test.d.ts.map +1 -0
  129. package/build/__tests__/unit/measureComponentTools.test.js +94 -0
  130. package/build/__tests__/unit/measureComponentTools.test.js.map +1 -0
  131. package/build/__tests__/unit/metro.test.d.ts +2 -0
  132. package/build/__tests__/unit/metro.test.d.ts.map +1 -0
  133. package/build/__tests__/unit/metro.test.js +61 -0
  134. package/build/__tests__/unit/metro.test.js.map +1 -0
  135. package/build/__tests__/unit/network.test.d.ts +2 -0
  136. package/build/__tests__/unit/network.test.d.ts.map +1 -0
  137. package/build/__tests__/unit/network.test.js +102 -0
  138. package/build/__tests__/unit/network.test.js.map +1 -0
  139. package/build/__tests__/unit/networkInterceptor.test.d.ts +2 -0
  140. package/build/__tests__/unit/networkInterceptor.test.d.ts.map +1 -0
  141. package/build/__tests__/unit/networkInterceptor.test.js +104 -0
  142. package/build/__tests__/unit/networkInterceptor.test.js.map +1 -0
  143. package/build/__tests__/unit/probe.test.d.ts +2 -0
  144. package/build/__tests__/unit/probe.test.d.ts.map +1 -0
  145. package/build/__tests__/unit/probe.test.js +62 -0
  146. package/build/__tests__/unit/probe.test.js.map +1 -0
  147. package/build/__tests__/unit/rnGlobalsBootstrap.test.d.ts +2 -0
  148. package/build/__tests__/unit/rnGlobalsBootstrap.test.d.ts.map +1 -0
  149. package/build/__tests__/unit/rnGlobalsBootstrap.test.js +29 -0
  150. package/build/__tests__/unit/rnGlobalsBootstrap.test.js.map +1 -0
  151. package/build/__tests__/unit/screenState.test.d.ts +2 -0
  152. package/build/__tests__/unit/screenState.test.d.ts.map +1 -0
  153. package/build/__tests__/unit/screenState.test.js +186 -0
  154. package/build/__tests__/unit/screenState.test.js.map +1 -0
  155. package/build/__tests__/unit/screenshot-diff.test.d.ts +2 -0
  156. package/build/__tests__/unit/screenshot-diff.test.d.ts.map +1 -0
  157. package/build/__tests__/unit/screenshot-diff.test.js +97 -0
  158. package/build/__tests__/unit/screenshot-diff.test.js.map +1 -0
  159. package/build/__tests__/unit/tap-evidence.test.d.ts +2 -0
  160. package/build/__tests__/unit/tap-evidence.test.d.ts.map +1 -0
  161. package/build/__tests__/unit/tap-evidence.test.js +89 -0
  162. package/build/__tests__/unit/tap-evidence.test.js.map +1 -0
  163. package/build/__tests__/unit/tap.test.d.ts +2 -0
  164. package/build/__tests__/unit/tap.test.d.ts.map +1 -0
  165. package/build/__tests__/unit/tap.test.js +769 -0
  166. package/build/__tests__/unit/tap.test.js.map +1 -0
  167. package/build/__tests__/unit/timeoutClamp.test.d.ts +2 -0
  168. package/build/__tests__/unit/timeoutClamp.test.d.ts.map +1 -0
  169. package/build/__tests__/unit/timeoutClamp.test.js +17 -0
  170. package/build/__tests__/unit/timeoutClamp.test.js.map +1 -0
  171. package/build/__tests__/unit/toolDescriptions.test.d.ts +2 -0
  172. package/build/__tests__/unit/toolDescriptions.test.d.ts.map +1 -0
  173. package/build/__tests__/unit/toolDescriptions.test.js +145 -0
  174. package/build/__tests__/unit/toolDescriptions.test.js.map +1 -0
  175. package/build/__tests__/unit/transportClassify.test.d.ts +2 -0
  176. package/build/__tests__/unit/transportClassify.test.d.ts.map +1 -0
  177. package/build/__tests__/unit/transportClassify.test.js +60 -0
  178. package/build/__tests__/unit/transportClassify.test.js.map +1 -0
  179. package/build/__tests__/unit/verifyAction.test.d.ts +2 -0
  180. package/build/__tests__/unit/verifyAction.test.d.ts.map +1 -0
  181. package/build/__tests__/unit/verifyAction.test.js +26 -0
  182. package/build/__tests__/unit/verifyAction.test.js.map +1 -0
  183. package/build/core/android.d.ts +299 -0
  184. package/build/core/android.d.ts.map +1 -0
  185. package/build/core/android.js +1582 -0
  186. package/build/core/android.js.map +1 -0
  187. package/build/core/appDetection.d.ts +20 -0
  188. package/build/core/appDetection.d.ts.map +1 -0
  189. package/build/core/appDetection.js +167 -0
  190. package/build/core/appDetection.js.map +1 -0
  191. package/build/core/bundle.d.ts +49 -0
  192. package/build/core/bundle.d.ts.map +1 -0
  193. package/build/core/bundle.js +356 -0
  194. package/build/core/bundle.js.map +1 -0
  195. package/build/core/componentSearch.d.ts +41 -0
  196. package/build/core/componentSearch.d.ts.map +1 -0
  197. package/build/core/componentSearch.js +588 -0
  198. package/build/core/componentSearch.js.map +1 -0
  199. package/build/core/componentTree.d.ts +13 -0
  200. package/build/core/componentTree.d.ts.map +1 -0
  201. package/build/core/componentTree.js +275 -0
  202. package/build/core/componentTree.js.map +1 -0
  203. package/build/core/config.d.ts +9 -0
  204. package/build/core/config.d.ts.map +1 -0
  205. package/build/core/config.js +28 -0
  206. package/build/core/config.js.map +1 -0
  207. package/build/core/connection.d.ts +102 -0
  208. package/build/core/connection.d.ts.map +1 -0
  209. package/build/core/connection.js +1710 -0
  210. package/build/core/connection.js.map +1 -0
  211. package/build/core/connectionState.d.ts +122 -0
  212. package/build/core/connectionState.d.ts.map +1 -0
  213. package/build/core/connectionState.js +313 -0
  214. package/build/core/connectionState.js.map +1 -0
  215. package/build/core/debugGlobals.d.ts +6 -0
  216. package/build/core/debugGlobals.d.ts.map +1 -0
  217. package/build/core/debugGlobals.js +370 -0
  218. package/build/core/debugGlobals.js.map +1 -0
  219. package/build/core/deviceDiscovery.d.ts +52 -0
  220. package/build/core/deviceDiscovery.d.ts.map +1 -0
  221. package/build/core/deviceDiscovery.js +74 -0
  222. package/build/core/deviceDiscovery.js.map +1 -0
  223. package/build/core/deviceResolver.d.ts +44 -0
  224. package/build/core/deviceResolver.d.ts.map +1 -0
  225. package/build/core/deviceResolver.js +225 -0
  226. package/build/core/deviceResolver.js.map +1 -0
  227. package/build/core/errorScreenParser.d.ts +30 -0
  228. package/build/core/errorScreenParser.d.ts.map +1 -0
  229. package/build/core/errorScreenParser.js +198 -0
  230. package/build/core/errorScreenParser.js.map +1 -0
  231. package/build/core/errors.d.ts +14 -0
  232. package/build/core/errors.d.ts.map +1 -0
  233. package/build/core/errors.js +17 -0
  234. package/build/core/errors.js.map +1 -0
  235. package/build/core/escapeNonAscii.d.ts +18 -0
  236. package/build/core/escapeNonAscii.d.ts.map +1 -0
  237. package/build/core/escapeNonAscii.js +352 -0
  238. package/build/core/escapeNonAscii.js.map +1 -0
  239. package/build/core/exec.d.ts +22 -0
  240. package/build/core/exec.d.ts.map +1 -0
  241. package/build/core/exec.js +54 -0
  242. package/build/core/exec.js.map +1 -0
  243. package/build/core/executor.d.ts +9 -0
  244. package/build/core/executor.d.ts.map +1 -0
  245. package/build/core/executor.js +12 -0
  246. package/build/core/executor.js.map +1 -0
  247. package/build/core/failureArtifact.d.ts +120 -0
  248. package/build/core/failureArtifact.d.ts.map +1 -0
  249. package/build/core/failureArtifact.js +113 -0
  250. package/build/core/failureArtifact.js.map +1 -0
  251. package/build/core/fastRefreshRecorder.d.ts +23 -0
  252. package/build/core/fastRefreshRecorder.d.ts.map +1 -0
  253. package/build/core/fastRefreshRecorder.js +83 -0
  254. package/build/core/fastRefreshRecorder.js.map +1 -0
  255. package/build/core/fastRefreshTools.d.ts +19 -0
  256. package/build/core/fastRefreshTools.d.ts.map +1 -0
  257. package/build/core/fastRefreshTools.js +71 -0
  258. package/build/core/fastRefreshTools.js.map +1 -0
  259. package/build/core/feedback.d.ts +18 -0
  260. package/build/core/feedback.d.ts.map +1 -0
  261. package/build/core/feedback.js +73 -0
  262. package/build/core/feedback.js.map +1 -0
  263. package/build/core/fiberMatch.d.ts +25 -0
  264. package/build/core/fiberMatch.d.ts.map +1 -0
  265. package/build/core/fiberMatch.js +35 -0
  266. package/build/core/fiberMatch.js.map +1 -0
  267. package/build/core/fingerprint.d.ts +4 -0
  268. package/build/core/fingerprint.d.ts.map +1 -0
  269. package/build/core/fingerprint.js +47 -0
  270. package/build/core/fingerprint.js.map +1 -0
  271. package/build/core/focusedInput.d.ts +27 -0
  272. package/build/core/focusedInput.d.ts.map +1 -0
  273. package/build/core/focusedInput.js +110 -0
  274. package/build/core/focusedInput.js.map +1 -0
  275. package/build/core/focusedInputTools.d.ts +21 -0
  276. package/build/core/focusedInputTools.d.ts.map +1 -0
  277. package/build/core/focusedInputTools.js +51 -0
  278. package/build/core/focusedInputTools.js.map +1 -0
  279. package/build/core/format.d.ts +8 -0
  280. package/build/core/format.d.ts.map +1 -0
  281. package/build/core/format.js +34 -0
  282. package/build/core/format.js.map +1 -0
  283. package/build/core/guides.d.ts +21 -0
  284. package/build/core/guides.d.ts.map +1 -0
  285. package/build/core/guides.js +397 -0
  286. package/build/core/guides.js.map +1 -0
  287. package/build/core/iconSemantics.d.ts +18 -0
  288. package/build/core/iconSemantics.d.ts.map +1 -0
  289. package/build/core/iconSemantics.js +114 -0
  290. package/build/core/iconSemantics.js.map +1 -0
  291. package/build/core/imageBuffer.d.ts +37 -0
  292. package/build/core/imageBuffer.d.ts.map +1 -0
  293. package/build/core/imageBuffer.js +58 -0
  294. package/build/core/imageBuffer.js.map +1 -0
  295. package/build/core/index.d.ts +37 -0
  296. package/build/core/index.d.ts.map +1 -0
  297. package/build/core/index.js +66 -0
  298. package/build/core/index.js.map +1 -0
  299. package/build/core/inspector.d.ts +55 -0
  300. package/build/core/inspector.d.ts.map +1 -0
  301. package/build/core/inspector.js +603 -0
  302. package/build/core/inspector.js.map +1 -0
  303. package/build/core/ios.d.ts +263 -0
  304. package/build/core/ios.d.ts.map +1 -0
  305. package/build/core/ios.js +1705 -0
  306. package/build/core/ios.js.map +1 -0
  307. package/build/core/jsExecute.d.ts +62 -0
  308. package/build/core/jsExecute.d.ts.map +1 -0
  309. package/build/core/jsExecute.js +696 -0
  310. package/build/core/jsExecute.js.map +1 -0
  311. package/build/core/license.d.ts +48 -0
  312. package/build/core/license.d.ts.map +1 -0
  313. package/build/core/license.js +267 -0
  314. package/build/core/license.js.map +1 -0
  315. package/build/core/logbox.d.ts +58 -0
  316. package/build/core/logbox.d.ts.map +1 -0
  317. package/build/core/logbox.js +330 -0
  318. package/build/core/logbox.js.map +1 -0
  319. package/build/core/logs.d.ts +44 -0
  320. package/build/core/logs.d.ts.map +1 -0
  321. package/build/core/logs.js +149 -0
  322. package/build/core/logs.js.map +1 -0
  323. package/build/core/measureComponent.d.ts +19 -0
  324. package/build/core/measureComponent.d.ts.map +1 -0
  325. package/build/core/measureComponent.js +94 -0
  326. package/build/core/measureComponent.js.map +1 -0
  327. package/build/core/measureComponentTools.d.ts +6 -0
  328. package/build/core/measureComponentTools.d.ts.map +1 -0
  329. package/build/core/measureComponentTools.js +43 -0
  330. package/build/core/measureComponentTools.js.map +1 -0
  331. package/build/core/metro.d.ts +31 -0
  332. package/build/core/metro.d.ts.map +1 -0
  333. package/build/core/metro.js +124 -0
  334. package/build/core/metro.js.map +1 -0
  335. package/build/core/nativeOnlyHints.d.ts +14 -0
  336. package/build/core/nativeOnlyHints.d.ts.map +1 -0
  337. package/build/core/nativeOnlyHints.js +58 -0
  338. package/build/core/nativeOnlyHints.js.map +1 -0
  339. package/build/core/network.d.ts +43 -0
  340. package/build/core/network.d.ts.map +1 -0
  341. package/build/core/network.js +217 -0
  342. package/build/core/network.js.map +1 -0
  343. package/build/core/networkInterceptor.d.ts +30 -0
  344. package/build/core/networkInterceptor.d.ts.map +1 -0
  345. package/build/core/networkInterceptor.js +211 -0
  346. package/build/core/networkInterceptor.js.map +1 -0
  347. package/build/core/ocr.d.ts +87 -0
  348. package/build/core/ocr.d.ts.map +1 -0
  349. package/build/core/ocr.js +335 -0
  350. package/build/core/ocr.js.map +1 -0
  351. package/build/core/paths.d.ts +2 -0
  352. package/build/core/paths.d.ts.map +1 -0
  353. package/build/core/paths.js +28 -0
  354. package/build/core/paths.js.map +1 -0
  355. package/build/core/posthog.d.ts +5 -0
  356. package/build/core/posthog.d.ts.map +1 -0
  357. package/build/core/posthog.js +52 -0
  358. package/build/core/posthog.js.map +1 -0
  359. package/build/core/pressables.d.ts +46 -0
  360. package/build/core/pressables.d.ts.map +1 -0
  361. package/build/core/pressables.js +1719 -0
  362. package/build/core/pressables.js.map +1 -0
  363. package/build/core/probe.d.ts +12 -0
  364. package/build/core/probe.d.ts.map +1 -0
  365. package/build/core/probe.js +56 -0
  366. package/build/core/probe.js.map +1 -0
  367. package/build/core/redux.d.ts +22 -0
  368. package/build/core/redux.d.ts.map +1 -0
  369. package/build/core/redux.js +116 -0
  370. package/build/core/redux.js.map +1 -0
  371. package/build/core/register.d.ts +8 -0
  372. package/build/core/register.d.ts.map +1 -0
  373. package/build/core/register.js +202 -0
  374. package/build/core/register.js.map +1 -0
  375. package/build/core/rnGlobalsBootstrap.d.ts +16 -0
  376. package/build/core/rnGlobalsBootstrap.d.ts.map +1 -0
  377. package/build/core/rnGlobalsBootstrap.js +116 -0
  378. package/build/core/rnGlobalsBootstrap.js.map +1 -0
  379. package/build/core/screenLayout.d.ts +53 -0
  380. package/build/core/screenLayout.d.ts.map +1 -0
  381. package/build/core/screenLayout.js +878 -0
  382. package/build/core/screenLayout.js.map +1 -0
  383. package/build/core/screenState.d.ts +98 -0
  384. package/build/core/screenState.d.ts.map +1 -0
  385. package/build/core/screenState.js +1121 -0
  386. package/build/core/screenState.js.map +1 -0
  387. package/build/core/sdkBridge.d.ts +67 -0
  388. package/build/core/sdkBridge.d.ts.map +1 -0
  389. package/build/core/sdkBridge.js +148 -0
  390. package/build/core/sdkBridge.js.map +1 -0
  391. package/build/core/state.d.ts +37 -0
  392. package/build/core/state.d.ts.map +1 -0
  393. package/build/core/state.js +124 -0
  394. package/build/core/state.js.map +1 -0
  395. package/build/core/telemetry.d.ts +50 -0
  396. package/build/core/telemetry.d.ts.map +1 -0
  397. package/build/core/telemetry.js +653 -0
  398. package/build/core/telemetry.js.map +1 -0
  399. package/build/core/toolHelpers.d.ts +24 -0
  400. package/build/core/toolHelpers.d.ts.map +1 -0
  401. package/build/core/toolHelpers.js +118 -0
  402. package/build/core/toolHelpers.js.map +1 -0
  403. package/build/core/types.d.ts +162 -0
  404. package/build/core/types.d.ts.map +1 -0
  405. package/build/core/types.js +2 -0
  406. package/build/core/types.js.map +1 -0
  407. package/build/index.d.ts +4 -0
  408. package/build/index.d.ts.map +1 -0
  409. package/build/index.js +132 -0
  410. package/build/index.js.map +1 -0
  411. package/build/pro/screenshot-diff.d.ts +10 -0
  412. package/build/pro/screenshot-diff.d.ts.map +1 -0
  413. package/build/pro/screenshot-diff.js +38 -0
  414. package/build/pro/screenshot-diff.js.map +1 -0
  415. package/build/pro/tap.d.ts +295 -0
  416. package/build/pro/tap.d.ts.map +1 -0
  417. package/build/pro/tap.js +1937 -0
  418. package/build/pro/tap.js.map +1 -0
  419. package/build/pro/verifyAction.d.ts +50 -0
  420. package/build/pro/verifyAction.d.ts.map +1 -0
  421. package/build/pro/verifyAction.js +285 -0
  422. package/build/pro/verifyAction.js.map +1 -0
  423. package/build/tools/_deviceArg.d.ts +45 -0
  424. package/build/tools/_deviceArg.d.ts.map +1 -0
  425. package/build/tools/_deviceArg.js +58 -0
  426. package/build/tools/_deviceArg.js.map +1 -0
  427. package/build/tools/accountTools.d.ts +46 -0
  428. package/build/tools/accountTools.d.ts.map +1 -0
  429. package/build/tools/accountTools.js +223 -0
  430. package/build/tools/accountTools.js.map +1 -0
  431. package/build/tools/bundleTools.d.ts +3 -0
  432. package/build/tools/bundleTools.d.ts.map +1 -0
  433. package/build/tools/bundleTools.js +375 -0
  434. package/build/tools/bundleTools.js.map +1 -0
  435. package/build/tools/componentTools.d.ts +3 -0
  436. package/build/tools/componentTools.d.ts.map +1 -0
  437. package/build/tools/componentTools.js +745 -0
  438. package/build/tools/componentTools.js.map +1 -0
  439. package/build/tools/connectionTools.d.ts +3 -0
  440. package/build/tools/connectionTools.d.ts.map +1 -0
  441. package/build/tools/connectionTools.js +625 -0
  442. package/build/tools/connectionTools.js.map +1 -0
  443. package/build/tools/deviceTools.d.ts +3 -0
  444. package/build/tools/deviceTools.d.ts.map +1 -0
  445. package/build/tools/deviceTools.js +423 -0
  446. package/build/tools/deviceTools.js.map +1 -0
  447. package/build/tools/executionTools.d.ts +3 -0
  448. package/build/tools/executionTools.d.ts.map +1 -0
  449. package/build/tools/executionTools.js +243 -0
  450. package/build/tools/executionTools.js.map +1 -0
  451. package/build/tools/interactionTools.d.ts +3 -0
  452. package/build/tools/interactionTools.d.ts.map +1 -0
  453. package/build/tools/interactionTools.js +539 -0
  454. package/build/tools/interactionTools.js.map +1 -0
  455. package/build/tools/logTools.d.ts +3 -0
  456. package/build/tools/logTools.d.ts.map +1 -0
  457. package/build/tools/logTools.js +371 -0
  458. package/build/tools/logTools.js.map +1 -0
  459. package/build/tools/metaTools.d.ts +7 -0
  460. package/build/tools/metaTools.d.ts.map +1 -0
  461. package/build/tools/metaTools.js +186 -0
  462. package/build/tools/metaTools.js.map +1 -0
  463. package/build/tools/networkTools.d.ts +3 -0
  464. package/build/tools/networkTools.d.ts.map +1 -0
  465. package/build/tools/networkTools.js +478 -0
  466. package/build/tools/networkTools.js.map +1 -0
  467. package/build/tools/reduxTools.d.ts +3 -0
  468. package/build/tools/reduxTools.d.ts.map +1 -0
  469. package/build/tools/reduxTools.js +83 -0
  470. package/build/tools/reduxTools.js.map +1 -0
  471. package/build/tools/screenshotTools.d.ts +3 -0
  472. package/build/tools/screenshotTools.d.ts.map +1 -0
  473. package/build/tools/screenshotTools.js +703 -0
  474. package/build/tools/screenshotTools.js.map +1 -0
  475. package/package.json +63 -2
@@ -0,0 +1,696 @@
1
+ import WebSocket from "ws";
2
+ import { escapeNonAsciiInStringLiterals } from "./escapeNonAscii.js";
3
+ import { pendingExecutions, getNextMessageId, connectedApps } from "./state.js";
4
+ import { getFirstConnectedApp, getConnectedAppByDevice, connectToDevice } from "./connection.js";
5
+ import { fetchDevices, selectMainDevice, scanMetroPorts } from "./metro.js";
6
+ import { cancelReconnectionTimer } from "./connectionState.js";
7
+ import { trackAutoReconnect } from "./telemetry.js";
8
+ // Hermes runtime compatibility: polyfill for 'global' which doesn't exist in Hermes
9
+ // In Hermes, globalThis is the standard way to access global scope
10
+ const GLOBAL_POLYFILL = `var global = typeof global !== 'undefined' ? global : globalThis;`;
11
+ /**
12
+ * Check if a string contains emoji or other problematic Unicode characters
13
+ * Hermes has issues with certain UTF-16 surrogate pairs (like emoji)
14
+ * @deprecated retained for backward compatibility — escapeNonAsciiInStringLiterals handles this now.
15
+ */
16
+ export function containsProblematicUnicode(str) {
17
+ // Detect UTF-16 surrogate pairs (emoji and other characters outside BMP)
18
+ // These cause "Invalid UTF-8 code point" errors in Hermes
19
+ // eslint-disable-next-line no-control-regex
20
+ return /[\uD800-\uDFFF]/.test(str);
21
+ }
22
+ /**
23
+ * Strip leading comments from an expression
24
+ * Users often start with // comments which break the (return expr) wrapping
25
+ */
26
+ export function stripLeadingComments(expression) {
27
+ let result = expression;
28
+ // Strip leading whitespace first
29
+ result = result.trimStart();
30
+ // Repeatedly strip leading single-line comments (// ...)
31
+ while (result.startsWith("//")) {
32
+ const newlineIndex = result.indexOf("\n");
33
+ if (newlineIndex === -1) {
34
+ // Entire expression is a comment
35
+ return "";
36
+ }
37
+ result = result.slice(newlineIndex + 1).trimStart();
38
+ }
39
+ // Strip leading multi-line comments (/* ... */)
40
+ while (result.startsWith("/*")) {
41
+ const endIndex = result.indexOf("*/");
42
+ if (endIndex === -1) {
43
+ // Unclosed comment
44
+ return result;
45
+ }
46
+ result = result.slice(endIndex + 2).trimStart();
47
+ }
48
+ return result;
49
+ }
50
+ /**
51
+ * Validate and preprocess an expression before execution
52
+ * Returns cleaned expression or error with helpful message
53
+ */
54
+ export function validateAndPreprocessExpression(expression) {
55
+ // Strip leading comments that would break the expression wrapper
56
+ const cleaned = stripLeadingComments(expression);
57
+ if (!cleaned.trim()) {
58
+ return {
59
+ valid: false,
60
+ expression,
61
+ error: "Expression is empty or contains only comments."
62
+ };
63
+ }
64
+ // Auto-escape non-ASCII inside string literals so the wire stays ASCII
65
+ // and Hermes can compile the expression.
66
+ const escapeResult = escapeNonAsciiInStringLiterals(cleaned);
67
+ if (!escapeResult.ok) {
68
+ return {
69
+ valid: false,
70
+ expression: cleaned,
71
+ error: "Unable to auto-escape non-ASCII characters in expression: " +
72
+ escapeResult.reason +
73
+ ". Replace non-ASCII characters with \\uXXXX escape sequences and retry, or check for unbalanced quotes."
74
+ };
75
+ }
76
+ const escaped = escapeResult.expression;
77
+ // Check for top-level async/await that Hermes doesn't support in Runtime.evaluate
78
+ const trimmed = escaped.trim();
79
+ if (looksLikeTopLevelAwait(trimmed)) {
80
+ return {
81
+ valid: false,
82
+ expression: escaped,
83
+ error: "top-level await is not supported in Hermes. " +
84
+ "Wrap in `Promise.resolve().then(v => ...)` instead, or assign the resolved value to a global: " +
85
+ "`global.__result = null; myAsyncFn().then(r => global.__result = r)`."
86
+ };
87
+ }
88
+ // Check for require() calls that don't work in Hermes Runtime.evaluate
89
+ if (/\brequire\s*\(/.test(trimmed)) {
90
+ return {
91
+ valid: false,
92
+ expression: escaped,
93
+ error: "require() is not available in Hermes Runtime.evaluate. " +
94
+ "Modules cannot be imported at runtime. Only pre-existing global variables are accessible. " +
95
+ "Use list_debug_globals to discover available globals, or add `globalThis.__MY_VAR__ = myModule;` in your app code."
96
+ };
97
+ }
98
+ // Check for multi-statement expressions. Runtime.evaluate compiles input as
99
+ // a single expression — `console.log('x'); 1+1` raises `')' expected at end
100
+ // of parenthesized expression`. Internal callers wrap in (function(){...})()
101
+ // so any `;` they use is at brace depth 1 and won't be flagged.
102
+ if (hasTopLevelStatementSeparator(trimmed)) {
103
+ return {
104
+ valid: false,
105
+ expression: escaped,
106
+ error: "Multi-statement expressions are not supported by Hermes Runtime.evaluate " +
107
+ "(compiles input as a single expression). " +
108
+ "Wrap the body in an IIFE: `(function(){ stmt1; stmt2; return result; })()`."
109
+ };
110
+ }
111
+ return {
112
+ valid: true,
113
+ expression: escaped
114
+ };
115
+ }
116
+ function isIdentChar(c) {
117
+ return c !== undefined && /[A-Za-z0-9_$]/.test(c);
118
+ }
119
+ // Detect top-level `await`, `async function`, `async (...) => ...`, or
120
+ // `(async ...)` IIFE forms in `src`. Walks char-by-char tracking string,
121
+ // template, comment, and bracket depth so we don't false-positive on
122
+ // substrings inside strings, identifiers like `awaiting`, etc.
123
+ function looksLikeTopLevelAwait(src) {
124
+ // Cheap prefix checks for async-function / async-arrow / async-IIFE forms.
125
+ // Whitespace-tolerant on `async <keyword>` / `async (`.
126
+ const asyncPrefix = /^async\s*(?:function\b|\()/;
127
+ if (asyncPrefix.test(src))
128
+ return true;
129
+ // `(async () => ...)()` or `(async(...)...)` — match `(async` followed by
130
+ // a non-identifier char (so `(asyncFoo` doesn't trigger).
131
+ const parenAsync = /^\(\s*async(?:\s|\()/;
132
+ if (parenAsync.test(src))
133
+ return true;
134
+ // Depth-tracked scan for a standalone `await` token at depth 0.
135
+ let i = 0;
136
+ let parens = 0;
137
+ let braces = 0;
138
+ let brackets = 0;
139
+ while (i < src.length) {
140
+ const ch = src[i];
141
+ const next = src[i + 1];
142
+ if (ch === "/" && next === "/") {
143
+ const nl = src.indexOf("\n", i + 2);
144
+ if (nl === -1)
145
+ return false;
146
+ i = nl + 1;
147
+ continue;
148
+ }
149
+ if (ch === "/" && next === "*") {
150
+ const end = src.indexOf("*/", i + 2);
151
+ if (end === -1)
152
+ return false;
153
+ i = end + 2;
154
+ continue;
155
+ }
156
+ if (ch === '"' || ch === "'" || ch === "`") {
157
+ const quote = ch;
158
+ i++;
159
+ while (i < src.length) {
160
+ if (src[i] === "\\") {
161
+ i += 2;
162
+ continue;
163
+ }
164
+ if (src[i] === quote) {
165
+ i++;
166
+ break;
167
+ }
168
+ i++;
169
+ }
170
+ continue;
171
+ }
172
+ if (ch === "(") {
173
+ parens++;
174
+ i++;
175
+ continue;
176
+ }
177
+ if (ch === ")") {
178
+ parens--;
179
+ i++;
180
+ continue;
181
+ }
182
+ if (ch === "{") {
183
+ braces++;
184
+ i++;
185
+ continue;
186
+ }
187
+ if (ch === "}") {
188
+ braces--;
189
+ i++;
190
+ continue;
191
+ }
192
+ if (ch === "[") {
193
+ brackets++;
194
+ i++;
195
+ continue;
196
+ }
197
+ if (ch === "]") {
198
+ brackets--;
199
+ i++;
200
+ continue;
201
+ }
202
+ if (parens === 0 && braces === 0 && brackets === 0 &&
203
+ ch === "a" &&
204
+ src.slice(i, i + 5) === "await" &&
205
+ !isIdentChar(src[i - 1]) &&
206
+ !isIdentChar(src[i + 5])) {
207
+ return true;
208
+ }
209
+ i++;
210
+ }
211
+ return false;
212
+ }
213
+ // Walk `src` tracking string/template/comment and bracket depth. Returns true
214
+ // iff a `;` appears at depth 0 with non-whitespace following it (i.e. it
215
+ // separates two top-level statements rather than terminating a single one).
216
+ function hasTopLevelStatementSeparator(src) {
217
+ let i = 0;
218
+ let parens = 0;
219
+ let braces = 0;
220
+ let brackets = 0;
221
+ while (i < src.length) {
222
+ const ch = src[i];
223
+ const next = src[i + 1];
224
+ if (ch === "/" && next === "/") {
225
+ const nl = src.indexOf("\n", i + 2);
226
+ if (nl === -1)
227
+ return false;
228
+ i = nl + 1;
229
+ continue;
230
+ }
231
+ if (ch === "/" && next === "*") {
232
+ const end = src.indexOf("*/", i + 2);
233
+ if (end === -1)
234
+ return false;
235
+ i = end + 2;
236
+ continue;
237
+ }
238
+ if (ch === '"' || ch === "'" || ch === "`") {
239
+ const quote = ch;
240
+ i++;
241
+ while (i < src.length) {
242
+ if (src[i] === "\\") {
243
+ i += 2;
244
+ continue;
245
+ }
246
+ if (src[i] === quote) {
247
+ i++;
248
+ break;
249
+ }
250
+ i++;
251
+ }
252
+ continue;
253
+ }
254
+ if (ch === "(")
255
+ parens++;
256
+ else if (ch === ")")
257
+ parens--;
258
+ else if (ch === "{")
259
+ braces++;
260
+ else if (ch === "}")
261
+ braces--;
262
+ else if (ch === "[")
263
+ brackets++;
264
+ else if (ch === "]")
265
+ brackets--;
266
+ else if (ch === ";" && parens === 0 && braces === 0 && brackets === 0) {
267
+ const rest = src.slice(i + 1).trim();
268
+ if (rest.length > 0)
269
+ return true;
270
+ }
271
+ i++;
272
+ }
273
+ return false;
274
+ }
275
+ // ============================================================================
276
+ // Per-call timeoutMs: clamp + defaults
277
+ // ============================================================================
278
+ export const TIMEOUT_HARD_CAP_MS = 120_000;
279
+ const TIMEOUT_DEFAULT_MS = 5_000;
280
+ // Flips true after the first successful executeInApp OR successful CDP
281
+ // connection in this process. Used by the auto-reconnect wrapper to distinguish
282
+ // "Metro/app never came up" (don't bother scanning) from a mid-session
283
+ // transport drop worth retrying.
284
+ let hasEverConnected = false;
285
+ export function markConnectionEstablished() {
286
+ hasEverConnected = true;
287
+ }
288
+ export function clampTimeoutMs(input) {
289
+ if (!Number.isFinite(input) || input <= 0) {
290
+ return { value: TIMEOUT_DEFAULT_MS, clampedFrom: input };
291
+ }
292
+ if (input > TIMEOUT_HARD_CAP_MS) {
293
+ return { value: TIMEOUT_HARD_CAP_MS, clampedFrom: input };
294
+ }
295
+ return { value: input };
296
+ }
297
+ /**
298
+ * Classify an error message into transport-vs-logical for auto-reconnect routing.
299
+ *
300
+ * The `source` argument distinguishes the CDP-emitted "Expression took too long"
301
+ * (a stale-target signal we DO want to reconnect on) from the server-side
302
+ * `Promise.race` timer text (a logical "this took too long" we do NOT).
303
+ */
304
+ export function classifyTransportError(message, source) {
305
+ if (!message)
306
+ return { kind: "logical" };
307
+ if (source === "server-timer")
308
+ return { kind: "logical" };
309
+ if (/No apps connected/i.test(message))
310
+ return { kind: "transport", pattern: "no_apps" };
311
+ if (/ECONNRESET/i.test(message) ||
312
+ /WebSocket connection is not open/i.test(message) ||
313
+ /socket hang up/i.test(message) ||
314
+ /WebSocket frame/i.test(message)) {
315
+ return { kind: "transport", pattern: "ws_closed" };
316
+ }
317
+ if (/target closed/i.test(message) || /Inspector detached/i.test(message)) {
318
+ return { kind: "transport", pattern: "target_closed" };
319
+ }
320
+ if (source === "cdp" && /Expression took too long to evaluate/i.test(message)) {
321
+ return { kind: "transport", pattern: "cdp_eval_too_long" };
322
+ }
323
+ return { kind: "logical" };
324
+ }
325
+ // Error patterns that indicate a stale/destroyed context
326
+ const CONTEXT_ERROR_PATTERNS = [
327
+ "cannot find context",
328
+ "execution context was destroyed",
329
+ "target closed",
330
+ "inspected target navigated",
331
+ "session closed",
332
+ "context with specified id",
333
+ "no execution context",
334
+ "runningdetached"
335
+ ];
336
+ /**
337
+ * Check if an error indicates a stale page context
338
+ */
339
+ function isContextError(error) {
340
+ if (!error)
341
+ return false;
342
+ const lowerError = error.toLowerCase();
343
+ return CONTEXT_ERROR_PATTERNS.some((pattern) => lowerError.includes(pattern));
344
+ }
345
+ /**
346
+ * Simple delay helper
347
+ */
348
+ export function delay(ms) {
349
+ return new Promise((resolve) => setTimeout(resolve, ms));
350
+ }
351
+ /**
352
+ * Attempt quick reconnection to Metro
353
+ */
354
+ async function attemptQuickReconnect(preferredPort) {
355
+ try {
356
+ const ports = await scanMetroPorts();
357
+ const targetPort = preferredPort && ports.includes(preferredPort) ? preferredPort : ports[0];
358
+ if (!targetPort)
359
+ return false;
360
+ const devices = await fetchDevices(targetPort);
361
+ const mainDevice = selectMainDevice(devices);
362
+ if (!mainDevice)
363
+ return false;
364
+ await connectToDevice(mainDevice, targetPort);
365
+ return true;
366
+ }
367
+ catch {
368
+ return false;
369
+ }
370
+ }
371
+ /**
372
+ * Execute expression on a connected app (core implementation without retry)
373
+ */
374
+ async function executeExpressionCore(expression, awaitPromise, timeoutMs = 10000, targetApp) {
375
+ const app = targetApp ?? getFirstConnectedApp();
376
+ if (!app) {
377
+ return { success: false, error: "No apps connected. Run 'scan_metro' first." };
378
+ }
379
+ if (app.ws.readyState !== WebSocket.OPEN) {
380
+ return { success: false, error: "WebSocket connection is not open." };
381
+ }
382
+ // Validate and preprocess the expression
383
+ const validation = validateAndPreprocessExpression(expression);
384
+ if (!validation.valid) {
385
+ return { success: false, error: validation.error };
386
+ }
387
+ const cleanedExpression = validation.expression;
388
+ // Hermes CDP does not support awaitPromise — it serializes the Promise's
389
+ // internal fields (_A, _x, _y, _z) instead of waiting for resolution.
390
+ // When the caller wants awaitPromise, we handle it ourselves: wrap the
391
+ // expression to store the resolved value in a temp global, then poll.
392
+ if (awaitPromise) {
393
+ return executeWithManualAwait(app, cleanedExpression, timeoutMs);
394
+ }
395
+ return executeCDP(app, cleanedExpression, false, timeoutMs);
396
+ }
397
+ /**
398
+ * Execute a CDP Runtime.evaluate call (no promise awaiting).
399
+ */
400
+ function executeCDP(app, cleanedExpression, awaitPromise, timeoutMs) {
401
+ const TIMEOUT_MS = timeoutMs;
402
+ const currentMessageId = getNextMessageId();
403
+ const wrappedExpression = `${GLOBAL_POLYFILL} ${cleanedExpression}`;
404
+ return new Promise((resolve) => {
405
+ const timeoutId = setTimeout(() => {
406
+ pendingExecutions.delete(currentMessageId);
407
+ const wsState = app.ws.readyState === WebSocket.OPEN ? "OPEN"
408
+ : app.ws.readyState === WebSocket.CLOSED ? "CLOSED"
409
+ : app.ws.readyState === WebSocket.CLOSING ? "CLOSING"
410
+ : "CONNECTING";
411
+ const deviceName = app.deviceInfo.deviceName || app.deviceInfo.title || "unknown";
412
+ const pageId = app.deviceInfo.id || "unknown";
413
+ const truncatedExpr = cleanedExpression.length > 100
414
+ ? cleanedExpression.substring(0, 100) + "..."
415
+ : cleanedExpression;
416
+ const errorMessage = [
417
+ "Timeout: Expression took too long to evaluate.",
418
+ "",
419
+ `Connection state: ws=${wsState}, device="${deviceName}", platform=${app.platform}, pageId=${pageId}`,
420
+ `Expression (truncated): ${truncatedExpr}`,
421
+ "",
422
+ "This usually means the JavaScript execution context became unresponsive or the CDP page is stale.",
423
+ "",
424
+ "Recovery steps (try in order):",
425
+ "1. Call scan_metro to re-establish a fresh CDP connection",
426
+ "2. If scan_metro doesn't help, force-restart the app:",
427
+ " - iOS: ios_terminate_app then ios_launch_app",
428
+ " - Android: android_launch_app (restarts automatically)",
429
+ "3. After restarting, call scan_metro again to reconnect",
430
+ ].join("\n");
431
+ resolve({ success: false, error: errorMessage });
432
+ }, TIMEOUT_MS);
433
+ pendingExecutions.set(currentMessageId, { resolve, timeoutId });
434
+ try {
435
+ app.ws.send(JSON.stringify({
436
+ id: currentMessageId,
437
+ method: "Runtime.evaluate",
438
+ params: {
439
+ expression: wrappedExpression,
440
+ returnByValue: true,
441
+ awaitPromise,
442
+ userGesture: true,
443
+ generatePreview: true,
444
+ // Hermes-side timeout layer. Older Hermes builds ignore this — the
445
+ // server-side setTimeout above is the primary defense.
446
+ timeout: timeoutMs
447
+ }
448
+ }));
449
+ }
450
+ catch (error) {
451
+ clearTimeout(timeoutId);
452
+ pendingExecutions.delete(currentMessageId);
453
+ resolve({
454
+ success: false,
455
+ error: `Failed to send: ${error instanceof Error ? error.message : String(error)}`
456
+ });
457
+ }
458
+ });
459
+ }
460
+ /**
461
+ * Hermes workaround for awaitPromise: execute the expression, and if it
462
+ * returns a Promise, store the resolved/rejected value in a temp global
463
+ * and read it back with a small number of spaced-out retries.
464
+ */
465
+ async function executeWithManualAwait(app, cleanedExpression, timeoutMs) {
466
+ const slotId = `__rn_dbg_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
467
+ // Wrap: run the expression, if result is thenable store resolved value in
468
+ // a temp global slot; otherwise store the sync value immediately.
469
+ const wrapperExpr = `(function(){
470
+ var __v=(${cleanedExpression});
471
+ if(__v&&typeof __v==='object'&&typeof __v.then==='function'){
472
+ globalThis['${slotId}']={s:'pending'};
473
+ __v.then(function(r){globalThis['${slotId}']={s:'ok',v:r}},function(e){globalThis['${slotId}']={s:'err',v:String(e)}});
474
+ return '__awaiting__'}
475
+ else{return __v}})()`;
476
+ const initial = await executeCDP(app, wrapperExpr, false, timeoutMs);
477
+ // If the expression didn't return a Promise, return the result directly
478
+ if (!initial.success || initial.result !== "__awaiting__") {
479
+ return initial;
480
+ }
481
+ // Read the settled value with a few spaced-out retries (not aggressive polling).
482
+ // Most Promises resolve within a microtask or a single event loop tick.
483
+ const RETRY_DELAYS_MS = [100, 300, 600, 1000, 2000, 3000];
484
+ const readExpr = `(function(){var s=globalThis['${slotId}'];if(!s||s.s==='pending')return '__pending__';delete globalThis['${slotId}'];return{status:s.s,value:s.v}})()`;
485
+ for (const delayMs of RETRY_DELAYS_MS) {
486
+ await new Promise((r) => setTimeout(r, delayMs));
487
+ const poll = await executeCDP(app, readExpr, false, 5000);
488
+ if (!poll.success)
489
+ return poll;
490
+ if (poll.result === "__pending__")
491
+ continue;
492
+ // The poll result comes through formatRemoteObject — objects are
493
+ // JSON.stringified, so we need to parse it back.
494
+ try {
495
+ const parsed = typeof poll.result === "string" ? JSON.parse(poll.result) : poll.result;
496
+ if (parsed?.status === "err") {
497
+ return { success: false, error: parsed.value || "Promise rejected" };
498
+ }
499
+ const value = parsed?.value;
500
+ return {
501
+ success: true,
502
+ result: value === undefined || value === null
503
+ ? String(value)
504
+ : typeof value === "object"
505
+ ? JSON.stringify(value, null, 2)
506
+ : String(value)
507
+ };
508
+ }
509
+ catch {
510
+ return poll;
511
+ }
512
+ }
513
+ // Cleanup on timeout
514
+ await executeCDP(app, `delete globalThis['${slotId}']`, false, 2000).catch(() => { });
515
+ return { success: false, error: "Timeout: Promise did not resolve within the time limit." };
516
+ }
517
+ // Execute JavaScript in the connected React Native app with retry logic
518
+ async function executeInAppInner(expression, awaitPromise = true, options = {}, device) {
519
+ const { maxRetries = 2, retryDelayMs = 1000, autoReconnect = true, timeoutMs = 10000, skipBootstrap = false } = options;
520
+ let lastError;
521
+ let preferredPort;
522
+ // Get preferred port from current connection if available
523
+ const currentApp = getConnectedAppByDevice(device);
524
+ if (currentApp) {
525
+ preferredPort = currentApp.port;
526
+ }
527
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
528
+ const app = getConnectedAppByDevice(device);
529
+ // No connection - try to reconnect if enabled
530
+ if (!app) {
531
+ if (autoReconnect && attempt < maxRetries) {
532
+ console.error(`[execbro] No connection, attempting reconnect (attempt ${attempt + 1}/${maxRetries})...`);
533
+ const reconnected = await attemptQuickReconnect(preferredPort);
534
+ if (reconnected) {
535
+ await delay(retryDelayMs);
536
+ continue;
537
+ }
538
+ }
539
+ return { success: false, error: "No apps connected. Run 'scan_metro' first." };
540
+ }
541
+ // WebSocket not open - try to reconnect
542
+ if (app.ws.readyState !== WebSocket.OPEN) {
543
+ if (autoReconnect && attempt < maxRetries) {
544
+ console.error(`[execbro] WebSocket not open, attempting reconnect (attempt ${attempt + 1}/${maxRetries})...`);
545
+ // Close stale connection
546
+ const appKey = `${app.port}-${app.deviceInfo.id}`;
547
+ cancelReconnectionTimer(appKey);
548
+ try {
549
+ app.ws.close();
550
+ }
551
+ catch {
552
+ /* ignore */
553
+ }
554
+ connectedApps.delete(appKey);
555
+ const reconnected = await attemptQuickReconnect(app.port);
556
+ if (reconnected) {
557
+ await delay(retryDelayMs);
558
+ continue;
559
+ }
560
+ }
561
+ return { success: false, error: "WebSocket connection is not open." };
562
+ }
563
+ // Best-effort one-shot bootstrap of globalThis.__rn__ for this app
564
+ // session. Hermes does not expose closure-captured RN modules, so this
565
+ // fiber-walk usually sets __rn__ = null — that's fine; list_debug_globals
566
+ // reports the failure clearly. Wrapped in try/catch so a bootstrap
567
+ // failure never breaks the user's expression. skipBootstrap is set by
568
+ // the bootstrap itself (via ensureRnGlobalsBootstrap) to avoid recursion.
569
+ if (!skipBootstrap) {
570
+ try {
571
+ const { ensureRnGlobalsBootstrap } = await import("./rnGlobalsBootstrap.js");
572
+ await ensureRnGlobalsBootstrap(device);
573
+ }
574
+ catch (e) {
575
+ console.error("[execbro] __rn__ bootstrap dispatch failed:", e);
576
+ }
577
+ }
578
+ // Execute the expression
579
+ const result = await executeExpressionCore(expression, awaitPromise, timeoutMs, app);
580
+ // Success - return result
581
+ if (result.success) {
582
+ return result;
583
+ }
584
+ lastError = result.error;
585
+ // Check if this is a context error that might be recoverable
586
+ if (isContextError(result.error)) {
587
+ if (autoReconnect && attempt < maxRetries) {
588
+ console.error(`[execbro] Context error detected, attempting reconnect (attempt ${attempt + 1}/${maxRetries})...`);
589
+ // Close and reconnect
590
+ const appKey = `${app.port}-${app.deviceInfo.id}`;
591
+ cancelReconnectionTimer(appKey);
592
+ try {
593
+ app.ws.close();
594
+ }
595
+ catch {
596
+ /* ignore */
597
+ }
598
+ connectedApps.delete(appKey);
599
+ const reconnected = await attemptQuickReconnect(app.port);
600
+ if (reconnected) {
601
+ await delay(retryDelayMs);
602
+ continue;
603
+ }
604
+ }
605
+ }
606
+ // Non-context error or no more retries - return error
607
+ return result;
608
+ }
609
+ return {
610
+ success: false,
611
+ error: lastError ?? [
612
+ "Execution failed after all retries. Connection may be stale.",
613
+ "",
614
+ "Recovery steps (try in order):",
615
+ "1. Call scan_metro to re-establish a fresh CDP connection",
616
+ "2. If scan_metro doesn't help, force-restart the app:",
617
+ " - iOS: ios_terminate_app then ios_launch_app",
618
+ " - Android: android_launch_app (restarts automatically)",
619
+ "3. After restarting, call scan_metro again to reconnect",
620
+ ].join("\n")
621
+ };
622
+ }
623
+ /**
624
+ * One-shot scan-and-retry wrapper on top of executeInAppInner.
625
+ *
626
+ * On first-failure, classifies the error as transport-vs-logical:
627
+ * - transport → call attemptQuickReconnect once, retry with autoReconnect:false
628
+ * to avoid recursion. Successful retries carry _meta.reconnected; surviving
629
+ * failures surface 'reconnected_but_still_failed'.
630
+ * - logical → propagate the original error unchanged.
631
+ *
632
+ * The server-side `timeoutMs` timer always classifies as logical (a too-long
633
+ * expression is not a transport drop), so timeoutMs hits never trigger
634
+ * reconnect.
635
+ */
636
+ export async function executeInApp(expression, awaitPromise = true, options = {}, device) {
637
+ const toolName = options.originatingToolName ?? "unknown";
638
+ // Clamp timeoutMs at the boundary. Mistyped values clamp with a warning surfaced in
639
+ // _meta rather than reject. The default (when not supplied) keeps the historical 10000 ms.
640
+ const requestedTimeout = options.timeoutMs ?? 10_000;
641
+ const { value: clampedTimeout, clampedFrom } = clampTimeoutMs(requestedTimeout);
642
+ const effectiveOptions = { ...options, timeoutMs: clampedTimeout };
643
+ const withClampMeta = (r) => {
644
+ if (clampedFrom === undefined)
645
+ return r;
646
+ return { ...r, _meta: { ...(r._meta ?? {}), timeoutClampedFrom: clampedFrom } };
647
+ };
648
+ const first = await executeInAppInner(expression, awaitPromise, effectiveOptions, device);
649
+ if (first.success) {
650
+ hasEverConnected = true;
651
+ trackAutoReconnect("not_needed", toolName);
652
+ return withClampMeta(first);
653
+ }
654
+ const source = first.error?.startsWith("Timeout: Expression took too long")
655
+ ? "server-timer"
656
+ : "cdp";
657
+ const classification = classifyTransportError(first.error ?? "", source);
658
+ if (classification.kind !== "transport") {
659
+ trackAutoReconnect("not_needed", toolName);
660
+ return withClampMeta(first);
661
+ }
662
+ // 'no_apps' without any prior successful exec means Metro/app simply isn't
663
+ // running — scanning will only re-confirm that. Return the original error
664
+ // so the user sees the actionable message ("Run 'scan_metro' first") instead
665
+ // of a misleading 'reconnect_attempted' prefix.
666
+ if (classification.pattern === "no_apps" && !hasEverConnected) {
667
+ trackAutoReconnect("not_needed", toolName);
668
+ return withClampMeta(first);
669
+ }
670
+ const currentApp = getConnectedAppByDevice(device);
671
+ const preferredPort = currentApp?.port;
672
+ const reconnected = await attemptQuickReconnect(preferredPort);
673
+ if (!reconnected) {
674
+ trackAutoReconnect("scan_failed", toolName, classification.pattern);
675
+ return withClampMeta({
676
+ success: false,
677
+ error: `reconnect_attempted: ${first.error ?? "unknown"}`,
678
+ _meta: { reconnected: false, transportError: first.error ?? "unknown" },
679
+ });
680
+ }
681
+ const retry = await executeInAppInner(expression, awaitPromise, { ...effectiveOptions, autoReconnect: false }, device);
682
+ if (retry.success) {
683
+ trackAutoReconnect("success", toolName, classification.pattern);
684
+ return withClampMeta({
685
+ ...retry,
686
+ _meta: { reconnected: true, transportError: first.error ?? "unknown" },
687
+ });
688
+ }
689
+ trackAutoReconnect("retry_failed", toolName, classification.pattern);
690
+ return withClampMeta({
691
+ success: false,
692
+ error: `reconnected_but_still_failed: ${first.error ?? "unknown"} | ${retry.error ?? "unknown"}`,
693
+ _meta: { reconnected: true, transportError: first.error ?? "unknown" },
694
+ });
695
+ }
696
+ //# sourceMappingURL=jsExecute.js.map