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,7 @@
4
4
  * Discovers forms, extracts semantic labels, detects state and validation,
5
5
  * and returns structured data for agent consumption.
6
6
  */
7
+ import { MASKED_VALUE, SENSITIVE_FIELD_JS } from './elementInfo.js';
7
8
  /**
8
9
  * Page-context script for form discovery.
9
10
  *
@@ -11,7 +12,11 @@
11
12
  * - Native form elements and inputs
12
13
  * - Custom components with ARIA roles
13
14
  * - Labels via priority chain (label[for], aria-label, placeholder, etc.)
14
- * - Current values and validation state
15
+ * - Current values and validation state (never a secret: a hidden input's
16
+ * value is left out, a sensitive text field's or select's
17
+ * ({@link SENSITIVE_FIELD_JS}; checkboxes and radios named like one keep
18
+ * their checked state) is {@link MASKED_VALUE} when filled, and a
19
+ * sensitive select's options do not say which is chosen)
15
20
  * - Form relevance scoring for multi-form pages
16
21
  */
17
22
  export const FORM_DISCOVERY_SCRIPT = `
@@ -206,6 +211,10 @@ export const FORM_DISCOVERY_SCRIPT = `
206
211
  function getFieldValue(element) {
207
212
  const tag = element.tagName.toLowerCase();
208
213
  const type = element.type?.toLowerCase() || 'text';
214
+ if (type === 'hidden') return '';
215
+ if (isSecret(element)) {
216
+ return (element.isContentEditable ? element.textContent : element.value) ? '${MASKED_VALUE}' : '';
217
+ }
209
218
  if (tag === 'select') {
210
219
  if (element.multiple) {
211
220
  return Array.from(element.selectedOptions).map(o => o.value);
@@ -265,12 +274,20 @@ export const FORM_DISCOVERY_SCRIPT = `
265
274
  return tag === 'input' || tag === 'textarea' || tag === 'select';
266
275
  }
267
276
 
277
+ function isSecret(element) {
278
+ const type = element.type?.toLowerCase() || 'text';
279
+ if (type === 'checkbox' || type === 'radio') return false;
280
+ if (element.getAttribute('role') === 'checkbox' || element.getAttribute('role') === 'switch') return false;
281
+ return (${SENSITIVE_FIELD_JS})(element);
282
+ }
283
+
268
284
  function getSelectOptions(element) {
269
285
  if (element.tagName.toLowerCase() !== 'select') return undefined;
286
+ const secret = isSecret(element);
270
287
  return Array.from(element.options).map(opt => ({
271
- value: opt.value,
288
+ value: secret ? '' : opt.value,
272
289
  label: opt.textContent.trim(),
273
- selected: opt.selected
290
+ selected: secret ? false : opt.selected
274
291
  }));
275
292
  }
276
293
 
@@ -5,9 +5,9 @@
5
5
  import * as fs from 'node:fs';
6
6
  import * as path from 'node:path';
7
7
  import { CommandError } from '../../../errors/index.js';
8
- import { fileNotFoundError, uploadDirectoryError, singleFileInputError, fillableElementNotFoundError, clickableElementNotFoundError, clickTargetDetachedError, unexpectedResponseFormatError, operationFailedError, pressNotReceivedError, unreachableElementError, } from '../../../errors/messages.js';
9
- import { escapeValueForJS, formatScriptExecutionError, throwIfInvalidSelector, withMultipleMatchesWarning, withValueMismatchWarning, } from './shared.js';
10
- import { FILL_READ_BACK_SCRIPT, REACT_FILL_SCRIPT, CLICK_ELEMENT_SCRIPT, isFillResult, isClickResult, } from '../reactEventHelpers.js';
8
+ import { fileNotFoundError, uploadDirectoryError, singleFileInputError, fillableElementNotFoundError, clickTargetDetachedError, unexpectedResponseFormatError, operationFailedError, pressNotReceivedError, unreachableElementError, } from '../../../errors/messages.js';
9
+ import { ActionScriptError, escapeValueForJS, exceptionSummary, throwIfInvalidSelector, withMultipleMatchesWarning, withValueMismatchWarning, } from './shared.js';
10
+ import { FILL_READ_BACK_SCRIPT, FIRE_EVENT_JS, REACT_FILL_SCRIPT, CLICK_ELEMENT_SCRIPT, SHADOW_FIELD_JS, isFillResult, isClickResult, } from '../reactEventHelpers.js';
11
11
  import { FIND_ELEMENTS_JS, LABEL_CONTROL_JS, selectorArgsJS } from '../targetNode.js';
12
12
  import { createLogger } from '../../../ui/logging/index.js';
13
13
  import { CLICK_NOT_RECEIVED_WARNING, POINTER_ACTION_DONE, POINTER_ACTION_NOUN, domClickFallbackWarning, } from '../../../ui/messages/commands.js';
@@ -32,9 +32,7 @@ export async function fillElement(cdp, selector, value, options = {}) {
32
32
  const cdpResponse = response;
33
33
  if (cdpResponse.exceptionDetails) {
34
34
  throwIfInvalidSelector(cdpResponse.exceptionDetails, selector);
35
- const errorMessage = formatScriptExecutionError(cdpResponse.exceptionDetails, selector, 'fill', expression);
36
- const err = fillableElementNotFoundError(selector);
37
- throw new CommandError(errorMessage, { suggestion: err.suggestion }, EXIT_CODES.SOFTWARE_ERROR);
35
+ throw new ActionScriptError('fill', exceptionSummary(cdpResponse.exceptionDetails), selector);
38
36
  }
39
37
  if (cdpResponse.result?.value && isFillResult(cdpResponse.result.value)) {
40
38
  const result = cdpResponse.result.value;
@@ -106,8 +104,8 @@ function isValueMismatch(value) {
106
104
  /** Empties a file input as a user removing the selection would (with events). */
107
105
  const CLEAR_FILE_INPUT_FUNCTION = `function () {
108
106
  this.value = '';
109
- this.dispatchEvent(new Event('input', { bubbles: true }));
110
- this.dispatchEvent(new Event('change', { bubbles: true }));
107
+ (${FIRE_EVENT_JS})(this, 'input');
108
+ (${FIRE_EVENT_JS})(this, 'change');
111
109
  }`;
112
110
  /** Object group for remote objects created while selecting files. */
113
111
  const UPLOAD_OBJECT_GROUP = 'bdg-upload';
@@ -176,7 +174,7 @@ async function setFileInput(cdp, selector, value, options) {
176
174
  return problem;
177
175
  try {
178
176
  const located = (await cdp.send('Runtime.evaluate', {
179
- expression: `((el) => (${LABEL_CONTROL_JS})(el) || el)((${FIND_ELEMENTS_JS})(${selectorArgsJS(selector)})[${options.index ?? 0}])`,
177
+ expression: `((el) => (${LABEL_CONTROL_JS})(el) || (${SHADOW_FIELD_JS})(el) || el)((${FIND_ELEMENTS_JS})(${selectorArgsJS(selector)})[${options.index ?? 0}])`,
180
178
  objectGroup: UPLOAD_OBJECT_GROUP,
181
179
  }));
182
180
  if (located.exceptionDetails)
@@ -441,9 +439,7 @@ export async function clickElement(cdp, selector, options = {}) {
441
439
  const cdpResponse = response;
442
440
  if (cdpResponse.exceptionDetails) {
443
441
  throwIfInvalidSelector(cdpResponse.exceptionDetails, selector);
444
- const errorMessage = formatScriptExecutionError(cdpResponse.exceptionDetails, selector, 'click', expression);
445
- const err = clickableElementNotFoundError(selector);
446
- throw new CommandError(errorMessage, { suggestion: err.suggestion }, EXIT_CODES.SOFTWARE_ERROR);
442
+ throw new ActionScriptError(POINTER_ACTION_NOUN[action], exceptionSummary(cdpResponse.exceptionDetails), selector);
447
443
  }
448
444
  if (cdpResponse.result?.value && isClickResult(cdpResponse.result.value)) {
449
445
  return await performClick(cdp, cdpResponse.result.value, action, options.strict === true);
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { CommandError } from '../../../errors/index.js';
7
7
  import { VIA_LABEL_SUFFIX, keyPressFailedError, operationFailedError, unknownKeyError, } from '../../../errors/messages.js';
8
- import { ELEMENT_IDENTITY_JS } from '../elementInfo.js';
8
+ import { DISABLED_CAUSE_JS, ELEMENT_IDENTITY_JS } from '../elementInfo.js';
9
9
  import { throwIfInvalidSelector, withMultipleMatchesWarning, } from './shared.js';
10
10
  import { describeModifiers, getKeyDefinition, impliesShift, MODIFIER_FLAGS, parseModifiers, similarKeyNames, shortcutCommands, } from '../keyMapping.js';
11
11
  import { FIND_ELEMENTS_JS, LABEL_CONTROL_JS, selectorArgsJS } from '../targetNode.js';
@@ -60,7 +60,7 @@ const FOCUS_ELEMENT_SCRIPT = `
60
60
  return {
61
61
  success: false,
62
62
  reason: 'not-focusable',
63
- error: 'Element <' + el.tagName.toLowerCase() + '> cannot receive keyboard focus' + (el.matches(':disabled') ? ' (it is disabled)' : '')
63
+ error: 'Element <' + el.tagName.toLowerCase() + '> cannot receive keyboard focus' + ((${DISABLED_CAUSE_JS})(el) !== null ? ' (it is disabled)' : '')
64
64
  };
65
65
  }
66
66
  }
@@ -1,13 +1,10 @@
1
1
  /**
2
- * Shared internal helpers for form-fill operations: script-error formatting
3
- * and JS string escaping.
2
+ * Shared internal helpers for form-fill operations: script errors and JS
3
+ * string escaping.
4
4
  */
5
5
  import type { Protocol } from '../../../connection/typed-cdp.js';
6
+ import { CommandError } from '../../../errors/index.js';
6
7
  import type { FillResult } from '../../../ipc/protocol/domTypes.js';
7
- /**
8
- * Escape a CSS selector for embedding in a single-quoted JS string.
9
- */
10
- export declare function escapeSelectorForJS(selector: string): string;
11
8
  /**
12
9
  * Add a warning when the selector matched several elements and no index was
13
10
  * given, so the caller knows which one was used. Keeps an existing warning.
@@ -34,11 +31,20 @@ export declare function withValueMismatchWarning(result: FillResult): FillResult
34
31
  */
35
32
  export declare function escapeValueForJS(value: string): string;
36
33
  /**
37
- * Format a CDP exception into a user-friendly error with troubleshooting
38
- * hints. Detects shell-quote-damaged selectors and recommends the
39
- * query-then-act pattern.
34
+ * An action's page script threw. The action that ran it reports what was
35
+ * thrown; when the page replaced built-ins the script uses,
36
+ * `onScriptTarget` makes that the error instead.
40
37
  */
41
- export declare function formatScriptExecutionError(exceptionDetails: Protocol.Runtime.ExceptionDetails, selector: string, operationType?: 'fill' | 'click', expression?: string): string;
38
+ export declare class ActionScriptError extends CommandError {
39
+ readonly action: string;
40
+ readonly exception: string;
41
+ /**
42
+ * @param action - The action, e.g. `fill`
43
+ * @param exception - What the script threw, in one line
44
+ * @param selector - Selector the action was for
45
+ */
46
+ constructor(action: string, exception: string, selector: string);
47
+ }
42
48
  /**
43
49
  * What a page script threw, in one line (`TypeError: Cannot read …` rather
44
50
  * than CDP's bare "Uncaught").
@@ -1,18 +1,11 @@
1
1
  /**
2
- * Shared internal helpers for form-fill operations: script-error formatting
3
- * and JS string escaping.
2
+ * Shared internal helpers for form-fill operations: script errors and JS
3
+ * string escaping.
4
4
  */
5
5
  import { CommandError } from '../../../errors/index.js';
6
- import { invalidSelectorError } from '../../../errors/messages.js';
6
+ import { actionScriptFailedError, invalidSelectorError } from '../../../errors/messages.js';
7
7
  import { multipleMatchesWarning, valueMismatchWarning } from '../../../ui/messages/commands.js';
8
8
  import { EXIT_CODES } from '../../../utils/exitCodes.js';
9
- import { detectSelectorQuoteDamage } from '../../../utils/shellDetection.js';
10
- /**
11
- * Escape a CSS selector for embedding in a single-quoted JS string.
12
- */
13
- export function escapeSelectorForJS(selector) {
14
- return JSON.stringify(selector).slice(1, -1).replace(/'/g, "\\'");
15
- }
16
9
  /**
17
10
  * Add a warning when the selector matched several elements and no index was
18
11
  * given, so the caller knows which one was used. Keeps an existing warning.
@@ -49,50 +42,24 @@ export function escapeValueForJS(value) {
49
42
  return JSON.stringify(value).slice(1, -1).replace(/'/g, "\\'");
50
43
  }
51
44
  /**
52
- * Format a CDP exception into a user-friendly error with troubleshooting
53
- * hints. Detects shell-quote-damaged selectors and recommends the
54
- * query-then-act pattern.
45
+ * An action's page script threw. The action that ran it reports what was
46
+ * thrown; when the page replaced built-ins the script uses,
47
+ * `onScriptTarget` makes that the error instead.
55
48
  */
56
- export function formatScriptExecutionError(exceptionDetails, selector, operationType = 'fill', expression) {
57
- const errorText = exceptionDetails.text || 'Unknown error';
58
- const location = exceptionDetails.lineNumber !== undefined && exceptionDetails.columnNumber !== undefined
59
- ? ` at line ${exceptionDetails.lineNumber + 1}, column ${exceptionDetails.columnNumber + 1}`
60
- : '';
61
- const lines = [];
62
- lines.push(`Script execution failed: ${errorText}${location}`);
63
- if (expression) {
64
- const truncated = expression.length > 150 ? expression.slice(0, 150) + '...' : expression;
65
- lines.push('');
66
- lines.push(`Expression received: ${truncated}`);
67
- const selectorCheck = detectSelectorQuoteDamage(selector);
68
- if (selectorCheck.damaged) {
69
- lines.push('');
70
- lines.push('Shell quote damage detected in selector:');
71
- if (selectorCheck.details) {
72
- lines.push(` ${selectorCheck.details}`);
73
- }
74
- lines.push('');
75
- lines.push('Try using the two-step pattern:');
76
- lines.push(` 1. bdg dom query '${selector}'`);
77
- lines.push(` 2. bdg dom ${operationType} 0${operationType === 'fill' ? ' "value"' : ''}`);
78
- return lines.join('\n');
79
- }
49
+ export class ActionScriptError extends CommandError {
50
+ action;
51
+ exception;
52
+ /**
53
+ * @param action - The action, e.g. `fill`
54
+ * @param exception - What the script threw, in one line
55
+ * @param selector - Selector the action was for
56
+ */
57
+ constructor(action, exception, selector) {
58
+ const err = actionScriptFailedError(action, exception, selector);
59
+ super(err.message, { suggestion: err.suggestion }, EXIT_CODES.SOFTWARE_ERROR);
60
+ this.action = action;
61
+ this.exception = exception;
80
62
  }
81
- const troubleshootingSteps = operationType === 'fill'
82
- ? [
83
- `1. Verify element exists: bdg dom query "${selector}"`,
84
- '2. Check element is visible and not disabled',
85
- `3. Try direct eval: bdg dom eval "document.querySelector('${escapeSelectorForJS(selector)}').value = 'your-value'"`,
86
- ]
87
- : [
88
- `1. Verify element exists: bdg dom query "${selector}"`,
89
- '2. Check element is visible and clickable',
90
- `3. Try direct eval: bdg dom eval "document.querySelector('${escapeSelectorForJS(selector)}').click()"`,
91
- ];
92
- lines.push('');
93
- lines.push('Troubleshooting:');
94
- lines.push(` ${troubleshootingSteps.join('\n ')}`);
95
- return lines.join('\n');
96
63
  }
97
64
  /**
98
65
  * What a page script threw, in one line (`TypeError: Cannot read …` rather
@@ -4,7 +4,7 @@
4
4
  import { CDPTimeoutError } from '../../connection/errors.js';
5
5
  import { trackInFlightRequests } from '../../connection/inFlightRequests.js';
6
6
  import { submitNetworkBusyWarning, submitTimeoutError } from '../../errors/messages.js';
7
- import { ELEMENT_IDENTITY_JS } from './elementInfo.js';
7
+ import { DISABLED_CAUSE_JS, ELEMENT_IDENTITY_JS } from './elementInfo.js';
8
8
  import { throwIfInvalidSelector } from './formFillHelpers/shared.js';
9
9
  import { FIND_ELEMENTS_JS, selectorArgsJS } from './targetNode.js';
10
10
  import { summarizePendingRequests } from '../page/loadingState.js';
@@ -49,7 +49,8 @@ const PREPARE_SUBMIT_SCRIPT = `
49
49
  f.matches('button:not([type]), button[type=submit], input[type=submit], input[type=image]')
50
50
  )
51
51
  : [];
52
- if (submitters.length > 0 && submitters.every((f) => f.matches(':disabled'))) {
52
+ const disabled = (f) => (${DISABLED_CAUSE_JS})(f) !== null;
53
+ if (submitters.length > 0 && submitters.every(disabled)) {
53
54
  // A user could not submit: Enter does nothing while the default button is disabled
54
55
  return { action: 'fail', reason: 'disabled', error: 'The form\\'s submit button is disabled' };
55
56
  }
@@ -62,7 +63,7 @@ const PREPARE_SUBMIT_SCRIPT = `
62
63
  if (isForm) {
63
64
  // Like pressing Enter: the form's default button is the submitter, so its
64
65
  // name=value is sent too
65
- const submitter = submitters.find((f) => !f.matches(':disabled'));
66
+ const submitter = submitters.find((f) => !disabled(f));
66
67
  const element = (${ELEMENT_IDENTITY_JS})(submitter || el);
67
68
  if (submitter) el.requestSubmit(submitter);
68
69
  else el.requestSubmit();
@@ -127,6 +127,7 @@ export function placeInOwnerFrame(raw, owner, mapping) {
127
127
  clipper: inner.clipper ?? (inside(rect, frameView) ? outer.clipper : frame.element),
128
128
  hidden: inner.hidden ?? (outer.hidden ? 'inside a hidden iframe' : null),
129
129
  invisible: inner.invisible ?? outer.invisible,
130
+ masked: inner.invisible ? null : (inner.masked ?? outer.masked ?? null),
130
131
  fixed: outer.fixed,
131
132
  sticky: outer.sticky ?? false,
132
133
  pageScroll: outer.pageScroll,
@@ -25,4 +25,11 @@ import type { InspectResult } from '../../ipc/protocol/inspectTypes.js';
25
25
  * selector or unknown property, (87) the cached element left the page
26
26
  */
27
27
  export declare function inspectElement(cdp: CDPConnection, params: DomInspectCommand): Promise<InspectResult>;
28
+ /**
29
+ * Enable DOM and CSS once per connection (kept on: CSS.enable replays every
30
+ * stylesheet, which costs up to a few hundred ms on large sites the first time).
31
+ *
32
+ * @param cdp - CDP connection
33
+ */
34
+ export declare function enableStyleDomains(cdp: CDPConnection): Promise<void>;
28
35
  //# sourceMappingURL=inspect.d.ts.map
@@ -13,16 +13,18 @@
13
13
  * read (no cascade).
14
14
  */
15
15
  import { CommandError } from '../../errors/index.js';
16
- import { operationFailedError, unknownCssPropertyError } from '../../errors/messages.js';
16
+ import { operationFailedError, unknownCssPropertyError, whyAllPropertyError, } from '../../errors/messages.js';
17
17
  import { throwIfInvalidSelector } from './formFillHelpers/shared.js';
18
18
  import { selectedProps } from './inspectAllStyles.js';
19
19
  import { buildCascadeFields } from './inspectCascadeModel.js';
20
+ import { explainUnsetVariables } from './inspectHints.js';
20
21
  import { buildInspectResult } from './inspectModel.js';
21
22
  import { matchedStyles, sourceLabel, trackStyleSheets } from './inspectRules.js';
22
- import { INSPECT_PAGE_JS, RELATED_NODE_JS } from './inspectScripts.js';
23
+ import { INSPECT_PAGE_JS, RELATED_NODE_JS, VARIABLE_SETTERS_JS, } from './inspectScripts.js';
23
24
  import { DEFAULT_TREE_DEPTH, DEFAULT_TREE_LIMIT } from './inspectTree.js';
24
25
  import { inspectLayout } from './layout.js';
25
26
  import { DEEP_QUERY_JS, missingElementError, selectorArgsJS } from './targetNode.js';
27
+ import { evaluateInBdgWorld, resolveNodeInBdgWorld } from '../page/bdgWorld.js';
26
28
  import { createLogger } from '../../ui/logging/index.js';
27
29
  import { getErrorMessage } from '../../utils/errors.js';
28
30
  import { EXIT_CODES } from '../../utils/exitCodes.js';
@@ -36,12 +38,18 @@ const HINTS_BUDGET_MS = 1000;
36
38
  const RULES_BUDGET_MS = 5000;
37
39
  /** Distinguishes the object groups of concurrent calls */
38
40
  let groupCounter = 0;
39
- /** Page-side choice of a match: the index asked for, else the first rendered one (the first when none is) */
41
+ /**
42
+ * Page-side choice of a match: the index asked for, else the first visible
43
+ * one (rendered, not `visibility: hidden`, not `opacity: 0`), else the first
44
+ * rendered one, else the first
45
+ */
40
46
  const PICK_MATCH_JS = `function (i) {
41
47
  if (i !== null) return i;
42
- const shown = (el) => (el.checkVisibility ? el.checkVisibility() : el.getClientRects().length > 0);
43
- const first = Array.prototype.findIndex.call(this, shown);
44
- return first < 0 ? 0 : first;
48
+ const check = (el, options) => (el.checkVisibility ? el.checkVisibility(options) : el.getClientRects().length > 0);
49
+ const visible = Array.prototype.findIndex.call(this, (el) => check(el, { visibilityProperty: true, opacityProperty: true }));
50
+ if (visible >= 0) return visible;
51
+ const rendered = Array.prototype.findIndex.call(this, (el) => check(el, {}));
52
+ return rendered < 0 ? 0 : rendered;
45
53
  }`;
46
54
  /**
47
55
  * Inspect one element.
@@ -54,10 +62,20 @@ const PICK_MATCH_JS = `function (i) {
54
62
  */
55
63
  export async function inspectElement(cdp, params) {
56
64
  const started = Date.now();
65
+ if (params.why === 'all') {
66
+ const err = whyAllPropertyError();
67
+ throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.INVALID_ARGUMENTS);
68
+ }
69
+ const pseudoOf = /::?(before|after)\s*$/i.exec(params.selector)?.[1]?.toLowerCase();
70
+ const request = pseudoOf
71
+ ? { ...params, selector: params.selector.replace(/::?(before|after)\s*$/i, '') }
72
+ : params;
57
73
  const objectGroup = `bdg-inspect-${++groupCounter}`;
58
74
  try {
59
- const found = await findElement(cdp, params, objectGroup);
60
- const sources = await readSources(cdp, found.objectId, params, objectGroup);
75
+ const found = await findElement(cdp, request, objectGroup);
76
+ const sources = await readSources(cdp, found.objectId, request, objectGroup);
77
+ if (sources.raw.unknownWhy)
78
+ throwUnknownProperties([params.why ?? ''], sources);
61
79
  const propValues = sources.props ? checkedProps(sources.props, sources) : undefined;
62
80
  const built = buildInspectResult(sources, {
63
81
  selector: params.selector,
@@ -67,8 +85,14 @@ export async function inspectElement(cdp, params) {
67
85
  ...(params.all && { all: true }),
68
86
  ...(propValues && { propValues }),
69
87
  });
70
- const withCascade = { ...built, ...cascadeFields(cdp, sources) };
71
- const result = found.picked ? { ...withCascade, picked: found.picked } : withCascade;
88
+ const cascade = cascadeFields(cdp, sources);
89
+ const hints = cascade.hints && (await explainedHints(cdp, found.objectId, cascade.hints));
90
+ const withCascade = { ...built, ...cascade, ...(hints && { hints }) };
91
+ const result = {
92
+ ...withCascade,
93
+ ...(found.picked && { picked: found.picked }),
94
+ ...(pseudoOf && { pseudoOf: `::${pseudoOf}` }),
95
+ };
72
96
  log.debug(`Inspected ${result.element} in ${Date.now() - started} ms`);
73
97
  return result;
74
98
  }
@@ -78,6 +102,25 @@ export async function inspectElement(cdp, params) {
78
102
  .catch((error) => log.debug(`Object group not released: ${getErrorMessage(error)}`));
79
103
  }
80
104
  }
105
+ /**
106
+ * Hints with unset variables told where the page sets them
107
+ * ({@link VARIABLE_SETTERS_JS}); unchanged when there are none or the
108
+ * search fails.
109
+ *
110
+ * @param cdp - CDP connection
111
+ * @param objectId - The element
112
+ * @param hints - Hints
113
+ * @returns Hints
114
+ */
115
+ async function explainedHints(cdp, objectId, hints) {
116
+ const names = [...new Set(hints.flatMap((hint) => hint.variables ?? []))];
117
+ if (names.length === 0)
118
+ return hints;
119
+ const setters = await callOn(cdp, objectId, VARIABLE_SETTERS_JS, [
120
+ names,
121
+ ]);
122
+ return setters ? explainUnsetVariables(hints, setters) : hints;
123
+ }
81
124
  /**
82
125
  * The properties asked for with `--props`.
83
126
  *
@@ -87,9 +130,19 @@ export async function inspectElement(cdp, params) {
87
130
  * @throws CommandError (81) for a name no value was found for
88
131
  */
89
132
  function checkedProps(names, sources) {
90
- const { props, unknown } = selectedProps(names, sources.style, sources.raw.props, sources.raw.unknownProps);
133
+ const { props, unknown } = selectedProps(names, sources.style, sources.raw.props, sources.raw.unknownProps, sources.raw.rootFontSize);
91
134
  if (unknown.length === 0)
92
135
  return props;
136
+ return throwUnknownProperties(unknown, sources);
137
+ }
138
+ /**
139
+ * Reject names that are not CSS properties, with the closest computed ones.
140
+ *
141
+ * @param unknown - Names
142
+ * @param sources - What was read (computed property names)
143
+ * @throws CommandError (81) always
144
+ */
145
+ function throwUnknownProperties(unknown, sources) {
93
146
  const suggestions = unknown.flatMap((name) => findSimilar(name, Object.keys(sources.style), { maxSuggestions: 1 }));
94
147
  const err = unknownCssPropertyError(unknown, suggestions);
95
148
  throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.INVALID_ARGUMENTS);
@@ -130,11 +183,14 @@ function cascadeFields(cdp, sources) {
130
183
  style: sources.style,
131
184
  parentStyle: sources.parentStyle,
132
185
  replaced: sources.raw.replaced === true,
133
- formControl: sources.raw.formControl,
186
+ formControl: sources.raw.formControl && sources.raw.hasText,
134
187
  ...(sources.hints === false && { hints: false }),
135
188
  label: (declaration) => sourceLabel(declaration, cdp),
136
189
  ...(sources.rules && { rules: true }),
137
190
  ...(sources.why && { why: sources.why }),
191
+ ...(sources.raw.whyLonghands && { whyLonghands: sources.raw.whyLonghands }),
192
+ ...(sources.raw.whyComputed && { whyComputed: sources.raw.whyComputed }),
193
+ ...(sources.raw.whyInactive && { whyInactive: sources.raw.whyInactive }),
138
194
  ...(sources.props && { props: sources.props }),
139
195
  });
140
196
  }
@@ -193,9 +249,7 @@ function pickedHow(params, count, index) {
193
249
  * @returns Remote object id, or undefined when the node left the page
194
250
  */
195
251
  async function resolveCachedNode(cdp, backendNodeId, objectGroup) {
196
- const resolved = (await cdp
197
- .send('DOM.resolveNode', { backendNodeId, objectGroup })
198
- .catch((error) => {
252
+ const resolved = (await resolveNodeInBdgWorld(cdp, { backendNodeId, objectGroup }).catch((error) => {
199
253
  log.debug(`Node ${backendNodeId} not resolved: ${getErrorMessage(error)}`);
200
254
  return {};
201
255
  }));
@@ -215,10 +269,10 @@ async function resolveCachedNode(cdp, backendNodeId, objectGroup) {
215
269
  * @throws CommandError (81) invalid selector, (91) page script failure
216
270
  */
217
271
  async function querySelector(cdp, selector, objectGroup) {
218
- const response = (await cdp.send('Runtime.evaluate', {
272
+ const response = await evaluateInBdgWorld(cdp, {
219
273
  expression: `(${DEEP_QUERY_JS})(${selectorArgsJS(selector)})`,
220
274
  objectGroup,
221
- }));
275
+ });
222
276
  if (response.exceptionDetails || !response.result.objectId) {
223
277
  if (response.exceptionDetails)
224
278
  throwIfInvalidSelector(response.exceptionDetails, selector);
@@ -269,7 +323,7 @@ async function readSources(cdp, objectId, params, objectGroup) {
269
323
  return {
270
324
  raw,
271
325
  ...styles,
272
- fonts: raw.ownText || raw.formControl ? styles.fonts.node : styles.fonts.textHolder,
326
+ fonts: raw.textHolder ? styles.fonts.textHolder : styles.fonts.node,
273
327
  ...measured,
274
328
  ...(params.rules && { rules: true }),
275
329
  ...(params.why && { why: params.why }),
@@ -290,6 +344,7 @@ async function readPage(cdp, objectId, params) {
290
344
  const raw = await callOn(cdp, objectId, INSPECT_PAGE_JS, [
291
345
  params.props || params.all ? 0 : (params.tree ?? DEFAULT_TREE_DEPTH),
292
346
  params.props ?? null,
347
+ params.why ?? null,
293
348
  ]);
294
349
  if (raw)
295
350
  return raw;
@@ -297,11 +352,12 @@ async function readPage(cdp, objectId, params) {
297
352
  throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.SCRIPT_ERROR);
298
353
  }
299
354
  /**
300
- * The backend node id of the element's layout parent or first text holder.
355
+ * The backend node id of the element's layout parent, the element that
356
+ * draws most of its text, or the parent of that text's nodes.
301
357
  *
302
358
  * @param cdp - CDP connection
303
359
  * @param objectId - The element
304
- * @param which - `parent` or `textHolder`
360
+ * @param which - `parent`, `textHolder` or `fontHolder`
305
361
  * @param objectGroup - Object group for handles
306
362
  * @returns Backend node id, or undefined when there is none
307
363
  */
@@ -316,8 +372,8 @@ async function relatedNode(cdp, objectId, which, objectGroup) {
316
372
  return id ? (await describe(cdp, id)).backendNodeId : undefined;
317
373
  }
318
374
  /**
319
- * The backend node ids of the element, its layout parent, its first text
320
- * holder and its generated pseudo-elements.
375
+ * The backend node ids of the element, its layout parent, its text holder
376
+ * (with the parent of its text nodes) and its generated pseudo-elements.
321
377
  *
322
378
  * @param cdp - CDP connection
323
379
  * @param objectId - The element
@@ -325,10 +381,11 @@ async function relatedNode(cdp, objectId, which, objectGroup) {
325
381
  * @returns Backend node ids
326
382
  */
327
383
  async function relatedNodes(cdp, objectId, objectGroup) {
328
- const [node, parent, textHolder] = await Promise.all([
384
+ const [node, parent, textHolder, fontHolder] = await Promise.all([
329
385
  describe(cdp, objectId),
330
386
  relatedNode(cdp, objectId, 'parent', objectGroup),
331
387
  relatedNode(cdp, objectId, 'textHolder', objectGroup),
388
+ relatedNode(cdp, objectId, 'fontHolder', objectGroup),
332
389
  ]);
333
390
  const pseudo = (node.pseudoElements ?? [])
334
391
  .filter((p) => p.pseudoType === 'before' || p.pseudoType === 'after')
@@ -339,7 +396,8 @@ async function relatedNodes(cdp, objectId, objectGroup) {
339
396
  return {
340
397
  node: node.backendNodeId,
341
398
  ...(parent && { parent }),
342
- ...(textHolder && { textHolder }),
399
+ ...(textHolder && textHolder !== node.backendNodeId && { textHolder }),
400
+ ...(fontHolder && { fontHolder }),
343
401
  pseudo,
344
402
  };
345
403
  }
@@ -392,6 +450,7 @@ async function nodeIdLookup(cdp, related) {
392
450
  related.node,
393
451
  related.parent,
394
452
  related.textHolder,
453
+ related.fontHolder,
395
454
  ...related.pseudo.map((p) => p.backendNodeId),
396
455
  ];
397
456
  const ids = await pushNodes(cdp, order.filter((id) => id !== undefined));
@@ -408,18 +467,23 @@ async function nodeIdLookup(cdp, related) {
408
467
  async function readStyles(cdp, related, params) {
409
468
  await enableStyleDomains(cdp);
410
469
  const nodeIdOf = await nodeIdLookup(cdp, related);
411
- const [matched, style, parentStyle, nodeFonts, holderFonts, size, pseudo] = await Promise.all([
470
+ const optionalStyle = (backendNodeId) => backendNodeId === undefined
471
+ ? Promise.resolve(undefined)
472
+ : computedStyle(cdp, nodeIdOf(backendNodeId));
473
+ const [matched, style, parentStyle, holderStyle, nodeFonts, holderFonts, size, pseudo] = await Promise.all([
412
474
  readMatched(cdp, nodeIdOf(related.node), params),
413
475
  computedStyle(cdp, nodeIdOf(related.node)),
414
- related.parent === undefined ? undefined : computedStyle(cdp, nodeIdOf(related.parent)),
476
+ optionalStyle(related.parent),
477
+ optionalStyle(related.textHolder),
415
478
  platformFonts(cdp, nodeIdOf(related.node)),
416
- platformFonts(cdp, nodeIdOf(related.textHolder)),
479
+ platformFonts(cdp, nodeIdOf(related.fontHolder)),
417
480
  borderBoxSize(cdp, related.node),
418
481
  Promise.all(related.pseudo.map((p) => pseudoSource(cdp, p.type, p.backendNodeId, nodeIdOf(p.backendNodeId)))),
419
482
  ]);
420
483
  return {
421
484
  style,
422
485
  ...(parentStyle && { parentStyle }),
486
+ ...(holderStyle && { holderStyle }),
423
487
  pseudo,
424
488
  fonts: { node: nodeFonts, textHolder: holderFonts },
425
489
  ...(size && { size }),
@@ -466,7 +530,7 @@ async function pseudoSource(cdp, type, backendNodeId, nodeId) {
466
530
  *
467
531
  * @param cdp - CDP connection
468
532
  */
469
- async function enableStyleDomains(cdp) {
533
+ export async function enableStyleDomains(cdp) {
470
534
  if (stylesEnabled.has(cdp))
471
535
  return;
472
536
  trackStyleSheets(cdp);
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * `--all` lists every computed longhand that is not noise and not its
5
5
  * default, collapsed into shorthands (margin, padding, inset, border,
6
- * radius, overflow, gap, flex, grid area, outline, animation). Defaults are
6
+ * radius, overflow, gap, flex, grid area, outline, animation, transition). Defaults are
7
7
  * the CSS initial values as Chrome computes them; the UA stylesheet's
8
8
  * per-tag values (a `<p>`'s margins, a button's padding) are real values and
9
9
  * are listed. Display, font, size, line height and color are always listed.
10
10
  *
11
11
  * Noise: custom properties, logical duplicates of physical properties,
12
- * width/height (in the header), transitions, origins without a transform,
12
+ * width/height (in the header), origins without a transform,
13
13
  * colors that only repeat `color` (currentColor), properties of borders,
14
14
  * outlines and rules that are not drawn, SVG paint properties on HTML
15
15
  * elements, and vendor-prefixed internals.
@@ -34,15 +34,25 @@ export declare function isDefaultValue(name: string, value: string): boolean;
34
34
  * @returns Normalized value
35
35
  */
36
36
  export declare function normalizeProperty(name: string, value: string): string;
37
+ /**
38
+ * A shorthand's computed value as `--all` writes it (`margin 0 8`,
39
+ * `outline 2 solid #f00`, `transition color 1s ease-in`).
40
+ *
41
+ * @param shorthand - Shorthand name
42
+ * @param style - Computed longhands
43
+ * @returns Value, or undefined for a shorthand `--all` does not collapse
44
+ */
45
+ export declare function collapsedValue(shorthand: string, style: StyleMap): string | undefined;
37
46
  /**
38
47
  * Every computed longhand that is not noise and not a default, normalized
39
48
  * and collapsed into shorthands.
40
49
  *
41
50
  * @param style - Computed styles
42
51
  * @param svg - The element is an SVG element (SVG properties are listed)
52
+ * @param formControl - A form control (`appearance: none` is not its default)
43
53
  * @returns Properties and values
44
54
  */
45
- export declare function allStyles(style: StyleMap, svg: boolean): Record<string, string>;
55
+ export declare function allStyles(style: StyleMap, svg: boolean, formControl?: boolean): Record<string, string>;
46
56
  /**
47
57
  * The properties asked for with `--props`, raw and normalized. CDP's
48
58
  * computed longhands come first; shorthands and custom properties come from
@@ -52,10 +62,12 @@ export declare function allStyles(style: StyleMap, svg: boolean): Record<string,
52
62
  * @param style - Computed longhands (CDP)
53
63
  * @param pageValues - Values the page read
54
64
  * @param pageUnknown - Names the page does not know as CSS properties
65
+ * @param rootFontSize - Root font size (px): a custom property that is one
66
+ * rem length is also given in px
55
67
  * @returns Values by name (an unset custom property is empty), and the
56
68
  * names that are not properties
57
69
  */
58
- export declare function selectedProps(names: readonly string[], style: StyleMap, pageValues: Record<string, string> | undefined, pageUnknown?: readonly string[]): {
70
+ export declare function selectedProps(names: readonly string[], style: StyleMap, pageValues: Record<string, string> | undefined, pageUnknown?: readonly string[], rootFontSize?: number): {
59
71
  props: Record<string, InspectProp>;
60
72
  unknown: string[];
61
73
  };