browser-debugger-cli 0.8.0 → 0.10.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 (304) hide show
  1. package/README.md +7 -1
  2. package/dist/cdp/schema.d.ts +4 -1
  3. package/dist/cdp/schema.js +48 -7
  4. package/dist/commands/cdp.js +3 -2
  5. package/dist/commands/cleanup.d.ts +11 -0
  6. package/dist/commands/cleanup.js +161 -57
  7. package/dist/commands/console.d.ts +20 -1
  8. package/dist/commands/console.js +57 -17
  9. package/dist/commands/details.js +3 -2
  10. package/dist/commands/dom/DomElementResolver.d.ts +10 -3
  11. package/dist/commands/dom/DomElementResolver.js +35 -17
  12. package/dist/commands/dom/a11y.d.ts +10 -0
  13. package/dist/commands/dom/a11y.js +29 -6
  14. package/dist/commands/dom/eval.d.ts +3 -1
  15. package/dist/commands/dom/eval.js +29 -4
  16. package/dist/commands/dom/form.js +16 -62
  17. package/dist/commands/dom/formInteraction.js +189 -119
  18. package/dist/commands/dom/formSummary.d.ts +49 -0
  19. package/dist/commands/dom/formSummary.js +180 -0
  20. package/dist/commands/dom/frames.d.ts +2 -1
  21. package/dist/commands/dom/frames.js +17 -2
  22. package/dist/commands/dom/get.d.ts +6 -5
  23. package/dist/commands/dom/get.js +92 -82
  24. package/dist/commands/dom/helpers/index.d.ts +1 -1
  25. package/dist/commands/dom/helpers/index.js +1 -1
  26. package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
  27. package/dist/commands/dom/helpers/keyAttributes.js +54 -0
  28. package/dist/commands/dom/helpers/query.d.ts +44 -17
  29. package/dist/commands/dom/helpers/query.js +300 -106
  30. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  31. package/dist/commands/dom/helpers/runElementCommand.js +98 -30
  32. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  33. package/dist/commands/dom/helpers/screenshot.js +239 -51
  34. package/dist/commands/dom/index.d.ts +4 -1
  35. package/dist/commands/dom/index.js +22 -7
  36. package/dist/commands/dom/inspect.d.ts +15 -0
  37. package/dist/commands/dom/inspect.js +82 -0
  38. package/dist/commands/dom/layout.d.ts +14 -0
  39. package/dist/commands/dom/layout.js +54 -0
  40. package/dist/commands/dom/listeners.d.ts +5 -1
  41. package/dist/commands/dom/listeners.js +15 -5
  42. package/dist/commands/dom/query.js +2 -3
  43. package/dist/commands/dom/screenshot.d.ts +12 -2
  44. package/dist/commands/dom/screenshot.js +27 -3
  45. package/dist/commands/dom/semanticUtils.d.ts +16 -10
  46. package/dist/commands/dom/semanticUtils.js +53 -16
  47. package/dist/commands/dom/wait.d.ts +13 -0
  48. package/dist/commands/dom/wait.js +83 -0
  49. package/dist/commands/helpJson.js +2 -2
  50. package/dist/commands/network/list.js +17 -13
  51. package/dist/commands/optionBehaviors.js +154 -21
  52. package/dist/commands/page.d.ts +3 -2
  53. package/dist/commands/page.js +100 -5
  54. package/dist/commands/peek.js +4 -11
  55. package/dist/commands/sessions.d.ts +8 -0
  56. package/dist/commands/sessions.js +19 -0
  57. package/dist/commands/shared/CommandRunner.js +4 -4
  58. package/dist/commands/shared/commonOptions.d.ts +4 -0
  59. package/dist/commands/shared/commonOptions.js +9 -0
  60. package/dist/commands/shared/dataFetcher.js +2 -2
  61. package/dist/commands/shared/followMode.d.ts +21 -1
  62. package/dist/commands/shared/followMode.js +29 -2
  63. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  64. package/dist/commands/shared/handleValidationError.js +12 -3
  65. package/dist/commands/shared/optionTypes.d.ts +61 -5
  66. package/dist/commands/shared/startHelpers.d.ts +66 -0
  67. package/dist/commands/shared/startHelpers.js +103 -13
  68. package/dist/commands/shared/validation.d.ts +14 -2
  69. package/dist/commands/shared/validation.js +20 -3
  70. package/dist/commands/start.d.ts +63 -0
  71. package/dist/commands/start.js +115 -15
  72. package/dist/commands/status.js +29 -7
  73. package/dist/commands/stop.js +7 -6
  74. package/dist/commands/tail.js +4 -11
  75. package/dist/commands/types.d.ts +2 -0
  76. package/dist/commands.js +2 -0
  77. package/dist/connection/chromeIdentity.d.ts +65 -0
  78. package/dist/connection/chromeIdentity.js +143 -0
  79. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  80. package/dist/connection/launcher/profilePreferences.js +151 -0
  81. package/dist/connection/launcher.d.ts +21 -2
  82. package/dist/connection/launcher.js +42 -16
  83. package/dist/connection/portReservation.d.ts +14 -4
  84. package/dist/connection/portReservation.js +21 -6
  85. package/dist/connection/startupExit.d.ts +8 -0
  86. package/dist/connection/startupExit.js +15 -6
  87. package/dist/constants.d.ts +6 -2
  88. package/dist/constants.js +9 -2
  89. package/dist/daemon/SessionController.js +23 -7
  90. package/dist/daemon/errors.d.ts +1 -1
  91. package/dist/daemon/errors.js +1 -1
  92. package/dist/daemon/launcher.d.ts +10 -2
  93. package/dist/daemon/launcher.js +8 -7
  94. package/dist/daemon/server/SocketServer.js +1 -2
  95. package/dist/daemon/session/Session.d.ts +20 -0
  96. package/dist/daemon/session/Session.js +80 -9
  97. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  98. package/dist/daemon/session/chromeConnection.js +45 -8
  99. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  100. package/dist/daemon/session/commandRegistry.js +113 -67
  101. package/dist/daemon/session/interactions.d.ts +48 -9
  102. package/dist/daemon/session/interactions.js +46 -9
  103. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  104. package/dist/daemon/session/triggeredRequests.js +157 -0
  105. package/dist/daemon/session/types.d.ts +5 -1
  106. package/dist/daemon.js +10630 -3601
  107. package/dist/errors/messages.d.ts +456 -24
  108. package/dist/errors/messages.js +862 -67
  109. package/dist/index.js +6915 -3401
  110. package/dist/ipc/client.d.ts +21 -1
  111. package/dist/ipc/client.js +35 -3
  112. package/dist/ipc/protocol/commands.d.ts +145 -5
  113. package/dist/ipc/protocol/commands.js +4 -0
  114. package/dist/ipc/protocol/domTypes.d.ts +291 -7
  115. package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
  116. package/dist/ipc/protocol/inspectTypes.js +10 -0
  117. package/dist/ipc/session/lifecycle.d.ts +8 -1
  118. package/dist/ipc/session/queries.d.ts +5 -1
  119. package/dist/ipc/session/types.d.ts +5 -0
  120. package/dist/ipc/transport/index.d.ts +2 -1
  121. package/dist/ipc/transport/index.js +2 -2
  122. package/dist/runtime/dom/actionEffects.d.ts +185 -0
  123. package/dist/runtime/dom/actionEffects.js +402 -0
  124. package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
  125. package/dist/runtime/dom/actionEffectsScripts.js +426 -0
  126. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  127. package/dist/runtime/dom/elementGeometry.js +553 -0
  128. package/dist/runtime/dom/elementInfo.d.ts +103 -0
  129. package/dist/runtime/dom/elementInfo.js +256 -0
  130. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  131. package/dist/runtime/dom/evalHelpers.js +136 -26
  132. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  133. package/dist/runtime/dom/eventListeners.js +184 -47
  134. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  135. package/dist/runtime/dom/formDiscovery.js +116 -16
  136. package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
  137. package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
  138. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  139. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  140. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  141. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  142. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  143. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  144. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  145. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  146. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  147. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  148. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  149. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  150. package/dist/runtime/dom/frameLayout.js +140 -0
  151. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  152. package/dist/runtime/dom/frameOrigin.js +62 -0
  153. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  154. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  155. package/dist/runtime/dom/frameSelection.d.ts +12 -1
  156. package/dist/runtime/dom/frameSelection.js +22 -3
  157. package/dist/runtime/dom/frames.d.ts +61 -5
  158. package/dist/runtime/dom/frames.js +329 -75
  159. package/dist/runtime/dom/inspect.d.ts +28 -0
  160. package/dist/runtime/dom/inspect.js +557 -0
  161. package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
  162. package/dist/runtime/dom/inspectAllStyles.js +385 -0
  163. package/dist/runtime/dom/inspectCascade.d.ts +94 -0
  164. package/dist/runtime/dom/inspectCascade.js +371 -0
  165. package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
  166. package/dist/runtime/dom/inspectCascadeModel.js +232 -0
  167. package/dist/runtime/dom/inspectHints.d.ts +62 -0
  168. package/dist/runtime/dom/inspectHints.js +305 -0
  169. package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
  170. package/dist/runtime/dom/inspectLayoutModel.js +346 -0
  171. package/dist/runtime/dom/inspectModel.d.ts +74 -0
  172. package/dist/runtime/dom/inspectModel.js +184 -0
  173. package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
  174. package/dist/runtime/dom/inspectPaintModel.js +461 -0
  175. package/dist/runtime/dom/inspectRules.d.ts +37 -0
  176. package/dist/runtime/dom/inspectRules.js +101 -0
  177. package/dist/runtime/dom/inspectScripts.d.ts +132 -0
  178. package/dist/runtime/dom/inspectScripts.js +263 -0
  179. package/dist/runtime/dom/inspectTree.d.ts +40 -0
  180. package/dist/runtime/dom/inspectTree.js +134 -0
  181. package/dist/runtime/dom/inspectVariables.d.ts +33 -0
  182. package/dist/runtime/dom/inspectVariables.js +94 -0
  183. package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
  184. package/dist/runtime/dom/inspectWhyModel.js +134 -0
  185. package/dist/runtime/dom/layout.d.ts +71 -0
  186. package/dist/runtime/dom/layout.js +340 -0
  187. package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
  188. package/dist/runtime/dom/listenerPageScripts.js +365 -0
  189. package/dist/runtime/dom/listenerSummary.d.ts +136 -11
  190. package/dist/runtime/dom/listenerSummary.js +361 -22
  191. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  192. package/dist/runtime/dom/pageActivity.js +123 -0
  193. package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
  194. package/dist/runtime/dom/reactEventHelpers.js +220 -41
  195. package/dist/runtime/dom/targetNode.d.ts +80 -27
  196. package/dist/runtime/dom/targetNode.js +249 -33
  197. package/dist/runtime/dom/wait.d.ts +25 -0
  198. package/dist/runtime/dom/wait.js +199 -0
  199. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  200. package/dist/runtime/dom/waitCondition.js +75 -0
  201. package/dist/runtime/page/emulation.d.ts +71 -0
  202. package/dist/runtime/page/emulation.js +117 -0
  203. package/dist/runtime/page/loadingState.d.ts +36 -0
  204. package/dist/runtime/page/loadingState.js +86 -0
  205. package/dist/runtime/page/navigation.d.ts +46 -2
  206. package/dist/runtime/page/navigation.js +69 -33
  207. package/dist/session/QueryCacheManager.d.ts +11 -1
  208. package/dist/session/QueryCacheManager.js +25 -3
  209. package/dist/session/chromeOwners.d.ts +34 -0
  210. package/dist/session/chromeOwners.js +51 -0
  211. package/dist/session/cleanup/staleSession.d.ts +11 -1
  212. package/dist/session/cleanup/staleSession.js +17 -6
  213. package/dist/session/cleanup/userCommands.js +2 -4
  214. package/dist/session/metadata.d.ts +5 -1
  215. package/dist/session/metadata.js +2 -1
  216. package/dist/session/paths.d.ts +77 -3
  217. package/dist/session/paths.js +111 -5
  218. package/dist/session/port.d.ts +31 -7
  219. package/dist/session/port.js +50 -43
  220. package/dist/session/portClaims.d.ts +66 -0
  221. package/dist/session/portClaims.js +284 -0
  222. package/dist/session/sessionList.d.ts +58 -0
  223. package/dist/session/sessionList.js +199 -0
  224. package/dist/session/sessionName.d.ts +46 -0
  225. package/dist/session/sessionName.js +97 -0
  226. package/dist/telemetry/a11y.d.ts +18 -3
  227. package/dist/telemetry/a11y.js +170 -29
  228. package/dist/telemetry/console.d.ts +1 -0
  229. package/dist/telemetry/console.js +100 -5
  230. package/dist/telemetry/network.js +3 -1
  231. package/dist/telemetry/requestKinds.d.ts +32 -0
  232. package/dist/telemetry/requestKinds.js +61 -0
  233. package/dist/telemetry/requestState.d.ts +31 -0
  234. package/dist/telemetry/requestState.js +38 -0
  235. package/dist/types.d.ts +112 -3
  236. package/dist/ui/formatters/a11y.js +3 -0
  237. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  238. package/dist/ui/formatters/console/chronological.js +17 -4
  239. package/dist/ui/formatters/console/json.js +3 -4
  240. package/dist/ui/formatters/console/shared.d.ts +12 -0
  241. package/dist/ui/formatters/console.d.ts +2 -2
  242. package/dist/ui/formatters/console.js +1 -1
  243. package/dist/ui/formatters/details.d.ts +8 -0
  244. package/dist/ui/formatters/details.js +61 -4
  245. package/dist/ui/formatters/dom.d.ts +27 -14
  246. package/dist/ui/formatters/dom.js +88 -59
  247. package/dist/ui/formatters/form.js +29 -18
  248. package/dist/ui/formatters/inspect.d.ts +39 -0
  249. package/dist/ui/formatters/inspect.js +596 -0
  250. package/dist/ui/formatters/keyAttributes.d.ts +19 -0
  251. package/dist/ui/formatters/keyAttributes.js +84 -0
  252. package/dist/ui/formatters/layout.d.ts +31 -0
  253. package/dist/ui/formatters/layout.js +53 -0
  254. package/dist/ui/formatters/listeners.d.ts +3 -2
  255. package/dist/ui/formatters/listeners.js +73 -9
  256. package/dist/ui/formatters/networkHeaders.d.ts +13 -0
  257. package/dist/ui/formatters/networkHeaders.js +36 -3
  258. package/dist/ui/formatters/networkList.d.ts +29 -1
  259. package/dist/ui/formatters/networkList.js +86 -20
  260. package/dist/ui/formatters/preview.js +2 -1
  261. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  262. package/dist/ui/formatters/requestStatus.js +2 -30
  263. package/dist/ui/formatters/sessions.d.ts +12 -0
  264. package/dist/ui/formatters/sessions.js +40 -0
  265. package/dist/ui/formatters/status.d.ts +21 -2
  266. package/dist/ui/formatters/status.js +47 -10
  267. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  268. package/dist/ui/formatters/triggeredRequests.js +65 -0
  269. package/dist/ui/formatting.d.ts +19 -0
  270. package/dist/ui/formatting.js +31 -36
  271. package/dist/ui/messages/chrome.d.ts +9 -0
  272. package/dist/ui/messages/chrome.js +17 -5
  273. package/dist/ui/messages/commands.d.ts +504 -14
  274. package/dist/ui/messages/commands.js +835 -21
  275. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  276. package/dist/ui/messages/consoleMessages.js +17 -0
  277. package/dist/ui/messages/hints.js +2 -1
  278. package/dist/ui/messages/networkMessages.d.ts +14 -0
  279. package/dist/ui/messages/networkMessages.js +18 -0
  280. package/dist/ui/messages/preview.js +5 -4
  281. package/dist/ui/messages/session.d.ts +30 -21
  282. package/dist/ui/messages/session.js +48 -26
  283. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  284. package/dist/ui/messages/sessionCommand.js +52 -0
  285. package/dist/utils/async.d.ts +17 -0
  286. package/dist/utils/async.js +36 -0
  287. package/dist/utils/color.d.ts +84 -0
  288. package/dist/utils/color.js +376 -0
  289. package/dist/utils/cssValues.d.ts +109 -0
  290. package/dist/utils/cssValues.js +236 -0
  291. package/dist/utils/http.d.ts +22 -1
  292. package/dist/utils/http.js +28 -9
  293. package/dist/utils/selectorFilters.d.ts +48 -8
  294. package/dist/utils/selectorFilters.js +296 -53
  295. package/dist/utils/shellDetection.d.ts +8 -2
  296. package/dist/utils/shellDetection.js +120 -33
  297. package/dist/utils/suggestions.d.ts +26 -0
  298. package/dist/utils/suggestions.js +73 -0
  299. package/dist/utils/taskMappings.js +10 -0
  300. package/dist/utils/url.d.ts +12 -2
  301. package/dist/utils/url.js +69 -7
  302. package/package.json +1 -1
  303. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  304. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -0,0 +1,199 @@
1
+ /**
2
+ * `bdg dom wait`: wait in the page until elements appear, become visible,
3
+ * contain a text or are gone, and/or the page has loaded.
4
+ *
5
+ * The page watches itself (a MutationObserver plus a short poll for style
6
+ * and frame changes the observer cannot see) and answers as soon as what it
7
+ * shows changes; the condition is decided here ({@link isWaitConditionMet}).
8
+ * Each page call lasts at most {@link WAIT_SLICE_MS}, so a navigation during
9
+ * the wait (the page's context is destroyed) only costs a retry on the new
10
+ * document. `--gone` is confirmed by a second snapshot of the same settled
11
+ * document, so the empty document right after a navigation does not count.
12
+ */
13
+ import { CommandError } from '../../errors/index.js';
14
+ import { invalidSelectorError, waitTimeoutError } from '../../errors/messages.js';
15
+ import { isContextLostError } from './evalHelpers.js';
16
+ import { DEEP_QUERY_JS, FILTER_MATCHING_JS, selectorArgsJS } from './targetNode.js';
17
+ import { isWaitConditionMet, needsGoneConfirmation, normalizeWaitText, } from './waitCondition.js';
18
+ import { createLogger } from '../../ui/logging/index.js';
19
+ import { delay, raceTimeout } from '../../utils/async.js';
20
+ import { getErrorMessage } from '../../utils/errors.js';
21
+ import { EXIT_CODES } from '../../utils/exitCodes.js';
22
+ import { filterDefined } from '../../utils/objects.js';
23
+ import { parseSelectorFilters } from '../../utils/selectorFilters.js';
24
+ const log = createLogger('dom');
25
+ /** Longest a single page call waits for a change */
26
+ const WAIT_SLICE_MS = 2000;
27
+ /** Pause before asking a page that could not answer (navigating) again */
28
+ const RETRY_DELAY_MS = 100;
29
+ /** Pause before the snapshot that confirms elements are gone */
30
+ const GONE_CONFIRM_DELAY_MS = 50;
31
+ /**
32
+ * Page-side: report what the page shows (matches, text matches, visible
33
+ * ones, readyState) as soon as it differs from `previous` (at once when
34
+ * `previous` is null), or after `sliceMs` without a change.
35
+ */
36
+ const WAIT_SNAPSHOT_JS = `async function (selector, parts, text, previous, sliceMs) {
37
+ const { passesAll } = (${FILTER_MATCHING_JS})([]);
38
+ const textFilter = text === null ? [] : [{ kind: 'has-text', text: text }];
39
+ const visibleFilter = [{ kind: 'visible' }];
40
+ const snapshot = () => {
41
+ const matches = selector === null ? [] : (${DEEP_QUERY_JS})(selector, parts);
42
+ const withText = matches.filter((el) => passesAll(el, textFilter));
43
+ return {
44
+ count: matches.length,
45
+ textCount: withText.length,
46
+ visibleCount: withText.filter((el) => passesAll(el, visibleFilter)).length,
47
+ readyState: document.readyState,
48
+ documentId: performance.timeOrigin
49
+ };
50
+ };
51
+ const changed = (s) => previous === null || s.count !== previous.count ||
52
+ s.textCount !== previous.textCount || s.visibleCount !== previous.visibleCount ||
53
+ s.readyState !== previous.readyState || s.documentId !== previous.documentId;
54
+ let current = snapshot();
55
+ if (changed(current)) return current;
56
+ return await new Promise((resolve) => {
57
+ let scheduled = null;
58
+ const observer = new MutationObserver(() => { if (scheduled === null) scheduled = setTimeout(check, 16); });
59
+ const poll = setInterval(check, 100);
60
+ const slice = setTimeout(finish, sliceMs);
61
+ function check() {
62
+ scheduled = null;
63
+ current = snapshot();
64
+ if (changed(current)) finish();
65
+ }
66
+ function finish() {
67
+ observer.disconnect();
68
+ clearInterval(poll);
69
+ clearTimeout(slice);
70
+ clearTimeout(scheduled);
71
+ document.removeEventListener('readystatechange', check);
72
+ resolve(current);
73
+ }
74
+ observer.observe(document, { childList: true, subtree: true, attributes: true, characterData: true });
75
+ document.addEventListener('readystatechange', check);
76
+ });
77
+ }`;
78
+ /**
79
+ * Wait until the page meets the condition.
80
+ *
81
+ * @param cdp - CDP connection
82
+ * @param params - Condition and timeout
83
+ * @returns What the page showed when it was met, and how long it took
84
+ * @throws CommandError (81) for an invalid selector, (102) when the timeout passed;
85
+ * CDP errors other than a lost page context (a closed connection) as they are
86
+ */
87
+ export async function waitForCondition(cdp, params) {
88
+ const condition = waitConditionOf(params);
89
+ const started = Date.now();
90
+ const deadline = started + params.timeout;
91
+ let last;
92
+ let confirming = false;
93
+ while (Date.now() < deadline) {
94
+ const snapshot = await nextSnapshot(cdp, condition, confirming ? null : (last ?? null), deadline);
95
+ if (!snapshot) {
96
+ confirming = false;
97
+ await delay(RETRY_DELAY_MS);
98
+ continue;
99
+ }
100
+ if (isWaitConditionMet(snapshot, condition, last)) {
101
+ return {
102
+ ...condition,
103
+ elapsedMs: Date.now() - started,
104
+ ...snapshotData(snapshot, condition),
105
+ };
106
+ }
107
+ last = snapshot;
108
+ confirming = needsGoneConfirmation(snapshot, condition);
109
+ if (confirming)
110
+ await delay(GONE_CONFIRM_DELAY_MS);
111
+ }
112
+ const err = waitTimeoutError(condition, last, params.timeout);
113
+ throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.CDP_TIMEOUT);
114
+ }
115
+ /**
116
+ * The condition of a request (options that are off left out).
117
+ *
118
+ * @param params - Request
119
+ * @returns Condition
120
+ */
121
+ function waitConditionOf(params) {
122
+ return {
123
+ ...filterDefined({ selector: params.selector, text: params.text }),
124
+ ...(params.gone && { gone: true }),
125
+ ...(params.visible && { visible: true }),
126
+ ...(params.load && { load: true }),
127
+ };
128
+ }
129
+ /**
130
+ * The snapshot as reported: `textCount` only when a text was given.
131
+ *
132
+ * @param snapshot - What the page showed
133
+ * @param condition - What was waited for
134
+ * @returns Snapshot fields of the result
135
+ */
136
+ function snapshotData(snapshot, condition) {
137
+ return {
138
+ count: snapshot.count,
139
+ ...(condition.text !== undefined && { textCount: snapshot.textCount }),
140
+ visibleCount: snapshot.visibleCount,
141
+ readyState: snapshot.readyState,
142
+ };
143
+ }
144
+ /**
145
+ * Ask the page for its next snapshot.
146
+ *
147
+ * @param cdp - CDP connection
148
+ * @param condition - What is waited for
149
+ * @param previous - Last snapshot (null for the first call)
150
+ * @param deadline - When the wait ends (epoch ms)
151
+ * @returns The snapshot, or undefined when the page could not answer (its context was lost
152
+ * to a navigation, or the time ran out)
153
+ * @throws CommandError (81) for an invalid selector; other CDP errors (a closed connection) as they are
154
+ */
155
+ async function nextSnapshot(cdp, condition, previous, deadline) {
156
+ const remaining = deadline - Date.now();
157
+ const selectorArgs = condition.selector === undefined ? 'null, null' : selectorArgsJS(condition.selector);
158
+ const text = condition.text === undefined ? null : normalizeWaitText(condition.text);
159
+ const args = `${selectorArgs}, ${JSON.stringify(text)}, ${JSON.stringify(previous)}, ${Math.min(remaining, WAIT_SLICE_MS)}`;
160
+ const evaluated = cdp.send('Runtime.evaluate', {
161
+ expression: `(${WAIT_SNAPSHOT_JS})(${args})`,
162
+ awaitPromise: true,
163
+ returnByValue: true,
164
+ });
165
+ evaluated.catch(() => undefined);
166
+ const response = await raceTimeout(evaluated, remaining).catch((error) => {
167
+ if (!isContextLostError(error))
168
+ throw error;
169
+ log.debug(`dom wait: page context lost (${getErrorMessage(error)}), retrying`);
170
+ return undefined;
171
+ });
172
+ if (!response)
173
+ return undefined;
174
+ if (response.exceptionDetails)
175
+ return pageException(response.exceptionDetails, condition);
176
+ return response.result.value;
177
+ }
178
+ /**
179
+ * Handle an exception of the page script: an invalid selector is the
180
+ * user's; anything else (a document being replaced) is retried.
181
+ *
182
+ * @param details - Exception details
183
+ * @param condition - What is waited for
184
+ * @returns undefined (retry)
185
+ * @throws CommandError (81) for an invalid selector
186
+ */
187
+ function pageException(details, condition) {
188
+ const description = details.exception?.description ?? details.text;
189
+ if (condition.selector !== undefined && description.startsWith('SyntaxError')) {
190
+ const detail = parseSelectorFilters(condition.selector)
191
+ ? undefined
192
+ : description.split('\n')[0];
193
+ const err = invalidSelectorError(condition.selector, detail);
194
+ throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.INVALID_ARGUMENTS);
195
+ }
196
+ log.debug(`dom wait: page script failed (${description.split('\n')[0]}), retrying`);
197
+ return undefined;
198
+ }
199
+ //# sourceMappingURL=wait.js.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * What `bdg dom wait` waits for, and whether what the page shows meets it.
3
+ *
4
+ * The page reports a {@link WaitSnapshot} whenever it changes; the condition
5
+ * is decided here, in one place.
6
+ */
7
+ /** What to wait for */
8
+ export interface WaitCondition {
9
+ /** Selector (filters like :has-text and :visible allowed); absent when only waiting for the load */
10
+ selector?: string;
11
+ /** Text one of the matches must contain (case-insensitive, whitespace collapsed) */
12
+ text?: string;
13
+ /** Wait for the (visible, with `visible`) matches to be gone */
14
+ gone?: boolean;
15
+ /** Only count visible matches */
16
+ visible?: boolean;
17
+ /** Also wait for `document.readyState` to be `complete` */
18
+ load?: boolean;
19
+ }
20
+ /** What the page shows at one moment */
21
+ export interface WaitSnapshot {
22
+ /** Elements matching the selector */
23
+ count: number;
24
+ /** Of those, the ones containing the text (all of them without a text) */
25
+ textCount: number;
26
+ /** Of the text matches, the visible ones */
27
+ visibleCount: number;
28
+ /** `document.readyState` */
29
+ readyState: string;
30
+ /** The document's identity (`performance.timeOrigin`): a new document after a navigation has another */
31
+ documentId: number;
32
+ }
33
+ /**
34
+ * The text as the page compares it: whitespace collapsed, lower case (like `:has-text`).
35
+ *
36
+ * @param text - Text as given
37
+ * @returns Normalized text
38
+ */
39
+ export declare function normalizeWaitText(text: string): string;
40
+ /**
41
+ * The matches the condition counts: visible ones with `visible`, else those
42
+ * containing the text (all matches without a text).
43
+ *
44
+ * @param snapshot - What the page shows
45
+ * @param condition - What is waited for
46
+ * @returns Number of counted matches
47
+ */
48
+ export declare function countedMatches(snapshot: WaitSnapshot, condition: WaitCondition): number;
49
+ /**
50
+ * Whether the page shows what is waited for.
51
+ *
52
+ * Elements are gone only when two consecutive snapshots of the same
53
+ * document, neither of it still `loading`, show none: right after a
54
+ * navigation commits, the new document is empty for a moment.
55
+ *
56
+ * @param snapshot - What the page shows
57
+ * @param condition - What is waited for
58
+ * @param previous - The snapshot before it, if any
59
+ * @returns True when the elements are there (or gone with `gone`) and, with `load`, the page loaded
60
+ */
61
+ export declare function isWaitConditionMet(snapshot: WaitSnapshot, condition: WaitCondition, previous?: WaitSnapshot): boolean;
62
+ /**
63
+ * Whether a `--gone` wait should confirm this snapshot with another one: it
64
+ * shows no (counted) matches in a document past `loading`.
65
+ *
66
+ * @param snapshot - What the page shows
67
+ * @param condition - What is waited for
68
+ * @returns True when one more snapshot of the same document may meet the condition
69
+ */
70
+ export declare function needsGoneConfirmation(snapshot: WaitSnapshot, condition: WaitCondition): boolean;
71
+ //# sourceMappingURL=waitCondition.d.ts.map
@@ -0,0 +1,75 @@
1
+ /**
2
+ * What `bdg dom wait` waits for, and whether what the page shows meets it.
3
+ *
4
+ * The page reports a {@link WaitSnapshot} whenever it changes; the condition
5
+ * is decided here, in one place.
6
+ */
7
+ /**
8
+ * The text as the page compares it: whitespace collapsed, lower case (like `:has-text`).
9
+ *
10
+ * @param text - Text as given
11
+ * @returns Normalized text
12
+ */
13
+ export function normalizeWaitText(text) {
14
+ return text.replace(/\s+/g, ' ').trim().toLowerCase();
15
+ }
16
+ /**
17
+ * The matches the condition counts: visible ones with `visible`, else those
18
+ * containing the text (all matches without a text).
19
+ *
20
+ * @param snapshot - What the page shows
21
+ * @param condition - What is waited for
22
+ * @returns Number of counted matches
23
+ */
24
+ export function countedMatches(snapshot, condition) {
25
+ return condition.visible ? snapshot.visibleCount : snapshot.textCount;
26
+ }
27
+ /**
28
+ * Whether the page shows what is waited for.
29
+ *
30
+ * Elements are gone only when two consecutive snapshots of the same
31
+ * document, neither of it still `loading`, show none: right after a
32
+ * navigation commits, the new document is empty for a moment.
33
+ *
34
+ * @param snapshot - What the page shows
35
+ * @param condition - What is waited for
36
+ * @param previous - The snapshot before it, if any
37
+ * @returns True when the elements are there (or gone with `gone`) and, with `load`, the page loaded
38
+ */
39
+ export function isWaitConditionMet(snapshot, condition, previous) {
40
+ if (condition.load && snapshot.readyState !== 'complete')
41
+ return false;
42
+ if (condition.selector === undefined)
43
+ return true;
44
+ if (!condition.gone)
45
+ return countedMatches(snapshot, condition) > 0;
46
+ if (previous?.documentId !== snapshot.documentId)
47
+ return false;
48
+ return showsNoneSettled(previous, condition) && showsNoneSettled(snapshot, condition);
49
+ }
50
+ /**
51
+ * Whether a `--gone` wait should confirm this snapshot with another one: it
52
+ * shows no (counted) matches in a document past `loading`.
53
+ *
54
+ * @param snapshot - What the page shows
55
+ * @param condition - What is waited for
56
+ * @returns True when one more snapshot of the same document may meet the condition
57
+ */
58
+ export function needsGoneConfirmation(snapshot, condition) {
59
+ if (!condition.gone || condition.selector === undefined)
60
+ return false;
61
+ if (condition.load && snapshot.readyState !== 'complete')
62
+ return false;
63
+ return showsNoneSettled(snapshot, condition);
64
+ }
65
+ /**
66
+ * No counted matches, in a document that is no longer `loading`.
67
+ *
68
+ * @param snapshot - What the page shows
69
+ * @param condition - What is waited for
70
+ * @returns True when nothing counted matches in a settled document
71
+ */
72
+ function showsNoneSettled(snapshot, condition) {
73
+ return snapshot.readyState !== 'loading' && countedMatches(snapshot, condition) === 0;
74
+ }
75
+ //# sourceMappingURL=waitCondition.js.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Page emulation a session was started with: the viewport size
3
+ * (`--viewport`) and `prefers-color-scheme` (`--color-scheme`).
4
+ *
5
+ * The overrides belong to the session's CDP connection: they last across
6
+ * navigations and reloads, and Chrome drops them when the session ends, so
7
+ * an attached Chrome (`--chrome-ws-url`) gets its own settings back.
8
+ */
9
+ import type { CDPConnection } from '../../connection/cdp.js';
10
+ import type { ColorScheme, ViewportSize } from '../../types.js';
11
+ /**
12
+ * `Emulation.setDeviceMetricsOverride` parameters for a session viewport: a
13
+ * desktop viewport of that size at the display's own pixel ratio.
14
+ *
15
+ * @param viewport - Viewport size in CSS px
16
+ * @param deviceScaleFactor - Pixel ratio (0 keeps the display's)
17
+ * @returns CDP parameters
18
+ */
19
+ export declare function viewportOverride(viewport: ViewportSize, deviceScaleFactor?: number): {
20
+ width: number;
21
+ height: number;
22
+ deviceScaleFactor: number;
23
+ mobile: false;
24
+ };
25
+ /**
26
+ * Apply the session's emulation to its page.
27
+ *
28
+ * @param cdp - Session connection
29
+ * @param emulation - Viewport and color scheme, when given at start
30
+ */
31
+ export declare function applySessionEmulation(cdp: CDPConnection, emulation: {
32
+ viewport?: ViewportSize;
33
+ colorScheme?: ColorScheme;
34
+ }): Promise<void>;
35
+ /** Page emulation of a session: what `--viewport` and `--color-scheme` set */
36
+ export interface SessionEmulation {
37
+ viewport?: ViewportSize;
38
+ colorScheme?: ColorScheme;
39
+ }
40
+ /**
41
+ * Change the page emulation mid-session (`bdg page emulate`): set the
42
+ * viewport or the color scheme, or clear both (back to the browser window
43
+ * and the system setting).
44
+ *
45
+ * @param cdp - Session connection
46
+ * @param current - Emulation now in effect
47
+ * @param change - What to set, or `reset`
48
+ * @param record - Called after each change Chrome accepted (so a later
49
+ * failure leaves the recorded emulation true)
50
+ * @returns Emulation in effect afterwards
51
+ */
52
+ export declare function emulatePage(cdp: CDPConnection, current: SessionEmulation, change: SessionEmulation & {
53
+ reset?: boolean;
54
+ }, record: (emulation: SessionEmulation) => void): Promise<SessionEmulation>;
55
+ /** What the page currently renders with, for `bdg status` */
56
+ export interface PageAppearance {
57
+ /** Layout viewport without scrollbars (as `dom layout` reports it) */
58
+ viewport?: ViewportSize;
59
+ /** `prefers-color-scheme` the page sees */
60
+ colorScheme?: ColorScheme;
61
+ }
62
+ /**
63
+ * The viewport and color scheme the page renders with. A busy page (or one
64
+ * still navigating) does not answer within {@link APPEARANCE_TIMEOUT_MS}; then
65
+ * nothing is reported rather than holding up `bdg status`.
66
+ *
67
+ * @param cdp - Session connection
68
+ * @returns Viewport and color scheme, or nothing
69
+ */
70
+ export declare function pageAppearance(cdp: CDPConnection): Promise<PageAppearance>;
71
+ //# sourceMappingURL=emulation.d.ts.map
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Page emulation a session was started with: the viewport size
3
+ * (`--viewport`) and `prefers-color-scheme` (`--color-scheme`).
4
+ *
5
+ * The overrides belong to the session's CDP connection: they last across
6
+ * navigations and reloads, and Chrome drops them when the session ends, so
7
+ * an attached Chrome (`--chrome-ws-url`) gets its own settings back.
8
+ */
9
+ import { VIEWPORT_SIZE_JS } from '../dom/elementGeometry.js';
10
+ import { createLogger } from '../../ui/logging/index.js';
11
+ import { getErrorMessage } from '../../utils/errors.js';
12
+ const log = createLogger('session');
13
+ /**
14
+ * `Emulation.setDeviceMetricsOverride` parameters for a session viewport: a
15
+ * desktop viewport of that size at the display's own pixel ratio.
16
+ *
17
+ * @param viewport - Viewport size in CSS px
18
+ * @param deviceScaleFactor - Pixel ratio (0 keeps the display's)
19
+ * @returns CDP parameters
20
+ */
21
+ export function viewportOverride(viewport, deviceScaleFactor = 0) {
22
+ return { width: viewport.width, height: viewport.height, deviceScaleFactor, mobile: false };
23
+ }
24
+ /**
25
+ * Apply the session's emulation to its page.
26
+ *
27
+ * @param cdp - Session connection
28
+ * @param emulation - Viewport and color scheme, when given at start
29
+ */
30
+ export async function applySessionEmulation(cdp, emulation) {
31
+ if (emulation.viewport) {
32
+ await cdp.send('Emulation.setDeviceMetricsOverride', viewportOverride(emulation.viewport));
33
+ }
34
+ if (emulation.colorScheme) {
35
+ await cdp.send('Emulation.setEmulatedMedia', {
36
+ features: [{ name: 'prefers-color-scheme', value: emulation.colorScheme }],
37
+ });
38
+ }
39
+ }
40
+ /**
41
+ * Change the page emulation mid-session (`bdg page emulate`): set the
42
+ * viewport or the color scheme, or clear both (back to the browser window
43
+ * and the system setting).
44
+ *
45
+ * @param cdp - Session connection
46
+ * @param current - Emulation now in effect
47
+ * @param change - What to set, or `reset`
48
+ * @param record - Called after each change Chrome accepted (so a later
49
+ * failure leaves the recorded emulation true)
50
+ * @returns Emulation in effect afterwards
51
+ */
52
+ export async function emulatePage(cdp, current, change, record) {
53
+ let state = current;
54
+ const step = async (send, next) => {
55
+ await send();
56
+ state = next;
57
+ record(state);
58
+ };
59
+ const { viewport: _viewport, colorScheme, ...rest } = state;
60
+ if (change.reset || change.viewport) {
61
+ await step(() => change.viewport
62
+ ? cdp.send('Emulation.setDeviceMetricsOverride', viewportOverride(change.viewport))
63
+ : cdp.send('Emulation.clearDeviceMetricsOverride', {}), {
64
+ ...rest,
65
+ ...(colorScheme && { colorScheme }),
66
+ ...(change.viewport && { viewport: change.viewport }),
67
+ });
68
+ }
69
+ if (change.reset || change.colorScheme) {
70
+ const { colorScheme: _scheme, ...withoutScheme } = state;
71
+ await step(() => cdp.send('Emulation.setEmulatedMedia', {
72
+ features: [{ name: 'prefers-color-scheme', value: change.colorScheme ?? '' }],
73
+ }), { ...withoutScheme, ...(change.colorScheme && { colorScheme: change.colorScheme }) });
74
+ }
75
+ return state;
76
+ }
77
+ /** How long `bdg status` waits for the page to report its appearance */
78
+ const APPEARANCE_TIMEOUT_MS = 1000;
79
+ /**
80
+ * The viewport and color scheme the page renders with. A busy page (or one
81
+ * still navigating) does not answer within {@link APPEARANCE_TIMEOUT_MS}; then
82
+ * nothing is reported rather than holding up `bdg status`.
83
+ *
84
+ * @param cdp - Session connection
85
+ * @returns Viewport and color scheme, or nothing
86
+ */
87
+ export async function pageAppearance(cdp) {
88
+ const expression = `(() => {
89
+ const size = (${VIEWPORT_SIZE_JS})(window);
90
+ return { width: Math.round(size.width), height: Math.round(size.height), dark: matchMedia('(prefers-color-scheme: dark)').matches };
91
+ })()`;
92
+ let timer;
93
+ const timeout = new Promise((resolve) => {
94
+ timer = setTimeout(() => resolve(null), APPEARANCE_TIMEOUT_MS);
95
+ });
96
+ try {
97
+ const response = (await Promise.race([
98
+ cdp.send('Runtime.evaluate', { expression, returnByValue: true }),
99
+ timeout,
100
+ ]));
101
+ const value = response?.result?.value;
102
+ if (!value)
103
+ return {};
104
+ return {
105
+ viewport: { width: value.width, height: value.height },
106
+ colorScheme: value.dark ? 'dark' : 'light',
107
+ };
108
+ }
109
+ catch (error) {
110
+ log.debug(`Could not read the page's viewport and color scheme: ${getErrorMessage(error)}`);
111
+ return {};
112
+ }
113
+ finally {
114
+ clearTimeout(timer);
115
+ }
116
+ }
117
+ //# sourceMappingURL=emulation.js.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Whether the page finished loading, and what it is still waiting for.
3
+ *
4
+ * Start and `bdg page` wait a limited time for the page; a document still
5
+ * `loading` after that (a script whose server never answers) makes every
6
+ * later command misleading, so they report it with the requests still
7
+ * running.
8
+ */
9
+ import type { PendingRequestInfo, PageLoadingState } from '../../ipc/protocol/commands.js';
10
+ import type { PendingRequest } from '../../telemetry/network.js';
11
+ import type { CDPSender } from '../../telemetry/objectExpander.js';
12
+ /**
13
+ * The requests to name: load-blocking ones (scripts, styles, images, frames)
14
+ * first, the longest-running first within each group.
15
+ *
16
+ * @param pending - Requests still running
17
+ * @param now - Current time (ms)
18
+ * @returns Up to {@link MAX_NAMED_PENDING_REQUESTS} requests
19
+ */
20
+ export declare function summarizePendingRequests(pending: Iterable<PendingRequest>, now: number): PendingRequestInfo[];
21
+ /**
22
+ * The page's `document.readyState`.
23
+ *
24
+ * @param cdp - CDP connection
25
+ * @returns The state, or undefined when the page did not answer in time
26
+ */
27
+ export declare function readDocumentReadyState(cdp: CDPSender): Promise<string | undefined>;
28
+ /**
29
+ * What the page is still loading, if it has not finished.
30
+ *
31
+ * @param cdp - CDP connection
32
+ * @param pending - Requests still running (from the session's network telemetry)
33
+ * @returns The loading state, or undefined when the document is complete or did not answer
34
+ */
35
+ export declare function readPageLoadingState(cdp: CDPSender, pending: Iterable<PendingRequest>): Promise<PageLoadingState | undefined>;
36
+ //# sourceMappingURL=loadingState.d.ts.map
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Whether the page finished loading, and what it is still waiting for.
3
+ *
4
+ * Start and `bdg page` wait a limited time for the page; a document still
5
+ * `loading` after that (a script whose server never answers) makes every
6
+ * later command misleading, so they report it with the requests still
7
+ * running.
8
+ */
9
+ import { createLogger } from '../../ui/logging/index.js';
10
+ import { raceTimeout } from '../../utils/async.js';
11
+ import { getErrorMessage } from '../../utils/errors.js';
12
+ const log = createLogger('readiness');
13
+ /** Pending requests named in the report */
14
+ const MAX_NAMED_PENDING_REQUESTS = 3;
15
+ /** How long the page gets to report its readyState (a busy page is not waited on) */
16
+ const READY_STATE_TIMEOUT_MS = 1000;
17
+ /** Request types that never hold up the load event, listed after the ones that do */
18
+ const NON_BLOCKING_TYPES = new Set([
19
+ 'XHR',
20
+ 'Fetch',
21
+ 'EventSource',
22
+ 'Ping',
23
+ 'Preflight',
24
+ 'Prefetch',
25
+ ]);
26
+ /**
27
+ * The requests to name: load-blocking ones (scripts, styles, images, frames)
28
+ * first, the longest-running first within each group.
29
+ *
30
+ * @param pending - Requests still running
31
+ * @param now - Current time (ms)
32
+ * @returns Up to {@link MAX_NAMED_PENDING_REQUESTS} requests
33
+ */
34
+ export function summarizePendingRequests(pending, now) {
35
+ const rank = (entry) => NON_BLOCKING_TYPES.has(entry.request.resourceType ?? '') ? 1 : 0;
36
+ return [...pending]
37
+ .sort((a, b) => rank(a) - rank(b) || a.request.timestamp - b.request.timestamp)
38
+ .slice(0, MAX_NAMED_PENDING_REQUESTS)
39
+ .map(({ request }) => ({
40
+ method: request.method,
41
+ url: request.url,
42
+ ...(request.resourceType && { resourceType: request.resourceType }),
43
+ pendingMs: Math.max(0, now - request.timestamp),
44
+ }));
45
+ }
46
+ /**
47
+ * The page's `document.readyState`.
48
+ *
49
+ * @param cdp - CDP connection
50
+ * @returns The state, or undefined when the page did not answer in time
51
+ */
52
+ export async function readDocumentReadyState(cdp) {
53
+ try {
54
+ const evaluated = cdp.send('Runtime.evaluate', {
55
+ expression: 'document.readyState',
56
+ returnByValue: true,
57
+ });
58
+ evaluated.catch(() => undefined);
59
+ const response = await raceTimeout(evaluated, READY_STATE_TIMEOUT_MS);
60
+ const value = response?.result?.value;
61
+ return typeof value === 'string' ? value : undefined;
62
+ }
63
+ catch (error) {
64
+ log.debug(`Could not read document.readyState: ${getErrorMessage(error)}`);
65
+ return undefined;
66
+ }
67
+ }
68
+ /**
69
+ * What the page is still loading, if it has not finished.
70
+ *
71
+ * @param cdp - CDP connection
72
+ * @param pending - Requests still running (from the session's network telemetry)
73
+ * @returns The loading state, or undefined when the document is complete or did not answer
74
+ */
75
+ export async function readPageLoadingState(cdp, pending) {
76
+ const readyState = await readDocumentReadyState(cdp);
77
+ if (readyState === undefined || readyState === 'complete')
78
+ return undefined;
79
+ const requests = [...pending];
80
+ return {
81
+ readyState,
82
+ pending: summarizePendingRequests(requests, Date.now()),
83
+ pendingCount: requests.length,
84
+ };
85
+ }
86
+ //# sourceMappingURL=loadingState.js.map