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
@@ -75,15 +75,23 @@ function createMessage(type, text, timestamp, args, context) {
75
75
  };
76
76
  }
77
77
  /**
78
- * Insert a message in timestamp order.
79
- * Messages are kept sorted by timestamp to handle async expansion delays.
78
+ * Insert a message in timestamp order (async expansion can deliver a message
79
+ * late). At {@link MAX_CONSOLE_MESSAGES} the oldest message is dropped to
80
+ * make room, so the newest are kept; a late message older than all kept ones
81
+ * is dropped itself.
80
82
  *
81
- * @returns False when the message limit is reached (the message is dropped)
83
+ * @param messages - Messages, oldest first (updated)
84
+ * @param message - Message to add
85
+ * @param onDropped - Called for each message dropped
86
+ * @returns False when the message itself was dropped
82
87
  */
83
- function insertMessageByTimestamp(messages, message) {
88
+ function insertMessageByTimestamp(messages, message, onDropped) {
84
89
  if (messages.length >= MAX_CONSOLE_MESSAGES) {
85
- log.debug(`Warning: Console message limit reached (${MAX_CONSOLE_MESSAGES})`);
86
- return false;
90
+ const oldest = messages[0];
91
+ onDropped();
92
+ if (oldest && message.timestamp < oldest.timestamp)
93
+ return false;
94
+ messages.shift();
87
95
  }
88
96
  const insertIndex = findInsertIndex(messages, message.timestamp);
89
97
  messages.splice(insertIndex, 0, message);
@@ -111,32 +119,31 @@ function findInsertIndex(messages, timestamp) {
111
119
  /**
112
120
  * Handle a console API call event with object expansion.
113
121
  */
114
- function handleConsoleAPICall(cdp, messages, params, context, includeAll) {
122
+ function handleConsoleAPICall(cdp, insert, params, context, includeAll) {
115
123
  const basicText = formatConsoleArgs(params.args);
116
124
  if (shouldExcludeConsoleMessage(basicText, params.type, includeAll)) {
117
125
  return;
118
126
  }
119
127
  if (hasArgsNeedingExpansion(params.args) && !usesFormatSpecifiers(params.args)) {
120
- handleExpandableMessage(cdp, messages, params, context, basicText);
128
+ handleExpandableMessage(cdp, insert, params, context, basicText);
121
129
  }
122
130
  else {
123
- const message = createMessage(params.type, basicText, params.timestamp, params.args, context);
124
- insertMessageByTimestamp(messages, message);
131
+ insert(createMessage(params.type, basicText, params.timestamp, params.args, context));
125
132
  }
126
133
  }
127
134
  /**
128
135
  * Handle a message with expandable objects.
129
136
  */
130
- function handleExpandableMessage(cdp, messages, params, context, fallbackText) {
137
+ function handleExpandableMessage(cdp, insert, params, context, fallbackText) {
131
138
  void expandConsoleArgs(cdp, params.args)
132
139
  .then((expandedText) => {
133
140
  const message = createMessage(params.type, expandedText, params.timestamp, params.args, context);
134
- insertMessageByTimestamp(messages, message);
141
+ insert(message);
135
142
  })
136
143
  .catch((error) => {
137
144
  log.debug(`Object expansion failed, using basic text: ${String(error)}`);
138
145
  const message = createMessage(params.type, fallbackText, params.timestamp, params.args, context);
139
- insertMessageByTimestamp(messages, message);
146
+ insert(message);
140
147
  });
141
148
  }
142
149
  /**
@@ -178,14 +185,14 @@ export function formatExceptionText(details) {
178
185
  *
179
186
  * @returns The message added, undefined when filtered out or over the limit
180
187
  */
181
- function handleExceptionThrown(messages, params, context, includeAll) {
188
+ function handleExceptionThrown(insert, params, context, includeAll) {
182
189
  const exception = params.exceptionDetails;
183
190
  const text = formatExceptionText(exception);
184
191
  if (shouldExcludeConsoleMessage(text, 'error', includeAll)) {
185
192
  return undefined;
186
193
  }
187
194
  const message = createMessage('error', text, params.timestamp, undefined, context);
188
- return insertMessageByTimestamp(messages, message) ? message : undefined;
195
+ return insert(message) ? message : undefined;
189
196
  }
190
197
  /** CDP's text of an unhandled promise rejection (the only kind Chrome revokes) */
191
198
  const UNHANDLED_REJECTION_TEXT = 'Uncaught (in promise)';
@@ -270,7 +277,7 @@ class RevocableRejections {
270
277
  * Worker entries are skipped: workers are attached directly, so their console
271
278
  * calls already arrive (with arguments) from the worker's own session.
272
279
  */
273
- function handleLogEntry(messages, entry, navigationId, includeAll) {
280
+ function handleLogEntry(insert, entry, navigationId, includeAll) {
274
281
  const type = LOG_LEVEL_TYPES[entry.level];
275
282
  if (entry.source === 'worker' || shouldExcludeConsoleMessage(entry.text, type, includeAll)) {
276
283
  return;
@@ -287,7 +294,7 @@ function handleLogEntry(messages, entry, navigationId, includeAll) {
287
294
  stackTrace: convertStackTrace(entry.stackTrace) ?? location,
288
295
  source: entry.source,
289
296
  };
290
- insertMessageByTimestamp(messages, createMessage(type, entry.text, entry.timestamp, undefined, context));
297
+ insert(createMessage(type, entry.text, entry.timestamp, undefined, context));
291
298
  }
292
299
  /**
293
300
  * Enable console and log events on an attached target's session.
@@ -325,17 +332,19 @@ async function startOptionalSources(cdp, typed) {
325
332
  * @param messages - Array to populate with console messages
326
333
  * @param includeAll - If true, disable default pattern filtering
327
334
  * @param getCurrentNavigationId - Function to get current navigation ID
335
+ * @param onDropped - Called for each message dropped at the limit (the oldest go first)
328
336
  * @returns Cleanup function to remove event handlers
329
337
  */
330
- export async function startConsoleCollection(cdp, messages, includeAll = false, getCurrentNavigationId) {
338
+ export async function startConsoleCollection(cdp, messages, includeAll = false, getCurrentNavigationId, onDropped = () => undefined) {
331
339
  const registry = new CDPHandlerRegistry();
332
340
  const typed = new TypedCDPConnection(cdp);
341
+ const insert = (message) => insertMessageByTimestamp(messages, message, onDropped);
333
342
  registry.registerTyped(typed, 'Runtime.consoleAPICalled', (params, sessionId) => {
334
343
  const context = {
335
344
  navigationId: getCurrentNavigationId?.(),
336
345
  stackTrace: convertStackTrace(params.stackTrace),
337
346
  };
338
- handleConsoleAPICall(senderFor(cdp, sessionId), messages, params, context, includeAll);
347
+ handleConsoleAPICall(senderFor(cdp, sessionId), insert, params, context, includeAll);
339
348
  });
340
349
  const rejections = new RevocableRejections();
341
350
  registry.registerTyped(typed, 'Runtime.exceptionThrown', (params, sessionId) => {
@@ -343,7 +352,7 @@ export async function startConsoleCollection(cdp, messages, includeAll = false,
343
352
  navigationId: getCurrentNavigationId?.(),
344
353
  stackTrace: convertStackTrace(params.exceptionDetails.stackTrace),
345
354
  };
346
- const message = handleExceptionThrown(messages, params, context, includeAll);
355
+ const message = handleExceptionThrown(insert, params, context, includeAll);
347
356
  if (message)
348
357
  rejections.track(params.exceptionDetails, message, sessionId);
349
358
  });
@@ -357,7 +366,7 @@ export async function startConsoleCollection(cdp, messages, includeAll = false,
357
366
  rejections.forgetSession(sessionId);
358
367
  });
359
368
  registry.registerTyped(typed, 'Log.entryAdded', ({ entry }) => {
360
- handleLogEntry(messages, entry, getCurrentNavigationId?.(), includeAll);
369
+ handleLogEntry(insert, entry, getCurrentNavigationId?.(), includeAll);
361
370
  });
362
371
  try {
363
372
  await typed.send('Runtime.enable', {});
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Renderer crash tracking: Chrome reports a crashed page with
3
+ * `Inspector.targetCrashed` and keeps the connection open, so without this a
4
+ * session looks active while every page command waits for a timeout. A
5
+ * reload (or any main-frame navigation) brings the page back.
6
+ */
7
+ import type { CDPConnection } from '../connection/cdp.js';
8
+ import { CommandError } from '../errors/index.js';
9
+ import type { CleanupFunction } from '../types.js';
10
+ /**
11
+ * Start tracking renderer crashes of the page.
12
+ *
13
+ * @param cdp - CDP connection to the page
14
+ * @param onChange - Called with the crash time when the page crashes, and
15
+ * with undefined when it is loaded again
16
+ * @returns Cleanup that stops tracking
17
+ */
18
+ export declare function startCrashTracking(cdp: CDPConnection, onChange: (crashedAt: number | undefined) => void): Promise<CleanupFunction>;
19
+ /**
20
+ * Error for a page command after the page's renderer crashed (exit 107).
21
+ *
22
+ * @param crashedAt - When it crashed (epoch ms)
23
+ * @returns Error with the way back
24
+ */
25
+ export declare function pageCrashedCommandError(crashedAt: number): CommandError;
26
+ //# sourceMappingURL=pageCrash.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Renderer crash tracking: Chrome reports a crashed page with
3
+ * `Inspector.targetCrashed` and keeps the connection open, so without this a
4
+ * session looks active while every page command waits for a timeout. A
5
+ * reload (or any main-frame navigation) brings the page back.
6
+ */
7
+ import { CDPHandlerRegistry } from '../connection/handlers.js';
8
+ import { TypedCDPConnection } from '../connection/typed-cdp.js';
9
+ import { CommandError } from '../errors/index.js';
10
+ import { pageCrashedError } from '../errors/messages.js';
11
+ import { createLogger } from '../ui/logging/index.js';
12
+ import { getErrorMessage } from '../utils/errors.js';
13
+ import { EXIT_CODES } from '../utils/exitCodes.js';
14
+ const log = createLogger('page-crash');
15
+ /**
16
+ * Start tracking renderer crashes of the page.
17
+ *
18
+ * @param cdp - CDP connection to the page
19
+ * @param onChange - Called with the crash time when the page crashes, and
20
+ * with undefined when it is loaded again
21
+ * @returns Cleanup that stops tracking
22
+ */
23
+ export async function startCrashTracking(cdp, onChange) {
24
+ const registry = new CDPHandlerRegistry();
25
+ const typed = new TypedCDPConnection(cdp);
26
+ registry.registerTyped(typed, 'Inspector.targetCrashed', () => {
27
+ log.info('The page crashed (renderer gone)');
28
+ onChange(Date.now());
29
+ });
30
+ registry.registerTyped(typed, 'Inspector.targetReloadedAfterCrash', () => onChange(undefined));
31
+ registry.registerTyped(typed, 'Page.frameNavigated', ({ frame }) => {
32
+ if (frame.parentId === undefined)
33
+ onChange(undefined);
34
+ });
35
+ try {
36
+ await cdp.send('Inspector.enable');
37
+ }
38
+ catch (error) {
39
+ log.debug(`Crash reports unavailable: ${getErrorMessage(error)}`);
40
+ }
41
+ return () => registry.cleanup();
42
+ }
43
+ /**
44
+ * Error for a page command after the page's renderer crashed (exit 107).
45
+ *
46
+ * @param crashedAt - When it crashed (epoch ms)
47
+ * @returns Error with the way back
48
+ */
49
+ export function pageCrashedCommandError(crashedAt) {
50
+ const err = pageCrashedError(crashedAt);
51
+ return new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.PAGE_CRASHED);
52
+ }
53
+ //# sourceMappingURL=pageCrash.js.map
package/dist/types.d.ts CHANGED
@@ -226,10 +226,14 @@ export interface BdgOutput {
226
226
  };
227
227
  /** Navigation id of the page currently loaded (live previews) */
228
228
  currentNavigationId?: number;
229
+ /** When the page's renderer crashed (epoch ms), while it is not loaded again */
230
+ pageCrashedAt?: number;
229
231
  /** Counts of all captured items matching the request (e.g. `peek --type`), when `data` holds only the most recent ones */
230
232
  totals?: {
231
233
  network: number;
232
234
  console: number;
235
+ /** Console messages dropped at the limit, oldest first (indices start after them) */
236
+ consoleDropped?: number;
233
237
  };
234
238
  error?: string;
235
239
  partial?: boolean;
@@ -327,6 +331,8 @@ export interface DomContext {
327
331
  children?: string[];
328
332
  /** Number of child elements, for an element without text */
329
333
  childCount?: number;
334
+ /** The children listed are those of its shadow root (a web component) */
335
+ shadowChildren?: boolean;
330
336
  /** Attributes that identify it by its type (see {@link KeyAttributes}) */
331
337
  attributes?: KeyAttributes;
332
338
  /** A field holding a secret (password, card, one-time code): its value is shown masked */
@@ -370,6 +376,8 @@ export type ColorScheme = 'light' | 'dark';
370
376
  export interface ViewportSize {
371
377
  width: number;
372
378
  height: number;
379
+ /** A phone: mobile viewport (meta viewport, overlay scrollbars), touch and a mobile user agent */
380
+ mobile?: true;
373
381
  }
374
382
  /**
375
383
  * The page (document) request an action sent, as far as it got: still
@@ -436,6 +444,14 @@ export interface DomQueryResult {
436
444
  /** Unique selector for this node (set by form discovery) */
437
445
  selector?: string;
438
446
  }>;
447
+ /** Matches not listed (`--limit`); `count` is all of them */
448
+ omitted?: number;
449
+ /** Matches usable by index (described and cached), when fewer than `count` */
450
+ indexed?: number;
451
+ /** First matches whose viewport position was checked (`inViewport`), when more are listed */
452
+ viewportChecked?: number;
453
+ /** Identity of the page document the matches belong to (cached results only) */
454
+ document?: string;
439
455
  }
440
456
  /**
441
457
  * Result of a DOM get operation.
@@ -483,6 +499,8 @@ export interface ScreenshotResult {
483
499
  * descendants) made it larger than the border box
484
500
  */
485
501
  captured?: ElementBounds;
502
+ /** `--padding` given: CSS px of page added around the captured area */
503
+ padding?: number;
486
504
  };
487
505
  /** Capture mode used */
488
506
  captureMode?: 'full_page' | 'viewport';
@@ -675,5 +693,7 @@ export interface InstalledSkill {
675
693
  target: SkillTarget;
676
694
  path: string;
677
695
  status: 'installed' | 'updated' | 'unchanged';
696
+ /** Where the replaced copy was kept (`updated` only) */
697
+ backup?: string;
678
698
  }
679
699
  //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Human output of `bdg dom audit` and `bdg css search`.
3
+ */
4
+ import type { AuditResult, CssSearchResult } from '../../ipc/protocol/auditTypes.js';
5
+ /**
6
+ * Format `bdg dom audit`.
7
+ *
8
+ * @param data - Audit result
9
+ * @returns Output
10
+ */
11
+ export declare function formatAudit(data: AuditResult): string;
12
+ /**
13
+ * Format `bdg css search`.
14
+ *
15
+ * @param data - Search result
16
+ * @returns Output
17
+ */
18
+ export declare function formatCssSearch(data: CssSearchResult): string;
19
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Human output of `bdg dom audit` and `bdg css search`.
3
+ */
4
+ import { auditCanvasNote, auditUncertainContrastNote } from '../messages/commands.js';
5
+ import { truncateByLength } from '../../utils/strings.js';
6
+ /** Width of the text quoted in a finding */
7
+ const TEXT_WIDTH = 50;
8
+ /**
9
+ * Format `bdg dom audit`.
10
+ *
11
+ * @param data - Audit result
12
+ * @returns Output
13
+ */
14
+ export function formatAudit(data) {
15
+ const sections = [
16
+ data.contrast && contrastSection(data.contrast),
17
+ data.overflow && overflowSection(data.overflow),
18
+ data.layers && layersSection(data.layers),
19
+ data.animations && animationsSection(data.animations, data.canvases),
20
+ ].filter((section) => section !== undefined);
21
+ const capped = data.capped ? [`(stopped after ${data.walked} elements; the page has more)`] : [];
22
+ return [...sections.flatMap((lines) => [...lines, '']), ...capped].join('\n').trimEnd();
23
+ }
24
+ /**
25
+ * The contrast section.
26
+ *
27
+ * @param contrast - Contrast findings
28
+ * @returns Lines
29
+ */
30
+ function contrastSection(contrast) {
31
+ const head = `Contrast (${contrast.level}): ${contrast.failing} of ${contrast.checked} text elements below`;
32
+ const rows = contrast.items.map((item) => ` ${item.ratio.toFixed(2).padStart(5)} ${item.color} on ${item.background} ${item.element} "${truncateByLength(item.text, TEXT_WIDTH)}" ${item.size}px${item.weight >= 700 ? ' bold' : ''}${item.opacity !== undefined ? ` (faded: opacity ${item.opacity})` : ''}${item.inView ? '' : ' (out of view)'}`);
33
+ const more = contrast.failing - contrast.items.length;
34
+ return [
35
+ head,
36
+ ...rows,
37
+ ...(more > 0 ? [` (+${more} more; --limit to list them)`] : []),
38
+ ...(contrast.uncertain ? [` ${auditUncertainContrastNote(contrast.uncertain)}`] : []),
39
+ ];
40
+ }
41
+ /**
42
+ * The overflow section.
43
+ *
44
+ * @param overflow - Overflow findings
45
+ * @returns Lines
46
+ */
47
+ function overflowSection(overflow) {
48
+ const head = overflow.scrollsSideways
49
+ ? `Overflow: the page is ${overflow.pageWidth} wide in a ${overflow.viewportWidth} viewport (it scrolls sideways)`
50
+ : `Overflow: nothing makes the page scroll sideways (${overflow.viewportWidth} wide)`;
51
+ return [
52
+ head,
53
+ ...overflow.wide.map((item) => ` past the right edge: ${item.element} (to ${item.right}, ${item.width} wide)`),
54
+ ...overflow.truncated.map((item) => ` cut off (${item.kind}): ${item.element}${times(item.count)} "${truncateByLength(item.text, TEXT_WIDTH)}"`),
55
+ ...overflow.scrollers.map((item) => ` scrolls sideways inside: ${item.element} (${item.scrollWidth} of content in ${item.width})`),
56
+ ...overflow.images.map((image) => ` image ${[image.upscaled && `upscaled ${image.scale}x${overflow.pixelRatio > 1 ? ` at pixel ratio ${overflow.pixelRatio}` : ''}`, image.distorted && 'distorted'].filter(Boolean).join(', ')}: ${image.element}${times(image.count)} ${image.natural.w}x${image.natural.h} pixels drawn at ${image.rendered.w}x${image.rendered.h} CSS px`),
57
+ ];
58
+ }
59
+ /**
60
+ * How many identical findings a row stands for.
61
+ *
62
+ * @param count - Count, when 2 or more
63
+ * @returns e.g. ` ×5`, or empty
64
+ */
65
+ function times(count) {
66
+ return count ? ` ×${count}` : '';
67
+ }
68
+ /**
69
+ * The layers section.
70
+ *
71
+ * @param layers - Fixed and sticky elements
72
+ * @returns Lines
73
+ */
74
+ function layersSection(layers) {
75
+ if (layers.length === 0)
76
+ return ['Layers: no fixed or sticky elements'];
77
+ return [
78
+ `Layers: ${layers.length} fixed or sticky`,
79
+ ...layers.map((layer) => ` ${layer.position} z ${layer.zIndex} ${layer.element} ${layer.rect.w}x${layer.rect.h} at ${layer.rect.x},${layer.rect.y} of the viewport${layer.inView ? '' : ' (not in view now)'}`),
80
+ ];
81
+ }
82
+ /**
83
+ * The animations section.
84
+ *
85
+ * @param animations - Running animations
86
+ * @param canvases - Visible canvas elements
87
+ * @returns Lines
88
+ */
89
+ function animationsSection(animations, canvases) {
90
+ const note = canvases ? [` ${auditCanvasNote(canvases)}`] : [];
91
+ if (animations.length === 0)
92
+ return ['Animations: none running', ...note];
93
+ return [
94
+ `Animations: ${animations.length} running`,
95
+ ...animations.map((animation) => ` ${animation.name} on ${animation.element}${times(animation.count)} (${animation.type}, ${typeof animation.duration === 'number' ? `${animation.duration}ms` : animation.duration}, ${animation.iterations === 'infinite' ? 'infinite' : `${animation.iterations}x`}${animation.scrollDriven ? ', scroll-driven' : ''})`),
96
+ ...note,
97
+ ];
98
+ }
99
+ /**
100
+ * Format `bdg css search`.
101
+ *
102
+ * @param data - Search result
103
+ * @returns Output
104
+ */
105
+ export function formatCssSearch(data) {
106
+ if (data.total === 0)
107
+ return `"${data.query}" is not in the page's ${data.sheets} stylesheets`;
108
+ const more = data.total - data.matches.length;
109
+ return [
110
+ `"${data.query}": ${data.total} matches in ${data.sheets} stylesheets`,
111
+ ...data.matches.flatMap((match) => [` ${match.source}`, ` ${match.text}`]),
112
+ ...(more > 0 ? [` (+${more} more; --limit to list them)`] : []),
113
+ ].join('\n');
114
+ }
115
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Human-readable output of `bdg cdp`: search results, domain and method
3
+ * lists, method schemas and method results (`--json` prints the data as is).
4
+ */
5
+ import type { ParameterSchema, ReturnSchema } from '../../cdp/schema.js';
6
+ /** Protocol description and flags shared by domains and methods */
7
+ interface ProtocolEntry {
8
+ description?: string | undefined;
9
+ experimental?: boolean | undefined;
10
+ deprecated?: boolean | undefined;
11
+ }
12
+ /** A method in `bdg cdp --search` results */
13
+ interface CdpSearchMethod extends ProtocolEntry {
14
+ name: string;
15
+ domain: string;
16
+ method: string;
17
+ parameterCount: number;
18
+ example?: string | undefined;
19
+ }
20
+ /** `bdg cdp --search <query>` result */
21
+ export interface CdpSearchData {
22
+ query: string;
23
+ count: number;
24
+ methods: CdpSearchMethod[];
25
+ }
26
+ /** A domain in `bdg cdp --list` */
27
+ interface CdpDomainEntry extends ProtocolEntry {
28
+ name: string;
29
+ commands: number;
30
+ events: number;
31
+ dependencies?: string[] | undefined;
32
+ }
33
+ /** `bdg cdp --list` result */
34
+ export interface CdpDomainListData {
35
+ count: number;
36
+ domains: CdpDomainEntry[];
37
+ }
38
+ /** A method in `bdg cdp <Domain> --list` */
39
+ interface CdpDomainMethod extends ProtocolEntry {
40
+ name: string;
41
+ fullName: string;
42
+ parameterCount: number;
43
+ parameters: Pick<ParameterSchema, 'name' | 'type' | 'required'>[];
44
+ returns: Pick<ReturnSchema, 'name' | 'type'>[];
45
+ example?: string | undefined;
46
+ }
47
+ /** `bdg cdp <Domain> --list` result */
48
+ export interface CdpDomainMethodsData {
49
+ domain: string;
50
+ description?: string | undefined;
51
+ count: number;
52
+ methods: CdpDomainMethod[];
53
+ }
54
+ /** `bdg cdp <Domain> --describe` result */
55
+ export interface CdpDomainDescription extends ProtocolEntry {
56
+ type: 'domain';
57
+ domain: string;
58
+ commands: number;
59
+ events: number;
60
+ note?: string | undefined;
61
+ nextStep: string;
62
+ }
63
+ /** A parameter or return value in `bdg cdp <Domain.method> --describe` */
64
+ interface CdpField {
65
+ name: string;
66
+ type: string;
67
+ description?: string | undefined;
68
+ items?: string | undefined;
69
+ }
70
+ /** `bdg cdp <Domain.method> --describe` result */
71
+ export interface CdpMethodDescription extends ProtocolEntry {
72
+ type: 'method';
73
+ name: string;
74
+ domain: string;
75
+ method: string;
76
+ note?: string | undefined;
77
+ parameters: (CdpField & {
78
+ required: boolean;
79
+ enum?: string[] | undefined;
80
+ deprecated?: boolean | undefined;
81
+ })[];
82
+ returns: (CdpField & {
83
+ optional: boolean;
84
+ })[];
85
+ example?: {
86
+ command: string;
87
+ params?: Record<string, unknown> | undefined;
88
+ } | undefined;
89
+ }
90
+ /** `bdg cdp <Domain.method>` result */
91
+ export interface CdpExecuteData {
92
+ method: string;
93
+ result: unknown;
94
+ }
95
+ /**
96
+ * Format `bdg cdp --search <query>`.
97
+ *
98
+ * @param data - Search result
99
+ * @returns Matching methods with their first description sentence
100
+ */
101
+ export declare function formatCdpSearch(data: CdpSearchData): string;
102
+ /**
103
+ * Format `bdg cdp --list`.
104
+ *
105
+ * @param data - All domains
106
+ * @returns One line per domain with its method and event counts
107
+ */
108
+ export declare function formatCdpDomains(data: CdpDomainListData): string;
109
+ /**
110
+ * Format `bdg cdp <Domain> --list`.
111
+ *
112
+ * @param data - The domain's methods
113
+ * @returns One line per method with the first sentence of its description
114
+ */
115
+ export declare function formatCdpDomainMethods(data: CdpDomainMethodsData): string;
116
+ /**
117
+ * Format `bdg cdp <Domain.method> --describe` or `bdg cdp <Domain> --describe`.
118
+ *
119
+ * @param data - Method or domain description
120
+ * @returns Description, parameters (`?` = optional), returns, note and example
121
+ */
122
+ export declare function formatCdpDescription(data: CdpMethodDescription | CdpDomainDescription): string;
123
+ /**
124
+ * Whether a CDP method returned nothing (null, undefined or an empty object).
125
+ *
126
+ * @param result - Method result
127
+ * @returns True for an empty result
128
+ */
129
+ export declare function isEmptyCdpResult(result: unknown): boolean;
130
+ /**
131
+ * Format a CDP method's result: the result object as indented JSON.
132
+ *
133
+ * @param data - Method and its result
134
+ * @returns The result, or a line saying the method returned nothing
135
+ */
136
+ export declare function formatCdpResult(data: CdpExecuteData): string;
137
+ export {};
138
+ //# sourceMappingURL=cdp.d.ts.map