@roxybrowser/playwright 2.0.2-beta.0

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 (424) hide show
  1. package/README.md +115 -0
  2. package/dist/apiRequestContext.d.ts +52 -0
  3. package/dist/apiRequestContext.d.ts.map +1 -0
  4. package/dist/apiRequestContext.js +632 -0
  5. package/dist/apiRequestContext.js.map +1 -0
  6. package/dist/ariaSnapshot.d.ts +38 -0
  7. package/dist/ariaSnapshot.d.ts.map +1 -0
  8. package/dist/ariaSnapshot.js +1137 -0
  9. package/dist/ariaSnapshot.js.map +1 -0
  10. package/dist/assertions.d.ts +2 -0
  11. package/dist/assertions.d.ts.map +1 -0
  12. package/dist/assertions.js +6 -0
  13. package/dist/assertions.js.map +1 -0
  14. package/dist/bin/roxybrowser-mcp.d.ts +3 -0
  15. package/dist/bin/roxybrowser-mcp.d.ts.map +1 -0
  16. package/dist/bin/roxybrowser-mcp.js +7 -0
  17. package/dist/bin/roxybrowser-mcp.js.map +1 -0
  18. package/dist/browser.d.ts +15 -0
  19. package/dist/browser.d.ts.map +1 -0
  20. package/dist/browser.js +67 -0
  21. package/dist/browser.js.map +1 -0
  22. package/dist/browserContext.d.ts +156 -0
  23. package/dist/browserContext.d.ts.map +1 -0
  24. package/dist/browserContext.js +1129 -0
  25. package/dist/browserContext.js.map +1 -0
  26. package/dist/browserContextClock.d.ts +54 -0
  27. package/dist/browserContextClock.d.ts.map +1 -0
  28. package/dist/browserContextClock.js +147 -0
  29. package/dist/browserContextClock.js.map +1 -0
  30. package/dist/browserType.d.ts +16 -0
  31. package/dist/browserType.d.ts.map +1 -0
  32. package/dist/browserType.js +68 -0
  33. package/dist/browserType.js.map +1 -0
  34. package/dist/bundle.d.ts +20 -0
  35. package/dist/bundle.d.ts.map +1 -0
  36. package/dist/bundle.js +20 -0
  37. package/dist/bundle.js.map +1 -0
  38. package/dist/clock.d.ts +43 -0
  39. package/dist/clock.d.ts.map +1 -0
  40. package/dist/clock.js +70 -0
  41. package/dist/clock.js.map +1 -0
  42. package/dist/elementHandle.d.ts +100 -0
  43. package/dist/elementHandle.d.ts.map +1 -0
  44. package/dist/elementHandle.js +423 -0
  45. package/dist/elementHandle.js.map +1 -0
  46. package/dist/errors.d.ts +10 -0
  47. package/dist/errors.d.ts.map +1 -0
  48. package/dist/errors.js +19 -0
  49. package/dist/errors.js.map +1 -0
  50. package/dist/evaluation.d.ts +4 -0
  51. package/dist/evaluation.d.ts.map +1 -0
  52. package/dist/evaluation.js +9 -0
  53. package/dist/evaluation.js.map +1 -0
  54. package/dist/frame.d.ts +139 -0
  55. package/dist/frame.d.ts.map +1 -0
  56. package/dist/frame.js +451 -0
  57. package/dist/frame.js.map +1 -0
  58. package/dist/httpHeaders.d.ts +6 -0
  59. package/dist/httpHeaders.d.ts.map +1 -0
  60. package/dist/httpHeaders.js +23 -0
  61. package/dist/httpHeaders.js.map +1 -0
  62. package/dist/human/controller.d.ts +15 -0
  63. package/dist/human/controller.d.ts.map +1 -0
  64. package/dist/human/controller.js +67 -0
  65. package/dist/human/controller.js.map +1 -0
  66. package/dist/human/profile.d.ts +5 -0
  67. package/dist/human/profile.d.ts.map +1 -0
  68. package/dist/human/profile.js +50 -0
  69. package/dist/human/profile.js.map +1 -0
  70. package/dist/human/types.d.ts +28 -0
  71. package/dist/human/types.d.ts.map +1 -0
  72. package/dist/human/types.js +2 -0
  73. package/dist/human/types.js.map +1 -0
  74. package/dist/index.d.ts +7 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +3 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/inputFiles.d.ts +18 -0
  79. package/dist/inputFiles.d.ts.map +1 -0
  80. package/dist/inputFiles.js +192 -0
  81. package/dist/inputFiles.js.map +1 -0
  82. package/dist/jsHandle.d.ts +32 -0
  83. package/dist/jsHandle.d.ts.map +1 -0
  84. package/dist/jsHandle.js +148 -0
  85. package/dist/jsHandle.js.map +1 -0
  86. package/dist/locator.d.ts +190 -0
  87. package/dist/locator.d.ts.map +1 -0
  88. package/dist/locator.js +883 -0
  89. package/dist/locator.js.map +1 -0
  90. package/dist/locatorSelectors.d.ts +11 -0
  91. package/dist/locatorSelectors.d.ts.map +1 -0
  92. package/dist/locatorSelectors.js +50 -0
  93. package/dist/locatorSelectors.js.map +1 -0
  94. package/dist/mcp/backend/common.d.ts +4 -0
  95. package/dist/mcp/backend/common.d.ts.map +1 -0
  96. package/dist/mcp/backend/common.js +40 -0
  97. package/dist/mcp/backend/common.js.map +1 -0
  98. package/dist/mcp/backend/connect.d.ts +10 -0
  99. package/dist/mcp/backend/connect.d.ts.map +1 -0
  100. package/dist/mcp/backend/connect.js +30 -0
  101. package/dist/mcp/backend/connect.js.map +1 -0
  102. package/dist/mcp/backend/console.d.ts +13 -0
  103. package/dist/mcp/backend/console.d.ts.map +1 -0
  104. package/dist/mcp/backend/console.js +36 -0
  105. package/dist/mcp/backend/console.js.map +1 -0
  106. package/dist/mcp/backend/context.d.ts +27 -0
  107. package/dist/mcp/backend/context.d.ts.map +1 -0
  108. package/dist/mcp/backend/context.js +33 -0
  109. package/dist/mcp/backend/context.js.map +1 -0
  110. package/dist/mcp/backend/dialogs.d.ts +7 -0
  111. package/dist/mcp/backend/dialogs.d.ts.map +1 -0
  112. package/dist/mcp/backend/dialogs.js +24 -0
  113. package/dist/mcp/backend/dialogs.js.map +1 -0
  114. package/dist/mcp/backend/evaluate.d.ts +9 -0
  115. package/dist/mcp/backend/evaluate.d.ts.map +1 -0
  116. package/dist/mcp/backend/evaluate.js +31 -0
  117. package/dist/mcp/backend/evaluate.js.map +1 -0
  118. package/dist/mcp/backend/files.d.ts +9 -0
  119. package/dist/mcp/backend/files.d.ts.map +1 -0
  120. package/dist/mcp/backend/files.js +39 -0
  121. package/dist/mcp/backend/files.js.map +1 -0
  122. package/dist/mcp/backend/keyboard.d.ts +22 -0
  123. package/dist/mcp/backend/keyboard.d.ts.map +1 -0
  124. package/dist/mcp/backend/keyboard.js +67 -0
  125. package/dist/mcp/backend/keyboard.js.map +1 -0
  126. package/dist/mcp/backend/navigate.d.ts +4 -0
  127. package/dist/mcp/backend/navigate.d.ts.map +1 -0
  128. package/dist/mcp/backend/navigate.js +82 -0
  129. package/dist/mcp/backend/navigate.js.map +1 -0
  130. package/dist/mcp/backend/network.d.ts +17 -0
  131. package/dist/mcp/backend/network.d.ts.map +1 -0
  132. package/dist/mcp/backend/network.js +144 -0
  133. package/dist/mcp/backend/network.js.map +1 -0
  134. package/dist/mcp/backend/response.d.ts +26 -0
  135. package/dist/mcp/backend/response.d.ts.map +1 -0
  136. package/dist/mcp/backend/response.js +109 -0
  137. package/dist/mcp/backend/response.js.map +1 -0
  138. package/dist/mcp/backend/runCode.d.ts +6 -0
  139. package/dist/mcp/backend/runCode.d.ts.map +1 -0
  140. package/dist/mcp/backend/runCode.js +20 -0
  141. package/dist/mcp/backend/runCode.js.map +1 -0
  142. package/dist/mcp/backend/screenshot.d.ts +13 -0
  143. package/dist/mcp/backend/screenshot.d.ts.map +1 -0
  144. package/dist/mcp/backend/screenshot.js +37 -0
  145. package/dist/mcp/backend/screenshot.js.map +1 -0
  146. package/dist/mcp/backend/snapshot.d.ts +70 -0
  147. package/dist/mcp/backend/snapshot.d.ts.map +1 -0
  148. package/dist/mcp/backend/snapshot.js +185 -0
  149. package/dist/mcp/backend/snapshot.js.map +1 -0
  150. package/dist/mcp/backend/tab.d.ts +72 -0
  151. package/dist/mcp/backend/tab.d.ts.map +1 -0
  152. package/dist/mcp/backend/tab.js +99 -0
  153. package/dist/mcp/backend/tab.js.map +1 -0
  154. package/dist/mcp/backend/tabs.d.ts +13 -0
  155. package/dist/mcp/backend/tabs.d.ts.map +1 -0
  156. package/dist/mcp/backend/tabs.js +44 -0
  157. package/dist/mcp/backend/tabs.js.map +1 -0
  158. package/dist/mcp/backend/tool.d.ts +52 -0
  159. package/dist/mcp/backend/tool.d.ts.map +1 -0
  160. package/dist/mcp/backend/tool.js +28 -0
  161. package/dist/mcp/backend/tool.js.map +1 -0
  162. package/dist/mcp/backend/tools.d.ts +4 -0
  163. package/dist/mcp/backend/tools.d.ts.map +1 -0
  164. package/dist/mcp/backend/tools.js +30 -0
  165. package/dist/mcp/backend/tools.js.map +1 -0
  166. package/dist/mcp/connectedBrowser.d.ts +3 -0
  167. package/dist/mcp/connectedBrowser.d.ts.map +1 -0
  168. package/dist/mcp/connectedBrowser.js +2153 -0
  169. package/dist/mcp/connectedBrowser.js.map +1 -0
  170. package/dist/mcp/errors.d.ts +6 -0
  171. package/dist/mcp/errors.d.ts.map +1 -0
  172. package/dist/mcp/errors.js +12 -0
  173. package/dist/mcp/errors.js.map +1 -0
  174. package/dist/mcp/format.d.ts +12 -0
  175. package/dist/mcp/format.d.ts.map +1 -0
  176. package/dist/mcp/format.js +48 -0
  177. package/dist/mcp/format.js.map +1 -0
  178. package/dist/mcp/index.d.ts +6 -0
  179. package/dist/mcp/index.d.ts.map +1 -0
  180. package/dist/mcp/index.js +5 -0
  181. package/dist/mcp/index.js.map +1 -0
  182. package/dist/mcp/output.d.ts +7 -0
  183. package/dist/mcp/output.d.ts.map +1 -0
  184. package/dist/mcp/output.js +39 -0
  185. package/dist/mcp/output.js.map +1 -0
  186. package/dist/mcp/runtime.d.ts +122 -0
  187. package/dist/mcp/runtime.d.ts.map +1 -0
  188. package/dist/mcp/runtime.js +524 -0
  189. package/dist/mcp/runtime.js.map +1 -0
  190. package/dist/mcp/schemas.d.ts +61 -0
  191. package/dist/mcp/schemas.d.ts.map +1 -0
  192. package/dist/mcp/schemas.js +41 -0
  193. package/dist/mcp/schemas.js.map +1 -0
  194. package/dist/mcp/server.d.ts +3 -0
  195. package/dist/mcp/server.d.ts.map +1 -0
  196. package/dist/mcp/server.js +117 -0
  197. package/dist/mcp/server.js.map +1 -0
  198. package/dist/mcp/snapshot.d.ts +3 -0
  199. package/dist/mcp/snapshot.d.ts.map +1 -0
  200. package/dist/mcp/snapshot.js +3 -0
  201. package/dist/mcp/snapshot.js.map +1 -0
  202. package/dist/mcp/tool.d.ts +19 -0
  203. package/dist/mcp/tool.d.ts.map +1 -0
  204. package/dist/mcp/tool.js +10 -0
  205. package/dist/mcp/tool.js.map +1 -0
  206. package/dist/mcp/tools/common.d.ts +6 -0
  207. package/dist/mcp/tools/common.d.ts.map +1 -0
  208. package/dist/mcp/tools/common.js +34 -0
  209. package/dist/mcp/tools/common.js.map +1 -0
  210. package/dist/mcp/tools/connect.d.ts +6 -0
  211. package/dist/mcp/tools/connect.d.ts.map +1 -0
  212. package/dist/mcp/tools/connect.js +28 -0
  213. package/dist/mcp/tools/connect.js.map +1 -0
  214. package/dist/mcp/tools/console.d.ts +6 -0
  215. package/dist/mcp/tools/console.d.ts.map +1 -0
  216. package/dist/mcp/tools/console.js +36 -0
  217. package/dist/mcp/tools/console.js.map +1 -0
  218. package/dist/mcp/tools/dialog.d.ts +6 -0
  219. package/dist/mcp/tools/dialog.d.ts.map +1 -0
  220. package/dist/mcp/tools/dialog.js +22 -0
  221. package/dist/mcp/tools/dialog.js.map +1 -0
  222. package/dist/mcp/tools/evaluate.d.ts +6 -0
  223. package/dist/mcp/tools/evaluate.d.ts.map +1 -0
  224. package/dist/mcp/tools/evaluate.js +31 -0
  225. package/dist/mcp/tools/evaluate.js.map +1 -0
  226. package/dist/mcp/tools/form.d.ts +6 -0
  227. package/dist/mcp/tools/form.d.ts.map +1 -0
  228. package/dist/mcp/tools/form.js +129 -0
  229. package/dist/mcp/tools/form.js.map +1 -0
  230. package/dist/mcp/tools/index.d.ts +3 -0
  231. package/dist/mcp/tools/index.d.ts.map +1 -0
  232. package/dist/mcp/tools/index.js +7 -0
  233. package/dist/mcp/tools/index.js.map +1 -0
  234. package/dist/mcp/tools/keyboard.d.ts +3 -0
  235. package/dist/mcp/tools/keyboard.d.ts.map +1 -0
  236. package/dist/mcp/tools/keyboard.js +44 -0
  237. package/dist/mcp/tools/keyboard.js.map +1 -0
  238. package/dist/mcp/tools/mouse.d.ts +3 -0
  239. package/dist/mcp/tools/mouse.d.ts.map +1 -0
  240. package/dist/mcp/tools/mouse.js +89 -0
  241. package/dist/mcp/tools/mouse.js.map +1 -0
  242. package/dist/mcp/tools/navigate.d.ts +6 -0
  243. package/dist/mcp/tools/navigate.d.ts.map +1 -0
  244. package/dist/mcp/tools/navigate.js +74 -0
  245. package/dist/mcp/tools/navigate.js.map +1 -0
  246. package/dist/mcp/tools/network.d.ts +6 -0
  247. package/dist/mcp/tools/network.d.ts.map +1 -0
  248. package/dist/mcp/tools/network.js +142 -0
  249. package/dist/mcp/tools/network.js.map +1 -0
  250. package/dist/mcp/tools/runCode.d.ts +6 -0
  251. package/dist/mcp/tools/runCode.d.ts.map +1 -0
  252. package/dist/mcp/tools/runCode.js +24 -0
  253. package/dist/mcp/tools/runCode.js.map +1 -0
  254. package/dist/mcp/tools/screenshot.d.ts +6 -0
  255. package/dist/mcp/tools/screenshot.d.ts.map +1 -0
  256. package/dist/mcp/tools/screenshot.js +46 -0
  257. package/dist/mcp/tools/screenshot.js.map +1 -0
  258. package/dist/mcp/tools/snapshot.d.ts +6 -0
  259. package/dist/mcp/tools/snapshot.d.ts.map +1 -0
  260. package/dist/mcp/tools/snapshot.js +56 -0
  261. package/dist/mcp/tools/snapshot.js.map +1 -0
  262. package/dist/mcp/tools/tabs.d.ts +6 -0
  263. package/dist/mcp/tools/tabs.d.ts.map +1 -0
  264. package/dist/mcp/tools/tabs.js +34 -0
  265. package/dist/mcp/tools/tabs.js.map +1 -0
  266. package/dist/mcp/transports/http.d.ts +3 -0
  267. package/dist/mcp/transports/http.d.ts.map +1 -0
  268. package/dist/mcp/transports/http.js +134 -0
  269. package/dist/mcp/transports/http.js.map +1 -0
  270. package/dist/mcp/transports/inMemory.d.ts +3 -0
  271. package/dist/mcp/transports/inMemory.d.ts.map +1 -0
  272. package/dist/mcp/transports/inMemory.js +18 -0
  273. package/dist/mcp/transports/inMemory.js.map +1 -0
  274. package/dist/mcp/transports/stdio.d.ts +3 -0
  275. package/dist/mcp/transports/stdio.d.ts.map +1 -0
  276. package/dist/mcp/transports/stdio.js +16 -0
  277. package/dist/mcp/transports/stdio.js.map +1 -0
  278. package/dist/mcp/types.d.ts +193 -0
  279. package/dist/mcp/types.d.ts.map +1 -0
  280. package/dist/mcp/types.js +2 -0
  281. package/dist/mcp/types.js.map +1 -0
  282. package/dist/navigationResult.d.ts +10 -0
  283. package/dist/navigationResult.d.ts.map +1 -0
  284. package/dist/navigationResult.js +15 -0
  285. package/dist/navigationResult.js.map +1 -0
  286. package/dist/page.d.ts +907 -0
  287. package/dist/page.d.ts.map +1 -0
  288. package/dist/page.js +6385 -0
  289. package/dist/page.js.map +1 -0
  290. package/dist/pageApiReport.d.ts +31 -0
  291. package/dist/pageApiReport.d.ts.map +1 -0
  292. package/dist/pageApiReport.js +218 -0
  293. package/dist/pageApiReport.js.map +1 -0
  294. package/dist/pageResponse.d.ts +18 -0
  295. package/dist/pageResponse.d.ts.map +1 -0
  296. package/dist/pageResponse.js +23 -0
  297. package/dist/pageResponse.js.map +1 -0
  298. package/dist/processCleanup.d.ts +8 -0
  299. package/dist/processCleanup.d.ts.map +1 -0
  300. package/dist/processCleanup.js +413 -0
  301. package/dist/processCleanup.js.map +1 -0
  302. package/dist/protocol/adapter.d.ts +406 -0
  303. package/dist/protocol/adapter.d.ts.map +1 -0
  304. package/dist/protocol/adapter.js +8 -0
  305. package/dist/protocol/adapter.js.map +1 -0
  306. package/dist/protocol/bidi/backend.d.ts +8 -0
  307. package/dist/protocol/bidi/backend.d.ts.map +1 -0
  308. package/dist/protocol/bidi/backend.js +3616 -0
  309. package/dist/protocol/bidi/backend.js.map +1 -0
  310. package/dist/protocol/bidi/client.d.ts +104 -0
  311. package/dist/protocol/bidi/client.d.ts.map +1 -0
  312. package/dist/protocol/bidi/client.js +228 -0
  313. package/dist/protocol/bidi/client.js.map +1 -0
  314. package/dist/protocol/capabilities.d.ts +11 -0
  315. package/dist/protocol/capabilities.d.ts.map +1 -0
  316. package/dist/protocol/capabilities.js +2 -0
  317. package/dist/protocol/capabilities.js.map +1 -0
  318. package/dist/protocol/cdp/backend.d.ts +24 -0
  319. package/dist/protocol/cdp/backend.d.ts.map +1 -0
  320. package/dist/protocol/cdp/backend.js +8428 -0
  321. package/dist/protocol/cdp/backend.js.map +1 -0
  322. package/dist/protocol/evaluate.d.ts +2 -0
  323. package/dist/protocol/evaluate.d.ts.map +1 -0
  324. package/dist/protocol/evaluate.js +14 -0
  325. package/dist/protocol/evaluate.js.map +1 -0
  326. package/dist/protocol/evaluationSerializer.d.ts +6 -0
  327. package/dist/protocol/evaluationSerializer.d.ts.map +1 -0
  328. package/dist/protocol/evaluationSerializer.js +234 -0
  329. package/dist/protocol/evaluationSerializer.js.map +1 -0
  330. package/dist/protocol/keyboardInput.d.ts +34 -0
  331. package/dist/protocol/keyboardInput.d.ts.map +1 -0
  332. package/dist/protocol/keyboardInput.js +246 -0
  333. package/dist/protocol/keyboardInput.js.map +1 -0
  334. package/dist/protocol/routing.d.ts +40 -0
  335. package/dist/protocol/routing.d.ts.map +1 -0
  336. package/dist/protocol/routing.js +2 -0
  337. package/dist/protocol/routing.js.map +1 -0
  338. package/dist/protocol/selectorRuntime.d.ts +30 -0
  339. package/dist/protocol/selectorRuntime.d.ts.map +1 -0
  340. package/dist/protocol/selectorRuntime.js +1814 -0
  341. package/dist/protocol/selectorRuntime.js.map +1 -0
  342. package/dist/protocol/webdriver-classic/backend.d.ts +6 -0
  343. package/dist/protocol/webdriver-classic/backend.d.ts.map +1 -0
  344. package/dist/protocol/webdriver-classic/backend.js +158 -0
  345. package/dist/protocol/webdriver-classic/backend.js.map +1 -0
  346. package/dist/routeHandler.d.ts +15 -0
  347. package/dist/routeHandler.d.ts.map +1 -0
  348. package/dist/routeHandler.js +2 -0
  349. package/dist/routeHandler.js.map +1 -0
  350. package/dist/roxybrowser.bundle.js +78236 -0
  351. package/dist/roxybrowser.bundle.js.map +1 -0
  352. package/dist/screencast.d.ts +57 -0
  353. package/dist/screencast.d.ts.map +1 -0
  354. package/dist/screencast.js +155 -0
  355. package/dist/screencast.js.map +1 -0
  356. package/dist/screencastActions.d.ts +2 -0
  357. package/dist/screencastActions.d.ts.map +1 -0
  358. package/dist/screencastActions.js +183 -0
  359. package/dist/screencastActions.js.map +1 -0
  360. package/dist/screencastOverlay.d.ts +3 -0
  361. package/dist/screencastOverlay.d.ts.map +1 -0
  362. package/dist/screencastOverlay.js +119 -0
  363. package/dist/screencastOverlay.js.map +1 -0
  364. package/dist/screenshotOptions.d.ts +26 -0
  365. package/dist/screenshotOptions.d.ts.map +1 -0
  366. package/dist/screenshotOptions.js +171 -0
  367. package/dist/screenshotOptions.js.map +1 -0
  368. package/dist/screenshotPreparation.d.ts +21 -0
  369. package/dist/screenshotPreparation.d.ts.map +1 -0
  370. package/dist/screenshotPreparation.js +199 -0
  371. package/dist/screenshotPreparation.js.map +1 -0
  372. package/dist/selectOptionValues.d.ts +10 -0
  373. package/dist/selectOptionValues.d.ts.map +1 -0
  374. package/dist/selectOptionValues.js +60 -0
  375. package/dist/selectOptionValues.js.map +1 -0
  376. package/dist/selectors.d.ts +3 -0
  377. package/dist/selectors.d.ts.map +1 -0
  378. package/dist/selectors.js +287 -0
  379. package/dist/selectors.js.map +1 -0
  380. package/dist/types/api.d.ts +2164 -0
  381. package/dist/types/api.d.ts.map +1 -0
  382. package/dist/types/api.js +2 -0
  383. package/dist/types/api.js.map +1 -0
  384. package/dist/types/events.d.ts +158 -0
  385. package/dist/types/events.d.ts.map +1 -0
  386. package/dist/types/events.js +2 -0
  387. package/dist/types/events.js.map +1 -0
  388. package/dist/types/options.d.ts +263 -0
  389. package/dist/types/options.d.ts.map +1 -0
  390. package/dist/types/options.js +2 -0
  391. package/dist/types/options.js.map +1 -0
  392. package/dist/urlMatch.d.ts +19 -0
  393. package/dist/urlMatch.d.ts.map +1 -0
  394. package/dist/urlMatch.js +183 -0
  395. package/dist/urlMatch.js.map +1 -0
  396. package/dist/utilityScriptSerializers.d.ts +61 -0
  397. package/dist/utilityScriptSerializers.d.ts.map +1 -0
  398. package/dist/utilityScriptSerializers.js +297 -0
  399. package/dist/utilityScriptSerializers.js.map +1 -0
  400. package/dist/vendor/playwright/ariaSnapshotEvaluate.d.ts +2 -0
  401. package/dist/vendor/playwright/ariaSnapshotEvaluate.d.ts.map +1 -0
  402. package/dist/vendor/playwright/ariaSnapshotEvaluate.js +207 -0
  403. package/dist/vendor/playwright/ariaSnapshotEvaluate.js.map +1 -0
  404. package/dist/vendor/playwright/generated/clockSource.d.ts +9 -0
  405. package/dist/vendor/playwright/generated/clockSource.d.ts.map +1 -0
  406. package/dist/vendor/playwright/generated/clockSource.js +9 -0
  407. package/dist/vendor/playwright/generated/clockSource.js.map +1 -0
  408. package/dist/vendor/playwright/generated/injectedScriptSource.d.ts +9 -0
  409. package/dist/vendor/playwright/generated/injectedScriptSource.d.ts.map +1 -0
  410. package/dist/vendor/playwright/generated/injectedScriptSource.js +9 -0
  411. package/dist/vendor/playwright/generated/injectedScriptSource.js.map +1 -0
  412. package/dist/video.d.ts +39 -0
  413. package/dist/video.d.ts.map +1 -0
  414. package/dist/video.js +235 -0
  415. package/dist/video.js.map +1 -0
  416. package/dist/waitForSelector.d.ts +7 -0
  417. package/dist/waitForSelector.d.ts.map +1 -0
  418. package/dist/waitForSelector.js +23 -0
  419. package/dist/waitForSelector.js.map +1 -0
  420. package/dist/worker.d.ts +45 -0
  421. package/dist/worker.d.ts.map +1 -0
  422. package/dist/worker.js +192 -0
  423. package/dist/worker.js.map +1 -0
  424. package/package.json +82 -0
@@ -0,0 +1,1129 @@
1
+ import { STATUS_CODES } from "node:http";
2
+ import { randomUUID } from "node:crypto";
3
+ import { mkdtemp, readFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { createApiResponse, fetchWithRetries, RoxyAPIRequestContext } from "./apiRequestContext.js";
7
+ import { RoxyBrowserContextClockDelegate } from "./browserContextClock.js";
8
+ import { RoxyClock } from "./clock.js";
9
+ import { TimeoutError } from "./errors.js";
10
+ import { normalizeExtraHTTPHeaders } from "./httpHeaders.js";
11
+ import { RoxyPage } from "./page.js";
12
+ import { serializePageFunction } from "./evaluation.js";
13
+ import { urlMatches } from "./urlMatch.js";
14
+ import { RoxyVideo } from "./video.js";
15
+ const DEFAULT_CONTEXT_EVENT_TIMEOUT_MS = 30_000;
16
+ const BUBBLED_PAGE_EVENTS = [
17
+ "console",
18
+ "dialog",
19
+ "request",
20
+ "requestfailed",
21
+ "requestfinished",
22
+ "response"
23
+ ];
24
+ export class RoxyBrowserContext {
25
+ adapter;
26
+ humanDefaults;
27
+ options;
28
+ pageSet = new Set();
29
+ pageByAdapter = new Map();
30
+ adapterByPage = new WeakMap();
31
+ pendingPageRegistrations = new Map();
32
+ emittedPages = new WeakSet();
33
+ clockDelegate;
34
+ listeners = new Map();
35
+ pageEventDisposers = new WeakMap();
36
+ routeHandlers = [];
37
+ websocketRouteHandlers = [];
38
+ initScripts = new Set();
39
+ routeMatcherIds = new WeakMap();
40
+ disposeAdapterPageListener;
41
+ closed = false;
42
+ nextRouteMatcherId = 0;
43
+ videoOutputDirPromise = null;
44
+ clock;
45
+ request = new RoxyAPIRequestContext();
46
+ constructor(adapter, humanDefaults, options = {}, browserName = "chromium") {
47
+ this.adapter = adapter;
48
+ this.humanDefaults = humanDefaults;
49
+ this.options = options;
50
+ this.clockDelegate = new RoxyBrowserContextClockDelegate(this, browserName);
51
+ this.clock = new RoxyClock(this.clockDelegate);
52
+ this.disposeAdapterPageListener =
53
+ this.adapter.onPage?.((pageAdapter, openerAdapter, hasWindowOpener) => this.attachDiscoveredPage(pageAdapter, openerAdapter ?? null, hasWindowOpener ?? true)) ?? null;
54
+ }
55
+ async newPage() {
56
+ const pageAdapter = await this.adapter.newPage();
57
+ const page = await this.registerPage(pageAdapter);
58
+ this.emitPageEventOnce(page);
59
+ return page;
60
+ }
61
+ async addInitScript(script, arg) {
62
+ const source = await evaluationScript(script, arg);
63
+ if (this.adapter.addInitScript) {
64
+ return this.adapter.addInitScript(source);
65
+ }
66
+ const entry = {
67
+ source,
68
+ disposablesByPage: new WeakMap()
69
+ };
70
+ this.initScripts.add(entry);
71
+ await Promise.all(Array.from(this.pageSet, async (page) => {
72
+ const disposable = await page.addInitScript(source);
73
+ entry.disposablesByPage.set(page, disposable);
74
+ }));
75
+ return {
76
+ dispose: async () => {
77
+ if (!this.initScripts.delete(entry)) {
78
+ return;
79
+ }
80
+ await Promise.all(Array.from(this.pageSet, async (page) => {
81
+ await entry.disposablesByPage.get(page)?.dispose();
82
+ }));
83
+ }
84
+ };
85
+ }
86
+ async addCookies(cookies) {
87
+ if (!this.adapter.addCookies) {
88
+ throw new Error("Browser context cookies are not supported by this protocol adapter.");
89
+ }
90
+ await this.adapter.addCookies(cookies);
91
+ }
92
+ async cookies(urls) {
93
+ if (!this.adapter.cookies) {
94
+ throw new Error("Browser context cookies are not supported by this protocol adapter.");
95
+ }
96
+ const normalizedUrls = urls === undefined ? undefined : Array.isArray(urls) ? [...urls] : [urls];
97
+ return this.adapter.cookies(normalizedUrls);
98
+ }
99
+ async clearCookies(options) {
100
+ if (!this.adapter.clearCookies) {
101
+ throw new Error("Browser context cookies are not supported by this protocol adapter.");
102
+ }
103
+ await this.adapter.clearCookies(options);
104
+ }
105
+ pages() {
106
+ return Array.from(this.pageSet);
107
+ }
108
+ async close() {
109
+ if (this.closed) {
110
+ return;
111
+ }
112
+ this.closed = true;
113
+ try {
114
+ this.disposeAdapterPageListener?.();
115
+ await Promise.all(Array.from(this.pageSet).map(async (page) => {
116
+ await page.close();
117
+ }));
118
+ }
119
+ finally {
120
+ await this.request.dispose();
121
+ await this.adapter.close();
122
+ this.emit("close", this);
123
+ }
124
+ }
125
+ async setExtraHTTPHeaders(headers) {
126
+ await this.adapter.setExtraHTTPHeaders(normalizeExtraHTTPHeaders(headers));
127
+ }
128
+ async route(url, handler, options = {}) {
129
+ this.routeHandlers.push({
130
+ matcher: url,
131
+ handler,
132
+ activeInvocations: new Set(),
133
+ ignoreExceptions: false,
134
+ remainingTimes: options.times ?? null
135
+ });
136
+ await this.installRouteInterceptorsOnPages();
137
+ return {
138
+ dispose: async () => {
139
+ const index = this.routeHandlers.findIndex((entry) => entry.matcher === url && entry.handler === handler);
140
+ if (index >= 0) {
141
+ this.routeHandlers.splice(index, 1);
142
+ }
143
+ await this.syncRouteInterceptionOnPages();
144
+ }
145
+ };
146
+ }
147
+ async routeWebSocket(url, handler) {
148
+ this.websocketRouteHandlers.push({
149
+ matcher: url,
150
+ handler
151
+ });
152
+ await this.installRouteInterceptorsOnPages();
153
+ }
154
+ async unroute(url, handler) {
155
+ const removed = [];
156
+ for (let index = this.routeHandlers.length - 1; index >= 0; index -= 1) {
157
+ const entry = this.routeHandlers[index];
158
+ if (!entry) {
159
+ continue;
160
+ }
161
+ if (this.routeMatcherKey(entry.matcher) !== this.routeMatcherKey(url)) {
162
+ continue;
163
+ }
164
+ if (handler && entry.handler !== handler) {
165
+ continue;
166
+ }
167
+ removed.push(entry);
168
+ this.routeHandlers.splice(index, 1);
169
+ }
170
+ await this.stopRouteHandlers(removed, "default");
171
+ await this.syncRouteInterceptionOnPages();
172
+ }
173
+ async unrouteAll(options) {
174
+ const removed = [...this.routeHandlers];
175
+ this.routeHandlers.length = 0;
176
+ await this.stopRouteHandlers(removed, options?.behavior ?? "default");
177
+ await this.syncRouteInterceptionOnPages();
178
+ }
179
+ async storageState(options) {
180
+ return this.request.storageState(options);
181
+ }
182
+ detachPage(page) {
183
+ this.pageSet.delete(page);
184
+ const disposers = this.pageEventDisposers.get(page);
185
+ if (disposers) {
186
+ for (const dispose of disposers) {
187
+ dispose();
188
+ }
189
+ this.pageEventDisposers.delete(page);
190
+ }
191
+ const adapter = this.adapterByPage.get(page);
192
+ if (adapter) {
193
+ this.pageByAdapter.delete(adapter);
194
+ this.pendingPageRegistrations.delete(adapter);
195
+ this.adapterByPage.delete(page);
196
+ }
197
+ this.clockDelegate.detachPage(page);
198
+ }
199
+ on(event, listener) {
200
+ return this.addListener(event, listener);
201
+ }
202
+ once(event, listener) {
203
+ const wrapped = ((payload) => {
204
+ this.removeListener(event, listener);
205
+ listener(payload);
206
+ });
207
+ const entries = this.ensureListenerSet(event);
208
+ entries.add({
209
+ original: listener,
210
+ wrapped: wrapped
211
+ });
212
+ return this;
213
+ }
214
+ addListener(event, listener) {
215
+ const entries = this.ensureListenerSet(event);
216
+ entries.add({
217
+ original: listener,
218
+ wrapped: listener
219
+ });
220
+ return this;
221
+ }
222
+ removeListener(event, listener) {
223
+ const entries = this.listeners.get(event);
224
+ if (!entries) {
225
+ return this;
226
+ }
227
+ for (const entry of Array.from(entries)) {
228
+ if (entry.original === listener) {
229
+ entries.delete(entry);
230
+ }
231
+ }
232
+ if (entries.size === 0) {
233
+ this.listeners.delete(event);
234
+ }
235
+ return this;
236
+ }
237
+ off(event, listener) {
238
+ return this.removeListener(event, listener);
239
+ }
240
+ async waitForEvent(event, optionsOrPredicate) {
241
+ const predicate = typeof optionsOrPredicate === "function"
242
+ ? optionsOrPredicate
243
+ : optionsOrPredicate?.predicate;
244
+ const timeout = typeof optionsOrPredicate === "function"
245
+ ? DEFAULT_CONTEXT_EVENT_TIMEOUT_MS
246
+ : optionsOrPredicate?.timeout ?? DEFAULT_CONTEXT_EVENT_TIMEOUT_MS;
247
+ return new Promise((resolve, reject) => {
248
+ const timer = timeout === 0
249
+ ? null
250
+ : setTimeout(() => {
251
+ cleanup();
252
+ reject(new Error(`Timeout ${timeout}ms exceeded while waiting for event "${String(event)}"`));
253
+ }, timeout);
254
+ const cleanup = () => {
255
+ if (timer) {
256
+ clearTimeout(timer);
257
+ }
258
+ this.removeListener(event, listener);
259
+ if (event !== "close") {
260
+ this.removeListener("close", closeListener);
261
+ }
262
+ };
263
+ const closeListener = (() => {
264
+ cleanup();
265
+ reject(new Error("Browser context has been closed."));
266
+ });
267
+ const listener = (async (payload) => {
268
+ try {
269
+ if (predicate && !(await predicate(payload))) {
270
+ return;
271
+ }
272
+ cleanup();
273
+ resolve(payload);
274
+ }
275
+ catch (error) {
276
+ cleanup();
277
+ reject(error instanceof Error ? error : new Error(String(error)));
278
+ }
279
+ });
280
+ if (event !== "close") {
281
+ this.on("close", closeListener);
282
+ }
283
+ this.on(event, listener);
284
+ });
285
+ }
286
+ async attachDiscoveredPage(pageAdapter, openerAdapter, hasWindowOpener) {
287
+ const pageRegistration = this.registerPage(pageAdapter);
288
+ const page = await pageRegistration;
289
+ const resolvedOpenerAdapter = openerAdapter ?? await this.resolvePageAdapterByTargetId(this.openerTargetIdOf(pageAdapter));
290
+ const opener = resolvedOpenerAdapter
291
+ ? await this.registerPage(resolvedOpenerAdapter)
292
+ : hasWindowOpener
293
+ ? this.resolveFallbackPopupOpener(page)
294
+ : null;
295
+ if (!opener) {
296
+ this.emitPageEventOnce(page);
297
+ return;
298
+ }
299
+ if (opener === page) {
300
+ return;
301
+ }
302
+ page.setOpener(hasWindowOpener ? opener : null);
303
+ this.emitPageEventOnce(page);
304
+ opener.emitPopup(page);
305
+ await pageRegistration;
306
+ }
307
+ async registerPage(pageAdapter) {
308
+ const pending = this.pendingPageRegistrations.get(pageAdapter);
309
+ if (pending) {
310
+ return pending;
311
+ }
312
+ const existing = this.pageByAdapter.get(pageAdapter);
313
+ if (existing) {
314
+ return existing;
315
+ }
316
+ const registration = this.createPage(pageAdapter);
317
+ this.pendingPageRegistrations.set(pageAdapter, registration);
318
+ try {
319
+ return await registration;
320
+ }
321
+ finally {
322
+ this.pendingPageRegistrations.delete(pageAdapter);
323
+ }
324
+ }
325
+ async createPage(pageAdapter) {
326
+ const page = new RoxyPage(pageAdapter, this.humanDefaults, this, this.options);
327
+ this.pageSet.add(page);
328
+ this.pageByAdapter.set(pageAdapter, page);
329
+ this.adapterByPage.set(page, pageAdapter);
330
+ this.attachPageEventBubbling(page);
331
+ try {
332
+ for (const entry of this.initScripts) {
333
+ const disposable = await page.addInitScript(entry.source);
334
+ entry.disposablesByPage.set(page, disposable);
335
+ }
336
+ await page._ensurePlaywrightBuiltinsInstalled().catch((error) => {
337
+ if (isClosedPageRegistrationError(error)) {
338
+ return;
339
+ }
340
+ throw error;
341
+ });
342
+ await this.clockDelegate.attachPage(page).catch((error) => {
343
+ if (isClosedPageRegistrationError(error)) {
344
+ return;
345
+ }
346
+ throw error;
347
+ });
348
+ if (this.options.recordVideo) {
349
+ await this.enableRecordVideo(page, this.options.recordVideo).catch((error) => {
350
+ if (isClosedPageRegistrationError(error)) {
351
+ return;
352
+ }
353
+ throw error;
354
+ });
355
+ }
356
+ if (this._hasRouteInterception()) {
357
+ await page._ensureRouteInterceptorsInstalled().catch((error) => {
358
+ if (isClosedPageRegistrationError(error)) {
359
+ return;
360
+ }
361
+ throw error;
362
+ });
363
+ }
364
+ return page;
365
+ }
366
+ catch (error) {
367
+ if (isClosedPageRegistrationError(error)) {
368
+ return page;
369
+ }
370
+ this.pageSet.delete(page);
371
+ this.pageByAdapter.delete(pageAdapter);
372
+ this.adapterByPage.delete(page);
373
+ this.clockDelegate.detachPage(page);
374
+ throw error;
375
+ }
376
+ }
377
+ emitPageEventOnce(page) {
378
+ if (this.emittedPages.has(page)) {
379
+ return;
380
+ }
381
+ this.emittedPages.add(page);
382
+ this.emit("page", page);
383
+ }
384
+ async enableRecordVideo(page, options) {
385
+ const directory = await this.resolveVideoOutputDirectory(options.dir);
386
+ const videoPath = join(directory, `${randomUUID()}.webm`);
387
+ const videoSize = options.size ?? this.deriveDefaultRecordVideoSize();
388
+ let resolveFinished;
389
+ let rejectFinished;
390
+ const finished = new Promise((resolve, reject) => {
391
+ resolveFinished = resolve;
392
+ rejectFinished = reject;
393
+ });
394
+ const video = new RoxyVideo(videoPath, finished);
395
+ page.setVideo(video);
396
+ try {
397
+ const recording = await page.startVideoRecording({
398
+ path: videoPath,
399
+ size: videoSize,
400
+ ...(options.showActions ? { showActions: options.showActions } : {})
401
+ });
402
+ page.setVideo(video, async () => {
403
+ try {
404
+ await recording.dispose();
405
+ resolveFinished();
406
+ }
407
+ catch (error) {
408
+ rejectFinished(error);
409
+ throw error;
410
+ }
411
+ }, rejectFinished);
412
+ }
413
+ catch (error) {
414
+ page.setVideo(null);
415
+ rejectFinished(error);
416
+ throw error;
417
+ }
418
+ }
419
+ async resolveVideoOutputDirectory(configuredDirectory) {
420
+ if (configuredDirectory) {
421
+ return configuredDirectory;
422
+ }
423
+ if (!this.videoOutputDirPromise) {
424
+ this.videoOutputDirPromise = mkdtemp(join(tmpdir(), "roxy-videos-"));
425
+ }
426
+ return this.videoOutputDirPromise;
427
+ }
428
+ deriveDefaultRecordVideoSize() {
429
+ if (Object.prototype.hasOwnProperty.call(this.options, "viewport") && this.options.viewport === null) {
430
+ return {
431
+ width: 800,
432
+ height: 600
433
+ };
434
+ }
435
+ if (this.options.viewport) {
436
+ const scale = Math.min(1, 800 / Math.max(this.options.viewport.width, this.options.viewport.height));
437
+ return {
438
+ width: Math.max(2, Math.floor(this.options.viewport.width * scale)) & ~1,
439
+ height: Math.max(2, Math.floor(this.options.viewport.height * scale)) & ~1
440
+ };
441
+ }
442
+ return {
443
+ width: 800,
444
+ height: 450
445
+ };
446
+ }
447
+ async resolvePageAdapterByTargetId(targetId) {
448
+ if (!targetId) {
449
+ return null;
450
+ }
451
+ for (const adapter of this.pageByAdapter.keys()) {
452
+ if (this.targetIdOf(adapter) === targetId) {
453
+ return adapter;
454
+ }
455
+ }
456
+ for (const adapter of this.pendingPageRegistrations.keys()) {
457
+ if (this.targetIdOf(adapter) === targetId) {
458
+ return adapter;
459
+ }
460
+ }
461
+ return null;
462
+ }
463
+ openerTargetIdOf(pageAdapter) {
464
+ return pageAdapter.__roxyOpenerTargetId;
465
+ }
466
+ targetIdOf(pageAdapter) {
467
+ return pageAdapter.__roxyTargetId;
468
+ }
469
+ resolveFallbackPopupOpener(page) {
470
+ const candidates = Array.from(this.pageSet).filter((candidate) => candidate !== page);
471
+ return candidates.length === 1 ? (candidates[0] ?? null) : null;
472
+ }
473
+ ensureListenerSet(event) {
474
+ const existing = this.listeners.get(event);
475
+ if (existing) {
476
+ return existing;
477
+ }
478
+ const created = new Set();
479
+ this.listeners.set(event, created);
480
+ return created;
481
+ }
482
+ emit(event, payload) {
483
+ const entries = this.listeners.get(event);
484
+ if (!entries?.size) {
485
+ return false;
486
+ }
487
+ for (const entry of Array.from(entries)) {
488
+ const listener = entry.wrapped;
489
+ listener(payload);
490
+ }
491
+ return true;
492
+ }
493
+ shouldAutoHandleDialog(_page) {
494
+ return (this.listeners.get("dialog")?.size ?? 0) === 0;
495
+ }
496
+ attachPageEventBubbling(page) {
497
+ const disposers = [];
498
+ for (const event of BUBBLED_PAGE_EVENTS) {
499
+ const listener = ((payload) => {
500
+ this.emit(event, payload);
501
+ });
502
+ disposers.push(page.attachInternalListener(event, listener));
503
+ }
504
+ this.pageEventDisposers.set(page, disposers);
505
+ }
506
+ async _onWebSocketRoute(websocketroute) {
507
+ for (let index = this.websocketRouteHandlers.length - 1; index >= 0; index -= 1) {
508
+ const entry = this.websocketRouteHandlers[index];
509
+ if (!entry || !this.matchesWebSocketRoute(websocketroute.url(), entry.matcher)) {
510
+ continue;
511
+ }
512
+ await entry.handler(websocketroute);
513
+ return true;
514
+ }
515
+ return false;
516
+ }
517
+ _hasRequestRoutes() {
518
+ return this.routeHandlers.length > 0;
519
+ }
520
+ _hasWebSocketRoutes() {
521
+ return this.websocketRouteHandlers.length > 0;
522
+ }
523
+ _hasRouteInterception() {
524
+ return this.routeHandlers.length > 0 || this.websocketRouteHandlers.length > 0;
525
+ }
526
+ _contextRouteHandlers() {
527
+ return [...this.routeHandlers];
528
+ }
529
+ _findLiveContextRouteHandlerIndex(entry) {
530
+ return this.routeHandlers.indexOf(entry);
531
+ }
532
+ _consumeContextRouteHandler(entry, liveIndex) {
533
+ if (entry.remainingTimes !== null && entry.remainingTimes <= 1) {
534
+ this.routeHandlers.splice(liveIndex, 1);
535
+ }
536
+ else if (entry.remainingTimes !== null) {
537
+ entry.remainingTimes -= 1;
538
+ }
539
+ }
540
+ _buildRouteFulfillDecision(request, options) {
541
+ return buildFulfillDecision(request, options);
542
+ }
543
+ _matchesRouteMatcher(url, matcher) {
544
+ if (url.startsWith("data:")) {
545
+ return false;
546
+ }
547
+ const normalizedUrl = tryParseUrl(url)?.toString() ?? url;
548
+ return urlMatches(this.options.baseURL, normalizedUrl, matcher, true);
549
+ }
550
+ matchesWebSocketRoute(url, matcher) {
551
+ const normalizedUrl = tryParseUrl(url)?.toString() ?? url;
552
+ return urlMatches(this.options.baseURL, normalizedUrl, matcher, true);
553
+ }
554
+ async installRouteInterceptorsOnPages() {
555
+ if (this.adapter.setRequestInterceptor) {
556
+ await this.adapter.setRequestInterceptor((call) => this.dispatchContextRoutedRequest(call));
557
+ return;
558
+ }
559
+ await Promise.all(Array.from(this.pageSet, async (page) => page._ensureRouteInterceptorsInstalled()));
560
+ }
561
+ async syncRouteInterceptionOnPages() {
562
+ if (this.adapter.setRequestInterceptor) {
563
+ await this.adapter.setRequestInterceptor(this._hasRequestRoutes() ? (call) => this.dispatchContextRoutedRequest(call) : null);
564
+ return;
565
+ }
566
+ await Promise.all(Array.from(this.pageSet, async (page) => page._syncRouteInterceptionForContext()));
567
+ }
568
+ async dispatchContextRoutedRequest(call) {
569
+ let requestState = {
570
+ ...call,
571
+ headers: normalizeHeaderRecord(call.headers)
572
+ };
573
+ let routedResponse = null;
574
+ let routedFailure = null;
575
+ const request = createContextRouteRequest(() => requestState, () => routedResponse, () => routedFailure);
576
+ const handlers = [...this.routeHandlers];
577
+ for (let index = handlers.length - 1; index >= 0; index -= 1) {
578
+ const entry = handlers[index];
579
+ if (!entry || !this._matchesRouteMatcher(requestState.url, entry.matcher)) {
580
+ continue;
581
+ }
582
+ const liveIndex = this._findLiveContextRouteHandlerIndex(entry);
583
+ if (liveIndex === -1) {
584
+ continue;
585
+ }
586
+ this._consumeContextRouteHandler(entry, liveIndex);
587
+ let routeOutcome = null;
588
+ let routeHandled = false;
589
+ let resolveRouteHandled;
590
+ const routeHandledPromise = new Promise((resolve) => {
591
+ resolveRouteHandled = resolve;
592
+ });
593
+ const ensureRouteIsUnhandled = () => {
594
+ if (routeHandled) {
595
+ throw new Error("Route is already handled!");
596
+ }
597
+ };
598
+ const reportRouteHandled = (outcome) => {
599
+ routeOutcome ??= outcome;
600
+ resolveRouteHandled(routeOutcome);
601
+ };
602
+ const route = {
603
+ abort: async (errorCode) => {
604
+ ensureRouteIsUnhandled();
605
+ routeHandled = true;
606
+ routedFailure = { errorText: errorCode ?? "failed" };
607
+ reportRouteHandled({
608
+ kind: "finish",
609
+ decision: {
610
+ action: "abort",
611
+ ...(errorCode !== undefined ? { errorCode } : {})
612
+ }
613
+ });
614
+ },
615
+ continue: async (options) => {
616
+ ensureRouteIsUnhandled();
617
+ routeHandled = true;
618
+ requestState = applyContextRouteOverrides(requestState, options);
619
+ reportRouteHandled({
620
+ kind: "finish",
621
+ decision: {
622
+ action: "continue",
623
+ headers: { ...requestState.headers },
624
+ method: requestState.method,
625
+ ...serializePostDataFields(requestState.postData, deserializeSerializedPostData(requestState.postData, requestState.postDataBufferBase64 ?? null).buffer),
626
+ url: requestState.url
627
+ }
628
+ });
629
+ },
630
+ fallback: async (options) => {
631
+ ensureRouteIsUnhandled();
632
+ routeHandled = true;
633
+ requestState = applyContextRouteOverrides(requestState, options);
634
+ reportRouteHandled({ kind: "fallback" });
635
+ },
636
+ fetch: async (options) => {
637
+ ensureRouteIsUnhandled();
638
+ const fetchedRequest = applyContextRouteOverrides(requestState, options);
639
+ const response = await fetchContextRouteRequest(fetchedRequest, options);
640
+ routedResponse = createRoutedResponse(await responseDataFromResponse(response), request);
641
+ return response;
642
+ },
643
+ fulfill: async (options = {}) => {
644
+ ensureRouteIsUnhandled();
645
+ const decision = await this._buildRouteFulfillDecision(requestState, options);
646
+ routeHandled = true;
647
+ routedResponse = createRoutedResponse({
648
+ body: decision.body,
649
+ ...(decision.bodyBufferBase64 != null
650
+ ? { bodyBufferBase64: decision.bodyBufferBase64 }
651
+ : {}),
652
+ headers: { ...decision.headers },
653
+ status: decision.status,
654
+ statusText: decision.statusText,
655
+ url: decision.url
656
+ }, request);
657
+ reportRouteHandled({
658
+ kind: "finish",
659
+ decision
660
+ });
661
+ },
662
+ request: () => request
663
+ };
664
+ let resolveInvocation;
665
+ const invocation = {
666
+ complete: new Promise((resolve) => {
667
+ resolveInvocation = resolve;
668
+ }),
669
+ resolve: () => {
670
+ resolveInvocation();
671
+ }
672
+ };
673
+ entry.activeInvocations.add(invocation);
674
+ let resolvedOutcome = null;
675
+ try {
676
+ const [handledOutcome] = await Promise.all([
677
+ routeHandledPromise,
678
+ Promise.resolve().then(() => entry.handler(route, request))
679
+ ]);
680
+ resolvedOutcome = handledOutcome;
681
+ }
682
+ catch (error) {
683
+ if (!entry.ignoreExceptions) {
684
+ throw error;
685
+ }
686
+ resolvedOutcome = routeOutcome;
687
+ }
688
+ finally {
689
+ invocation.resolve();
690
+ entry.activeInvocations.delete(invocation);
691
+ }
692
+ if (!resolvedOutcome) {
693
+ continue;
694
+ }
695
+ if (resolvedOutcome.kind === "fallback") {
696
+ continue;
697
+ }
698
+ return resolvedOutcome.decision;
699
+ }
700
+ return {
701
+ action: "continue",
702
+ headers: { ...requestState.headers },
703
+ method: requestState.method,
704
+ ...serializePostDataFields(requestState.postData, deserializeSerializedPostData(requestState.postData, requestState.postDataBufferBase64 ?? null).buffer),
705
+ url: requestState.url
706
+ };
707
+ }
708
+ async stopRouteHandlers(entries, behavior) {
709
+ if (behavior === "ignoreErrors") {
710
+ for (const entry of entries) {
711
+ entry.ignoreExceptions = true;
712
+ for (const invocation of entry.activeInvocations) {
713
+ invocation.resolve();
714
+ }
715
+ }
716
+ return;
717
+ }
718
+ if (behavior === "wait") {
719
+ await Promise.all(entries.flatMap((entry) => Array.from(entry.activeInvocations, (invocation) => invocation.complete)));
720
+ }
721
+ }
722
+ routeMatcherKey(matcher) {
723
+ if (typeof matcher === "string") {
724
+ return `string:${matcher}`;
725
+ }
726
+ if (matcher instanceof RegExp) {
727
+ return `regexp:${matcher.source}/${matcher.flags}`;
728
+ }
729
+ const existing = this.routeMatcherIds.get(matcher);
730
+ if (existing) {
731
+ return existing;
732
+ }
733
+ const id = `matcher:${++this.nextRouteMatcherId}`;
734
+ this.routeMatcherIds.set(matcher, id);
735
+ return id;
736
+ }
737
+ }
738
+ function tryParseUrl(url) {
739
+ try {
740
+ return new URL(url);
741
+ }
742
+ catch {
743
+ return null;
744
+ }
745
+ }
746
+ function isClosedPageRegistrationError(error) {
747
+ const message = String(error instanceof Error ? error.message : error).toLowerCase();
748
+ return (message.includes("target page, context or browser has been closed")
749
+ || message.includes("browser context has been closed")
750
+ || message.includes("session closed")
751
+ || message.includes("session with given id not found")
752
+ || message.includes("connection closed")
753
+ || message.includes("target closed")
754
+ || message.includes("websocket connection closed")
755
+ || message.includes("write epipe"));
756
+ }
757
+ async function evaluationScript(script, arg) {
758
+ if (typeof script === "function") {
759
+ const source = serializePageFunction(script);
760
+ const argString = Object.is(arg, undefined) ? "undefined" : JSON.stringify(arg);
761
+ return `(${source})(${argString})`;
762
+ }
763
+ if (arg !== undefined) {
764
+ throw new Error("Cannot evaluate a string with arguments");
765
+ }
766
+ if (typeof script === "string") {
767
+ return script;
768
+ }
769
+ if (script.content !== undefined) {
770
+ return script.content;
771
+ }
772
+ if (script.path !== undefined) {
773
+ const source = await readFile(script.path, "utf8");
774
+ return `${source}\n//# sourceURL=${script.path.replace(/\n/g, "")}`;
775
+ }
776
+ throw new Error("Either path or content property must be present");
777
+ }
778
+ function applyContextRouteOverrides(request, options) {
779
+ if (!options) {
780
+ return request;
781
+ }
782
+ const headers = options.headers === undefined
783
+ ? request.headers
784
+ : Array.isArray(options.headers)
785
+ ? Object.fromEntries(options.headers.map((header) => [header.name, header.value]))
786
+ : { ...options.headers };
787
+ const normalizedPostData = options.postData !== undefined
788
+ ? normalizeSerializedPostData(options.postData)
789
+ : deserializeSerializedPostData(request.postData, request.postDataBufferBase64 ?? null);
790
+ return {
791
+ ...request,
792
+ headers,
793
+ method: options.method ?? request.method,
794
+ ...serializePostDataFields(normalizedPostData.text, normalizedPostData.buffer),
795
+ url: options.url ?? request.url
796
+ };
797
+ }
798
+ function normalizeSerializedPostData(value) {
799
+ if (value === undefined || value === null) {
800
+ return { buffer: null, text: null };
801
+ }
802
+ if (typeof value === "string") {
803
+ return {
804
+ buffer: Buffer.from(value, "utf8"),
805
+ text: value
806
+ };
807
+ }
808
+ if (Buffer.isBuffer(value)) {
809
+ return {
810
+ buffer: Buffer.from(value),
811
+ text: value.toString("utf8")
812
+ };
813
+ }
814
+ const text = JSON.stringify(value);
815
+ return {
816
+ buffer: Buffer.from(text, "utf8"),
817
+ text
818
+ };
819
+ }
820
+ function deserializeSerializedPostData(text, base64) {
821
+ if (base64 !== null) {
822
+ const buffer = Buffer.from(base64, "base64");
823
+ return {
824
+ buffer,
825
+ text: text ?? buffer.toString("utf8")
826
+ };
827
+ }
828
+ if (text === null) {
829
+ return { buffer: null, text: null };
830
+ }
831
+ return {
832
+ buffer: Buffer.from(text, "utf8"),
833
+ text
834
+ };
835
+ }
836
+ function serializePostDataFields(text, buffer) {
837
+ return {
838
+ postData: text,
839
+ ...(buffer ? { postDataBufferBase64: buffer.toString("base64") } : {})
840
+ };
841
+ }
842
+ function createContextRouteRequest(current, currentResponse, currentFailure) {
843
+ return {
844
+ allHeaders: async () => ({ ...current().headers }),
845
+ existingResponse: () => currentResponse(),
846
+ failure: () => currentFailure(),
847
+ frame: () => {
848
+ throw new Error("Request.frame is not available for context-level protocol interception.");
849
+ },
850
+ headers: () => ({ ...current().headers }),
851
+ headersArray: async () => Object.entries(current().headers).map(([name, value]) => ({ name, value })),
852
+ headerValue: async (name) => current().headers[name.toLowerCase()] ?? null,
853
+ isNavigationRequest: () => current().isNavigationRequest ?? false,
854
+ method: () => current().method,
855
+ postData: () => deserializeSerializedPostData(current().postData, current().postDataBufferBase64 ?? null).text,
856
+ postDataBuffer: () => {
857
+ const buffer = deserializeSerializedPostData(current().postData, current().postDataBufferBase64 ?? null).buffer;
858
+ return buffer ? Buffer.from(buffer) : null;
859
+ },
860
+ postDataJSON: () => {
861
+ const { text } = deserializeSerializedPostData(current().postData, current().postDataBufferBase64 ?? null);
862
+ if (text === null) {
863
+ return null;
864
+ }
865
+ try {
866
+ return JSON.parse(text);
867
+ }
868
+ catch {
869
+ return null;
870
+ }
871
+ },
872
+ redirectedFrom: () => null,
873
+ redirectedTo: () => null,
874
+ resourceType: () => current().resourceType ?? "fetch",
875
+ response: async () => currentResponse(),
876
+ serviceWorker: () => null,
877
+ sizes: async () => {
878
+ const response = currentResponse();
879
+ const requestBody = deserializeSerializedPostData(current().postData, current().postDataBufferBase64 ?? null).buffer;
880
+ const responseHeaders = response ? await response.allHeaders() : {};
881
+ return {
882
+ requestBodySize: requestBody?.byteLength ?? 0,
883
+ requestHeadersSize: headerSize(current().headers),
884
+ responseBodySize: response ? await measureResponseBodySize(response) : 0,
885
+ responseHeadersSize: headerSize(responseHeaders)
886
+ };
887
+ },
888
+ timing: () => ({
889
+ startTime: Date.now(),
890
+ domainLookupStart: -1,
891
+ domainLookupEnd: -1,
892
+ connectStart: -1,
893
+ secureConnectionStart: -1,
894
+ connectEnd: -1,
895
+ requestStart: 0,
896
+ responseStart: -1,
897
+ responseEnd: -1
898
+ }),
899
+ url: () => current().url
900
+ };
901
+ }
902
+ async function fetchContextRouteRequest(request, options) {
903
+ const fetchRequest = applyContextRouteOverrides(request, options);
904
+ const requestBody = deserializeSerializedPostData(fetchRequest.postData, fetchRequest.postDataBufferBase64 ?? null).buffer;
905
+ const headers = { ...fetchRequest.headers };
906
+ if (options?.postData !== undefined && headers["content-type"] === undefined) {
907
+ if (Buffer.isBuffer(options.postData)) {
908
+ headers["content-type"] = "application/octet-stream";
909
+ }
910
+ else if (typeof options.postData === "object" &&
911
+ options.postData !== null &&
912
+ !Buffer.isBuffer(options.postData)) {
913
+ headers["content-type"] = "application/json";
914
+ }
915
+ }
916
+ const controller = new AbortController();
917
+ const timeout = options?.timeout ?? DEFAULT_CONTEXT_EVENT_TIMEOUT_MS;
918
+ const timeoutHandle = timeout > 0
919
+ ? setTimeout(() => controller.abort(new TimeoutError(`route.fetch: Timeout ${timeout}ms exceeded`)), timeout)
920
+ : null;
921
+ try {
922
+ const response = await fetchWithRetries(fetchRequest.url, {
923
+ allowGetOrHeadBody: true,
924
+ ...(!requestBody ? {} : { body: requestBody }),
925
+ headers,
926
+ method: fetchRequest.method,
927
+ signal: controller.signal,
928
+ ...(options?.maxRedirects !== undefined ? { maxRedirects: options.maxRedirects } : {}),
929
+ ...(options?.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {})
930
+ });
931
+ return createApiResponse(response);
932
+ }
933
+ finally {
934
+ if (timeoutHandle) {
935
+ clearTimeout(timeoutHandle);
936
+ }
937
+ }
938
+ }
939
+ function bufferToText(value) {
940
+ return Buffer.isBuffer(value) ? value.toString("utf8") : value;
941
+ }
942
+ function normalizeHeaderRecord(headers) {
943
+ const normalized = {};
944
+ for (const [name, value] of Object.entries(headers)) {
945
+ normalized[name.toLowerCase()] = value;
946
+ }
947
+ return normalized;
948
+ }
949
+ function hasExplicitHeader(headers, name) {
950
+ if (!headers) {
951
+ return false;
952
+ }
953
+ return Object.keys(headers).some((headerName) => headerName.toLowerCase() === name.toLowerCase());
954
+ }
955
+ function statusTextForCode(status) {
956
+ return STATUS_CODES[status] ?? "Unknown";
957
+ }
958
+ function inferMimeType(path) {
959
+ if (path.endsWith(".html"))
960
+ return "text/html";
961
+ if (path.endsWith(".json"))
962
+ return "application/json";
963
+ if (path.endsWith(".txt"))
964
+ return "text/plain";
965
+ if (path.endsWith(".css"))
966
+ return "text/css";
967
+ if (path.endsWith(".js"))
968
+ return "application/javascript";
969
+ if (path.endsWith(".svg"))
970
+ return "image/svg+xml";
971
+ if (path.endsWith(".png"))
972
+ return "image/png";
973
+ if (path.endsWith(".jpg") || path.endsWith(".jpeg"))
974
+ return "image/jpeg";
975
+ if (path.endsWith(".webp"))
976
+ return "image/webp";
977
+ return "application/octet-stream";
978
+ }
979
+ function headerSize(headers) {
980
+ return Object.entries(headers).reduce((size, [name, value]) => size + Buffer.byteLength(`${name}: ${value}\r\n`, "utf8"), 2);
981
+ }
982
+ async function measureResponseBodySize(response) {
983
+ const body = await response.body();
984
+ return body ? body.length : 0;
985
+ }
986
+ function createRoutedResponse(data, request) {
987
+ const body = data.bodyBufferBase64 !== undefined
988
+ ? Buffer.from(data.bodyBufferBase64, "base64")
989
+ : Buffer.from(data.body, "utf8");
990
+ return {
991
+ allHeaders: async () => ({ ...data.headers }),
992
+ body: async () => Buffer.from(body),
993
+ finished: async () => null,
994
+ frame: () => {
995
+ throw new Error("Response.frame is not available for context-level protocol interception.");
996
+ },
997
+ fromServiceWorker: () => false,
998
+ headerValue: async (name) => data.headers[name.toLowerCase()] ?? null,
999
+ headerValues: async (name) => {
1000
+ const value = data.headers[name.toLowerCase()];
1001
+ return value === undefined ? [] : [value];
1002
+ },
1003
+ headers: () => ({ ...data.headers }),
1004
+ headersArray: async () => Object.entries(data.headers).map(([name, value]) => ({ name, value })),
1005
+ httpVersion: async () => "HTTP/1.1",
1006
+ json: async () => JSON.parse(body.toString("utf8")),
1007
+ ok: () => data.status >= 200 && data.status <= 299,
1008
+ request: () => request,
1009
+ securityDetails: async () => null,
1010
+ serverAddr: async () => null,
1011
+ status: () => data.status,
1012
+ statusText: () => data.statusText,
1013
+ text: async () => body.toString("utf8"),
1014
+ url: () => data.url
1015
+ };
1016
+ }
1017
+ async function responseDataFromResponse(response) {
1018
+ const bodyBuffer = await responseBodyBuffer(response);
1019
+ return {
1020
+ body: bodyBuffer.toString("utf8"),
1021
+ ...(bodyBuffer.length ? { bodyBufferBase64: bodyBuffer.toString("base64") } : {}),
1022
+ headers: normalizeHeaderRecord(await responseHeadersRecord(response)),
1023
+ status: getResponseStatus(response),
1024
+ statusText: getResponseStatusText(response),
1025
+ url: response.url()
1026
+ };
1027
+ }
1028
+ async function responseHeadersRecord(response) {
1029
+ if ("allHeaders" in response && typeof response.allHeaders === "function") {
1030
+ return response.allHeaders();
1031
+ }
1032
+ if (typeof response.headers === "function") {
1033
+ return response.headers();
1034
+ }
1035
+ return Object.fromEntries(response.headers.map((header) => [header.name, header.value]));
1036
+ }
1037
+ function getResponseStatus(response) {
1038
+ return typeof response.status === "function" ? response.status() : response.status;
1039
+ }
1040
+ function getResponseStatusText(response) {
1041
+ return typeof response.statusText === "function" ? response.statusText() : response.statusText;
1042
+ }
1043
+ async function responseBodyBuffer(response) {
1044
+ if ("body" in response && typeof response.body === "function") {
1045
+ return response.body();
1046
+ }
1047
+ return Buffer.from(await response.text(), "utf8");
1048
+ }
1049
+ async function buildFulfillDecision(request, options) {
1050
+ if (options.json !== undefined && options.body !== undefined) {
1051
+ throw new Error("Can specify either body or json parameters");
1052
+ }
1053
+ const responseHeaders = options.response ? await responseHeadersRecord(options.response) : {};
1054
+ const headers = normalizeHeaderRecord({
1055
+ ...responseHeaders,
1056
+ ...(options.headers ?? {})
1057
+ });
1058
+ let body = "";
1059
+ let bodyBuffer = null;
1060
+ if (options.path) {
1061
+ bodyBuffer = await readFile(options.path);
1062
+ body = bodyBuffer.toString("utf8");
1063
+ if (!hasExplicitHeader(options.headers, "content-type")) {
1064
+ headers["content-type"] = inferMimeType(options.path);
1065
+ }
1066
+ }
1067
+ else if (options.json !== undefined) {
1068
+ body = JSON.stringify(options.json);
1069
+ bodyBuffer = Buffer.from(body, "utf8");
1070
+ if (!("content-type" in headers) && !options.contentType) {
1071
+ headers["content-type"] = "application/json";
1072
+ }
1073
+ }
1074
+ else if (options.body !== undefined) {
1075
+ body = bufferToText(options.body);
1076
+ bodyBuffer = Buffer.isBuffer(options.body)
1077
+ ? Buffer.from(options.body)
1078
+ : Buffer.from(body, "utf8");
1079
+ }
1080
+ else if (options.response) {
1081
+ bodyBuffer = await responseBodyBuffer(options.response);
1082
+ body = bodyBuffer.toString("utf8");
1083
+ }
1084
+ if (options.contentType && !options.path) {
1085
+ headers["content-type"] = options.contentType;
1086
+ }
1087
+ if (bodyBuffer !== null && !hasExplicitHeader(options.headers, "content-length")) {
1088
+ headers["content-length"] = String(bodyBuffer.byteLength);
1089
+ }
1090
+ maybeAddCorsHeaders(request, headers);
1091
+ const inheritedStatus = options.response ? getResponseStatus(options.response) : undefined;
1092
+ const inheritedStatusText = options.response ? getResponseStatusText(options.response) : undefined;
1093
+ const status = options.status ?? inheritedStatus ?? 200;
1094
+ return {
1095
+ action: "fulfill",
1096
+ body,
1097
+ ...(bodyBuffer ? { bodyBufferBase64: bodyBuffer.toString("base64") } : {}),
1098
+ headers,
1099
+ status,
1100
+ statusText: inheritedStatusText ?? statusTextForCode(status),
1101
+ url: request.url
1102
+ };
1103
+ }
1104
+ function maybeAddCorsHeaders(request, headers) {
1105
+ const origin = request.headers.origin;
1106
+ if (!origin) {
1107
+ return;
1108
+ }
1109
+ let requestUrl;
1110
+ try {
1111
+ requestUrl = new URL(request.url);
1112
+ }
1113
+ catch {
1114
+ return;
1115
+ }
1116
+ if (!requestUrl.protocol.startsWith("http")) {
1117
+ return;
1118
+ }
1119
+ if (requestUrl.origin === origin.trim()) {
1120
+ return;
1121
+ }
1122
+ if (Object.keys(headers).some((name) => name.toLowerCase() === "access-control-allow-origin")) {
1123
+ return;
1124
+ }
1125
+ headers["access-control-allow-origin"] = origin;
1126
+ headers["access-control-allow-credentials"] = "true";
1127
+ headers.vary = "Origin";
1128
+ }
1129
+ //# sourceMappingURL=browserContext.js.map