browser-debugger-cli 0.11.0 → 0.13.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 (222) hide show
  1. package/.claude/skills/bdg/SKILL.md +4 -4
  2. package/README.md +143 -79
  3. package/dist/commands/cdp.d.ts +22 -1
  4. package/dist/commands/cdp.js +100 -43
  5. package/dist/commands/console.d.ts +12 -0
  6. package/dist/commands/console.js +62 -12
  7. package/dist/commands/css.d.ts +13 -0
  8. package/dist/commands/css.js +53 -0
  9. package/dist/commands/dom/DomElementResolver.d.ts +3 -1
  10. package/dist/commands/dom/DomElementResolver.js +10 -3
  11. package/dist/commands/dom/a11y.js +3 -2
  12. package/dist/commands/dom/audit.d.ts +14 -0
  13. package/dist/commands/dom/audit.js +87 -0
  14. package/dist/commands/dom/eval.d.ts +3 -2
  15. package/dist/commands/dom/eval.js +11 -5
  16. package/dist/commands/dom/form.js +10 -9
  17. package/dist/commands/dom/formInteraction.js +42 -11
  18. package/dist/commands/dom/get.js +8 -8
  19. package/dist/commands/dom/helpers/index.d.ts +1 -1
  20. package/dist/commands/dom/helpers/index.js +1 -1
  21. package/dist/commands/dom/helpers/keyAttributes.d.ts +3 -2
  22. package/dist/commands/dom/helpers/keyAttributes.js +6 -4
  23. package/dist/commands/dom/helpers/query.d.ts +27 -3
  24. package/dist/commands/dom/helpers/query.js +152 -64
  25. package/dist/commands/dom/helpers/screenshot.d.ts +1 -0
  26. package/dist/commands/dom/helpers/screenshot.js +169 -49
  27. package/dist/commands/dom/index.js +7 -2
  28. package/dist/commands/dom/query.d.ts +19 -2
  29. package/dist/commands/dom/query.js +37 -6
  30. package/dist/commands/dom/screenshot.js +12 -7
  31. package/dist/commands/dom/semanticUtils.d.ts +3 -2
  32. package/dist/commands/dom/semanticUtils.js +40 -9
  33. package/dist/commands/dom/wait.js +5 -3
  34. package/dist/commands/helpJson.d.ts +82 -19
  35. package/dist/commands/helpJson.js +112 -41
  36. package/dist/commands/helpTopic.d.ts +16 -1
  37. package/dist/commands/helpTopic.js +59 -1
  38. package/dist/commands/installSkill.d.ts +15 -5
  39. package/dist/commands/installSkill.js +86 -16
  40. package/dist/commands/network/list.js +22 -12
  41. package/dist/commands/optionBehaviors.js +53 -16
  42. package/dist/commands/page.js +7 -4
  43. package/dist/commands/peek.d.ts +7 -0
  44. package/dist/commands/peek.js +65 -23
  45. package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
  46. package/dist/commands/shared/daemonErrorHandler.js +20 -9
  47. package/dist/commands/shared/dataFetcher.d.ts +12 -4
  48. package/dist/commands/shared/dataFetcher.js +12 -4
  49. package/dist/commands/shared/followMode.d.ts +9 -1
  50. package/dist/commands/shared/followMode.js +22 -4
  51. package/dist/commands/shared/optionTypes.d.ts +9 -2
  52. package/dist/commands/shared/outputFile.js +6 -1
  53. package/dist/commands/start.d.ts +20 -5
  54. package/dist/commands/start.js +84 -23
  55. package/dist/commands/stop.d.ts +11 -0
  56. package/dist/commands/stop.js +24 -1
  57. package/dist/commands/tail.d.ts +7 -1
  58. package/dist/commands/tail.js +13 -62
  59. package/dist/commands.js +2 -0
  60. package/dist/connection/cdp.d.ts +7 -0
  61. package/dist/connection/cdp.js +9 -0
  62. package/dist/connection/launcher.js +3 -2
  63. package/dist/daemon/SessionController.js +6 -1
  64. package/dist/daemon/launcher.d.ts +3 -2
  65. package/dist/daemon/launcher.js +47 -3
  66. package/dist/daemon/session/Session.d.ts +4 -1
  67. package/dist/daemon/session/Session.js +33 -2
  68. package/dist/daemon/session/TelemetryStore.d.ts +8 -1
  69. package/dist/daemon/session/TelemetryStore.js +13 -1
  70. package/dist/daemon/session/commandRegistry.js +36 -14
  71. package/dist/daemon/session/interactions.d.ts +2 -1
  72. package/dist/daemon/session/interactions.js +13 -1
  73. package/dist/daemon/session/plugins.js +19 -53
  74. package/dist/daemon/session/teardown.js +1 -1
  75. package/dist/daemon.js +9234 -7222
  76. package/dist/errors/messages.d.ts +88 -15
  77. package/dist/errors/messages.js +177 -27
  78. package/dist/index.js +19322 -13961
  79. package/dist/ipc/client.d.ts +22 -2
  80. package/dist/ipc/client.js +34 -5
  81. package/dist/ipc/protocol/auditTypes.d.ts +135 -0
  82. package/dist/ipc/protocol/auditTypes.js +6 -0
  83. package/dist/ipc/protocol/commands.d.ts +35 -0
  84. package/dist/ipc/protocol/commands.js +2 -0
  85. package/dist/ipc/protocol/domTypes.d.ts +16 -0
  86. package/dist/ipc/protocol/inspectTypes.d.ts +73 -8
  87. package/dist/ipc/session/types.d.ts +2 -0
  88. package/dist/runtime/css/search.d.ts +39 -0
  89. package/dist/runtime/css/search.js +122 -0
  90. package/dist/runtime/dom/actionEffects.d.ts +9 -2
  91. package/dist/runtime/dom/actionEffects.js +30 -14
  92. package/dist/runtime/dom/audit.d.ts +19 -0
  93. package/dist/runtime/dom/audit.js +37 -0
  94. package/dist/runtime/dom/auditModel.d.ts +45 -0
  95. package/dist/runtime/dom/auditModel.js +220 -0
  96. package/dist/runtime/dom/auditScripts.d.ts +113 -0
  97. package/dist/runtime/dom/auditScripts.js +148 -0
  98. package/dist/runtime/dom/elementGeometry.d.ts +16 -3
  99. package/dist/runtime/dom/elementGeometry.js +49 -10
  100. package/dist/runtime/dom/elementInfo.d.ts +74 -17
  101. package/dist/runtime/dom/elementInfo.js +187 -34
  102. package/dist/runtime/dom/evalHelpers.d.ts +12 -2
  103. package/dist/runtime/dom/evalHelpers.js +67 -7
  104. package/dist/runtime/dom/formDiscovery.d.ts +6 -2
  105. package/dist/runtime/dom/formDiscovery.js +20 -3
  106. package/dist/runtime/dom/formFillHelpers/fill.js +8 -12
  107. package/dist/runtime/dom/formFillHelpers/pressKey.js +2 -2
  108. package/dist/runtime/dom/formFillHelpers/shared.d.ts +16 -10
  109. package/dist/runtime/dom/formFillHelpers/shared.js +19 -52
  110. package/dist/runtime/dom/formSubmitHelpers.js +4 -3
  111. package/dist/runtime/dom/frameLayout.js +1 -0
  112. package/dist/runtime/dom/inspect.d.ts +7 -0
  113. package/dist/runtime/dom/inspect.js +92 -28
  114. package/dist/runtime/dom/inspectAllStyles.d.ts +16 -4
  115. package/dist/runtime/dom/inspectAllStyles.js +90 -7
  116. package/dist/runtime/dom/inspectCascade.d.ts +19 -2
  117. package/dist/runtime/dom/inspectCascade.js +214 -44
  118. package/dist/runtime/dom/inspectCascadeModel.d.ts +8 -0
  119. package/dist/runtime/dom/inspectCascadeModel.js +108 -34
  120. package/dist/runtime/dom/inspectHints.d.ts +26 -3
  121. package/dist/runtime/dom/inspectHints.js +125 -9
  122. package/dist/runtime/dom/inspectModel.d.ts +5 -1
  123. package/dist/runtime/dom/inspectModel.js +37 -10
  124. package/dist/runtime/dom/inspectPaintModel.d.ts +50 -22
  125. package/dist/runtime/dom/inspectPaintModel.js +182 -68
  126. package/dist/runtime/dom/inspectRules.d.ts +19 -0
  127. package/dist/runtime/dom/inspectRules.js +21 -5
  128. package/dist/runtime/dom/inspectScripts.d.ts +112 -12
  129. package/dist/runtime/dom/inspectScripts.js +357 -32
  130. package/dist/runtime/dom/inspectTree.js +10 -2
  131. package/dist/runtime/dom/inspectWhyModel.d.ts +2 -1
  132. package/dist/runtime/dom/inspectWhyModel.js +52 -10
  133. package/dist/runtime/dom/layout.js +40 -16
  134. package/dist/runtime/dom/reactEventHelpers.d.ts +21 -4
  135. package/dist/runtime/dom/reactEventHelpers.js +90 -36
  136. package/dist/runtime/dom/targetNode.d.ts +18 -5
  137. package/dist/runtime/dom/targetNode.js +268 -8
  138. package/dist/runtime/dom/wait.js +2 -1
  139. package/dist/runtime/page/bdgWorld.d.ts +57 -0
  140. package/dist/runtime/page/bdgWorld.js +180 -0
  141. package/dist/runtime/page/emulation.d.ts +13 -4
  142. package/dist/runtime/page/emulation.js +69 -4
  143. package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
  144. package/dist/runtime/page/replacedBuiltins.js +136 -0
  145. package/dist/runtime/page/userAgent.d.ts +17 -0
  146. package/dist/runtime/page/userAgent.js +57 -0
  147. package/dist/session/QueryCacheManager.d.ts +4 -1
  148. package/dist/session/QueryCacheManager.js +5 -2
  149. package/dist/session/chrome.d.ts +4 -1
  150. package/dist/session/chrome.js +7 -1
  151. package/dist/session/cleanup/staleSession.d.ts +21 -4
  152. package/dist/session/cleanup/staleSession.js +79 -9
  153. package/dist/session/cleanup/userCommands.d.ts +4 -1
  154. package/dist/session/cleanup/userCommands.js +10 -5
  155. package/dist/session/daemonSocket.d.ts +10 -0
  156. package/dist/session/daemonSocket.js +22 -0
  157. package/dist/session/lastSession.d.ts +6 -3
  158. package/dist/session/lastSession.js +11 -5
  159. package/dist/session/paths.d.ts +3 -1
  160. package/dist/session/paths.js +5 -5
  161. package/dist/session/portClaims.js +4 -3
  162. package/dist/session/sessionList.d.ts +13 -5
  163. package/dist/session/sessionList.js +31 -7
  164. package/dist/telemetry/a11y.js +2 -2
  165. package/dist/telemetry/console.d.ts +2 -1
  166. package/dist/telemetry/console.js +30 -21
  167. package/dist/telemetry/pageCrash.d.ts +26 -0
  168. package/dist/telemetry/pageCrash.js +53 -0
  169. package/dist/types.d.ts +20 -0
  170. package/dist/ui/formatters/audit.d.ts +19 -0
  171. package/dist/ui/formatters/audit.js +115 -0
  172. package/dist/ui/formatters/cdp.d.ts +138 -0
  173. package/dist/ui/formatters/cdp.js +131 -0
  174. package/dist/ui/formatters/console/chronological.js +3 -1
  175. package/dist/ui/formatters/console/follow.d.ts +2 -1
  176. package/dist/ui/formatters/console/follow.js +2 -2
  177. package/dist/ui/formatters/console/json.d.ts +2 -2
  178. package/dist/ui/formatters/console/json.js +11 -5
  179. package/dist/ui/formatters/console/shared.d.ts +30 -0
  180. package/dist/ui/formatters/console/shared.js +16 -0
  181. package/dist/ui/formatters/console/summarize.d.ts +9 -2
  182. package/dist/ui/formatters/console/summarize.js +40 -9
  183. package/dist/ui/formatters/console.d.ts +2 -1
  184. package/dist/ui/formatters/console.js +7 -5
  185. package/dist/ui/formatters/details.js +3 -1
  186. package/dist/ui/formatters/dom.d.ts +2 -2
  187. package/dist/ui/formatters/dom.js +10 -8
  188. package/dist/ui/formatters/helpFormatters.js +1 -1
  189. package/dist/ui/formatters/inspect.js +50 -17
  190. package/dist/ui/formatters/installSkill.d.ts +9 -1
  191. package/dist/ui/formatters/installSkill.js +32 -6
  192. package/dist/ui/formatters/layout.js +2 -1
  193. package/dist/ui/formatters/networkList.d.ts +1 -1
  194. package/dist/ui/formatters/networkList.js +1 -2
  195. package/dist/ui/formatters/preview.d.ts +2 -0
  196. package/dist/ui/formatters/preview.js +17 -7
  197. package/dist/ui/formatters/sessions.d.ts +2 -2
  198. package/dist/ui/formatters/sessions.js +9 -2
  199. package/dist/ui/formatters/status.js +1 -1
  200. package/dist/ui/logging/logger.d.ts +1 -1
  201. package/dist/ui/messages/commands.d.ts +168 -11
  202. package/dist/ui/messages/commands.js +245 -18
  203. package/dist/ui/messages/consoleMessages.d.ts +24 -0
  204. package/dist/ui/messages/consoleMessages.js +32 -0
  205. package/dist/ui/messages/preview.d.ts +12 -0
  206. package/dist/ui/messages/preview.js +18 -2
  207. package/dist/ui/messages/session.d.ts +13 -2
  208. package/dist/ui/messages/session.js +22 -3
  209. package/dist/utils/cssValues.js +36 -4
  210. package/dist/utils/decisionTrees.js +0 -5
  211. package/dist/utils/directories.d.ts +34 -0
  212. package/dist/utils/directories.js +88 -0
  213. package/dist/utils/display.d.ts +16 -0
  214. package/dist/utils/display.js +42 -0
  215. package/dist/utils/exitCodes.d.ts +1 -0
  216. package/dist/utils/exitCodes.js +6 -0
  217. package/dist/utils/process.d.ts +12 -0
  218. package/dist/utils/process.js +25 -0
  219. package/dist/utils/suggestions.d.ts +4 -2
  220. package/dist/utils/suggestions.js +7 -5
  221. package/dist/utils/taskMappings.js +1 -1
  222. package/package.json +3 -2
@@ -4,6 +4,8 @@ import { createInteractionRunner } from './interactions.js';
4
4
  import { withTriggeredRequestCount } from './triggeredRequests.js';
5
5
  import { CommandError } from '../../errors/index.js';
6
6
  import { cdpCallError, formDiscoveryFailedError } from '../../errors/messages.js';
7
+ import { searchStyleSheets } from '../../runtime/css/search.js';
8
+ import { auditPage } from '../../runtime/dom/audit.js';
7
9
  import { evaluateScript, withBusyPageRecovery } from '../../runtime/dom/evalHelpers.js';
8
10
  import { inspectEventListeners } from '../../runtime/dom/eventListeners.js';
9
11
  import { FORM_DISCOVERY_SCRIPT, isRawFormData } from '../../runtime/dom/formDiscovery.js';
@@ -15,10 +17,12 @@ import { inspectElement } from '../../runtime/dom/inspect.js';
15
17
  import { inspectLayout } from '../../runtime/dom/layout.js';
16
18
  import { onScriptTarget } from '../../runtime/dom/targetNode.js';
17
19
  import { waitForCondition } from '../../runtime/dom/wait.js';
20
+ import { evaluateInBdgWorld, sendForBdgScript } from '../../runtime/page/bdgWorld.js';
18
21
  import { emulatePage, pageAppearance } from '../../runtime/page/emulation.js';
19
22
  import { readDocumentReadyState } from '../../runtime/page/loadingState.js';
20
23
  import { navigatePage } from '../../runtime/page/navigation.js';
21
24
  import { skippedBodyReason } from '../../telemetry/network.js';
25
+ import { consoleMessageDroppedError } from '../../ui/messages/consoleMessages.js';
22
26
  import { sessionCommand } from '../../ui/messages/sessionCommand.js';
23
27
  import { EXIT_CODES } from '../../utils/exitCodes.js';
24
28
  import { filterDefined } from '../../utils/objects.js';
@@ -185,24 +189,28 @@ function findNetworkRequestOrThrow(store, id) {
185
189
  return request;
186
190
  }
187
191
  /**
188
- * Find console message by index or throw.
192
+ * Find console message by its session index or throw.
189
193
  *
190
- * @param messages - Array of console messages
194
+ * @param messages - Console messages kept
191
195
  * @param indexStr - Index as string
196
+ * @param dropped - Messages dropped before the first kept one (its index)
192
197
  * @returns Found message
193
- * @throws Error if invalid index or not found
198
+ * @throws CommandError if the index is invalid, dropped or not found
194
199
  */
195
- function findConsoleMessageOrThrow(messages, indexStr) {
200
+ function findConsoleMessageOrThrow(messages, indexStr, dropped) {
196
201
  if (!/^\d+$/.test(indexStr)) {
197
202
  throw new CommandError(`Invalid console message index: ${indexStr}`, { suggestion: `Use a 0-based index from: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.INVALID_ARGUMENTS);
198
203
  }
199
204
  const index = parseInt(indexStr, 10);
200
- if (index >= messages.length) {
205
+ if (index < dropped) {
206
+ throw new CommandError(consoleMessageDroppedError(index, dropped), { suggestion: `List messages with: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.RESOURCE_NOT_FOUND);
207
+ }
208
+ if (index - dropped >= messages.length) {
201
209
  throw new CommandError(messages.length === 0
202
210
  ? `Console message not found at index: ${indexStr} (no messages captured yet)`
203
- : `Console message not found at index: ${indexStr} (available: 0-${messages.length - 1})`, { suggestion: `List messages with: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.RESOURCE_NOT_FOUND);
211
+ : `Console message not found at index: ${indexStr} (available: ${dropped}-${dropped + messages.length - 1})`, { suggestion: `List messages with: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.RESOURCE_NOT_FOUND);
204
212
  }
205
- const message = messages[index];
213
+ const message = messages[index - dropped];
206
214
  if (!message) {
207
215
  throw new CommandError(`Console message not found at index: ${indexStr}`, {}, EXIT_CODES.RESOURCE_NOT_FOUND);
208
216
  }
@@ -310,6 +318,7 @@ export function createCommandRegistry(store, emulation) {
310
318
  const allNetwork = allNetworkRequests(store);
311
319
  const totalNetwork = allNetwork.length;
312
320
  const totalConsole = store.consoleMessages.length;
321
+ const dropped = store.consoleDropped;
313
322
  const networkBounds = calculateSliceBounds(totalNetwork, lastN, offset);
314
323
  const consoleBounds = calculateSliceBounds(totalConsole, lastN, offset);
315
324
  const recentNetwork = params.only === 'console'
@@ -321,7 +330,7 @@ export function createCommandRegistry(store, emulation) {
321
330
  ? []
322
331
  : store.consoleMessages
323
332
  .slice(consoleBounds.start, consoleBounds.end)
324
- .map((msg, i) => mapConsoleMessageToPreview(msg, consoleBounds.start + i));
333
+ .map((msg, i) => mapConsoleMessageToPreview(msg, dropped + consoleBounds.start + i));
325
334
  return Promise.resolve({
326
335
  version: VERSION,
327
336
  startTime: store.sessionStartTime,
@@ -332,10 +341,12 @@ export function createCommandRegistry(store, emulation) {
332
341
  },
333
342
  activeTelemetry: store.activeTelemetry,
334
343
  currentNavigationId: store.getCurrentNavigationId?.() ?? 0,
344
+ ...(store.pageCrashedAt !== undefined && { pageCrashedAt: store.pageCrashedAt }),
335
345
  network: recentNetwork,
336
346
  console: recentConsole,
337
347
  totalNetwork,
338
348
  totalConsole,
349
+ ...(dropped > 0 && { droppedConsole: dropped }),
339
350
  hasMoreNetwork: networkBounds.start > 0,
340
351
  hasMoreConsole: consoleBounds.start > 0,
341
352
  });
@@ -346,7 +357,7 @@ export function createCommandRegistry(store, emulation) {
346
357
  return Promise.resolve({ item: withBodyNotCaptured(request) });
347
358
  }
348
359
  if (params.itemType === 'console') {
349
- const message = findConsoleMessageOrThrow(store.consoleMessages, params.id);
360
+ const message = findConsoleMessageOrThrow(store.consoleMessages, params.id, store.consoleDropped);
350
361
  return Promise.resolve({ item: message });
351
362
  }
352
363
  return Promise.reject(new Error(`Unknown itemType: ${String(params.itemType)}. Expected 'network' or 'console'.`));
@@ -361,7 +372,9 @@ export function createCommandRegistry(store, emulation) {
361
372
  target: {
362
373
  url: store.targetInfo?.url ?? '',
363
374
  title: store.targetInfo?.title ?? '',
364
- ...(await pageAppearance(cdp)),
375
+ ...(store.pageCrashedAt === undefined
376
+ ? await pageAppearance(cdp)
377
+ : { crashedAt: store.pageCrashedAt }),
365
378
  },
366
379
  activeTelemetry: store.activeTelemetry,
367
380
  activity: filterDefined({
@@ -399,10 +412,15 @@ export function createCommandRegistry(store, emulation) {
399
412
  });
400
413
  },
401
414
  cdp_call: async (cdp, params) => {
402
- const result = await withBusyPageRecovery(cdp, cdp.send(params.method, params.params ?? {}).catch((error) => {
415
+ const send = params.isolated
416
+ ? sendForBdgScript(cdp, params.method, params.params ?? {})
417
+ : cdp.send(params.method, params.params ?? {});
418
+ const result = await withBusyPageRecovery(cdp, send.catch((error) => {
403
419
  throw callerError(params.method, error) ?? error;
404
420
  }));
405
- const detectionResult = patternDetector.trackCommand(params.method);
421
+ const detectionResult = params.isolated
422
+ ? { shouldShow: false, pattern: undefined }
423
+ : patternDetector.trackCommand(params.method);
406
424
  let hint;
407
425
  if (detectionResult.shouldShow && detectionResult.pattern) {
408
426
  hint = {
@@ -458,7 +476,11 @@ export function createCommandRegistry(store, emulation) {
458
476
  })), params.wait !== false))),
459
477
  dom_listeners: async (cdp, params) => withBusyPageRecovery(cdp, inspectEventListeners(cdp, params)),
460
478
  dom_layout: async (cdp, params) => withBusyPageRecovery(cdp, inspectLayout(cdp, params)),
461
- dom_inspect: async (cdp, params) => withBusyPageRecovery(cdp, inspectElement(cdp, params)),
479
+ dom_audit: async (cdp, params) => withBusyPageRecovery(cdp, auditPage(cdp, params)),
480
+ css_search: async (cdp, params) => searchStyleSheets(cdp, params),
481
+ dom_inspect: async (cdp, params) => withBusyPageRecovery(cdp, inspectElement(cdp, params).then((result) => result.theme === 'dark' && emulation.get().colorScheme === 'dark'
482
+ ? { ...result, themeFrom: 'emulation' }
483
+ : result)),
462
484
  dom_wait: async (cdp, params) => waitForCondition(cdp, params),
463
485
  page_navigate: async (cdp, params) => interact(cdp, () => navigatePage(cdp, params.action, {
464
486
  ...filterDefined({ url: params.url, wait: params.wait }),
@@ -469,7 +491,7 @@ export function createCommandRegistry(store, emulation) {
469
491
  return { emulated, ...(await pageAppearance(cdp)) };
470
492
  },
471
493
  dom_form_discover: async (cdp) => {
472
- const response = await withBusyPageRecovery(cdp, cdp.send('Runtime.evaluate', {
494
+ const response = await withBusyPageRecovery(cdp, evaluateInBdgWorld(cdp, {
473
495
  expression: FORM_DISCOVERY_SCRIPT,
474
496
  returnByValue: true,
475
497
  }));
@@ -51,7 +51,8 @@ export type InteractionRunner = <T extends object>(cdp: CDPConnection, action: (
51
51
  * queued. After each one, the bound target (`window.__bdgTarget`) is removed
52
52
  * from the page (without waiting: during a pending navigation that takes until
53
53
  * the new page commits), and the dialogs it opened, what it changed on the
54
- * page (see {@link watchActionEffects}) and the network requests it
54
+ * page (see {@link watchActionEffects}; a console message logged meanwhile
55
+ * counts as an effect) and the network requests it
55
56
  * triggered (see {@link watchTriggeredRequests}) are added to its result,
56
57
  * and, when asked, what the page was still working on (see
57
58
  * {@link pendingChanges}). They are attributed by time: a dialog or request
@@ -18,6 +18,15 @@ const log = createLogger('dom');
18
18
  function succeeded(result) {
19
19
  return !('success' in result) || result.success !== false;
20
20
  }
21
+ /**
22
+ * Console messages the session has logged, dropped ones included.
23
+ *
24
+ * @param store - Session store
25
+ * @returns Count that only grows
26
+ */
27
+ function consoleMessagesLogged(store) {
28
+ return store.consoleDropped + store.consoleMessages.length;
29
+ }
21
30
  /**
22
31
  * Create the runner for a session's interactions.
23
32
  *
@@ -26,7 +35,8 @@ function succeeded(result) {
26
35
  * queued. After each one, the bound target (`window.__bdgTarget`) is removed
27
36
  * from the page (without waiting: during a pending navigation that takes until
28
37
  * the new page commits), and the dialogs it opened, what it changed on the
29
- * page (see {@link watchActionEffects}) and the network requests it
38
+ * page (see {@link watchActionEffects}; a console message logged meanwhile
39
+ * counts as an effect) and the network requests it
30
40
  * triggered (see {@link watchTriggeredRequests}) are added to its result,
31
41
  * and, when asked, what the page was still working on (see
32
42
  * {@link pendingChanges}). They are attributed by time: a dialog or request
@@ -41,6 +51,7 @@ export function createInteractionRunner(store) {
41
51
  return (cdp, action, options = {}) => {
42
52
  const run = queue.then(async () => {
43
53
  const firstDialog = store.dialogs.length;
54
+ const firstConsoleMessage = consoleMessagesLogged(store);
44
55
  const collectRequests = options.reportRequests === false ? undefined : watchTriggeredRequests(store);
45
56
  const effects = options.reportEffects === false ? undefined : watchActionEffects(cdp);
46
57
  try {
@@ -50,6 +61,7 @@ export function createInteractionRunner(store) {
50
61
  return { ...result, ...(dialogs.length > 0 && { dialogs }) };
51
62
  const collected = await effects?.collect({
52
63
  dialogs: dialogs.length,
64
+ consoleMessages: () => consoleMessagesLogged(store) - firstConsoleMessage,
53
65
  detectNoEffect: options.detectNoEffect === true,
54
66
  reportShown: options.reportShown === true,
55
67
  detectUnsettled: options.detectUnsettled === true,
@@ -1,8 +1,10 @@
1
+ import { hideHeadlessUserAgent } from '../../runtime/page/userAgent.js';
1
2
  import { startConsoleCollection } from '../../telemetry/console.js';
2
3
  import { startDialogHandling } from '../../telemetry/dialogs.js';
3
4
  import { prepareDOMCollection } from '../../telemetry/dom.js';
4
5
  import { startNavigationTracking } from '../../telemetry/navigation.js';
5
6
  import { startNetworkCollection, startWebSocketCollection } from '../../telemetry/network.js';
7
+ import { pageCrashedCommandError, startCrashTracking } from '../../telemetry/pageCrash.js';
6
8
  import { getErrorMessage } from '../../utils/errors.js';
7
9
  import { filterDefined } from '../../utils/objects.js';
8
10
  /** Delay before reading the title after a same-document navigation */
@@ -83,56 +85,6 @@ async function emulatePageFocus(cdp, logger) {
83
85
  .send('Emulation.setFocusEmulationEnabled', { enabled: true })
84
86
  .catch((error) => logger.debug(`No focus emulation: ${getErrorMessage(error)}`));
85
87
  }
86
- /** Reads the client hints Chrome reports, renaming the HeadlessChrome brand */
87
- const USER_AGENT_METADATA_SCRIPT = `(async () => {
88
- const data = navigator.userAgentData;
89
- if (!data) return null;
90
- const values = await data.getHighEntropyValues(
91
- ['architecture', 'bitness', 'model', 'platformVersion', 'fullVersionList', 'wow64']
92
- );
93
- const rename = (list) => (list || []).map((entry) => ({
94
- brand: entry.brand.replace('HeadlessChrome', 'Google Chrome'),
95
- version: entry.version,
96
- }));
97
- return {
98
- brands: rename(values.brands),
99
- fullVersionList: rename(values.fullVersionList),
100
- platform: values.platform,
101
- platformVersion: values.platformVersion,
102
- architecture: values.architecture,
103
- model: values.model,
104
- mobile: values.mobile,
105
- bitness: values.bitness,
106
- wow64: values.wow64,
107
- };
108
- })()`;
109
- /**
110
- * Send the user agent and client hints of regular Chrome from headless
111
- * Chrome: sites serve "HeadlessChrome" a different page (or a bot
112
- * challenge), so the page would not be the one a user sees.
113
- *
114
- * @param cdp - CDP connection
115
- * @param logger - Logger for failures (the session works without it)
116
- */
117
- async function hideHeadlessUserAgent(cdp, logger) {
118
- try {
119
- const { userAgent } = (await cdp.send('Browser.getVersion'));
120
- if (!userAgent.includes('HeadlessChrome'))
121
- return;
122
- const metadata = (await cdp.send('Runtime.evaluate', {
123
- expression: USER_AGENT_METADATA_SCRIPT,
124
- awaitPromise: true,
125
- returnByValue: true,
126
- }));
127
- await cdp.send('Emulation.setUserAgentOverride', {
128
- userAgent: userAgent.replace('HeadlessChrome', 'Chrome'),
129
- ...(metadata.result?.value ? { userAgentMetadata: metadata.result.value } : {}),
130
- });
131
- }
132
- catch (error) {
133
- logger.debug(`User agent left as is: ${getErrorMessage(error)}`);
134
- }
135
- }
136
88
  export function createDefaultTelemetryPlugins() {
137
89
  return [
138
90
  {
@@ -145,12 +97,24 @@ export function createDefaultTelemetryPlugins() {
145
97
  {
146
98
  name: 'page-identity',
147
99
  runAlways: true,
148
- async start({ cdp, logger }) {
100
+ async start({ cdp, logger, config }) {
149
101
  await emulatePageFocus(cdp, logger);
150
- await hideHeadlessUserAgent(cdp, logger);
102
+ if (!config.viewport?.mobile)
103
+ await hideHeadlessUserAgent(cdp, logger);
151
104
  return () => undefined;
152
105
  },
153
106
  },
107
+ {
108
+ name: 'page-crash',
109
+ runAlways: true,
110
+ async start({ cdp, store }) {
111
+ return startCrashTracking(cdp, (crashedAt) => {
112
+ store.pageCrashedAt = crashedAt;
113
+ if (crashedAt !== undefined)
114
+ cdp.rejectPending(pageCrashedCommandError(crashedAt));
115
+ });
116
+ },
117
+ },
154
118
  {
155
119
  name: 'navigation',
156
120
  runAlways: true,
@@ -191,7 +155,9 @@ export function createDefaultTelemetryPlugins() {
191
155
  name: 'console',
192
156
  telemetry: 'console',
193
157
  async start({ cdp, config, store }) {
194
- return startConsoleCollection(cdp, store.consoleMessages, config.includeAll ?? false, store.getCurrentNavigationId ?? undefined);
158
+ return startConsoleCollection(cdp, store.consoleMessages, config.includeAll ?? false, store.getCurrentNavigationId ?? undefined, () => {
159
+ store.consoleDropped++;
160
+ });
195
161
  },
196
162
  },
197
163
  {
@@ -123,6 +123,6 @@ async function terminateChrome(chrome, log) {
123
123
  log.info(`Chrome (PID ${pid}) survived SIGKILL`);
124
124
  return;
125
125
  }
126
- clearChromePid();
126
+ clearChromePid(pid);
127
127
  }
128
128
  //# sourceMappingURL=teardown.js.map