browser-debugger-cli 0.12.0 → 0.14.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.
- package/.claude/skills/bdg/SKILL.md +100 -186
- package/README.md +5 -4
- package/dist/commands/cdp.d.ts +22 -1
- package/dist/commands/cdp.js +100 -43
- package/dist/commands/console.d.ts +12 -0
- package/dist/commands/console.js +67 -13
- package/dist/commands/dom/DomElementResolver.d.ts +3 -1
- package/dist/commands/dom/DomElementResolver.js +10 -3
- package/dist/commands/dom/a11y.d.ts +1 -1
- package/dist/commands/dom/a11y.js +23 -22
- package/dist/commands/dom/eval.d.ts +4 -2
- package/dist/commands/dom/eval.js +31 -7
- package/dist/commands/dom/form.js +10 -9
- package/dist/commands/dom/formInteraction.js +9 -8
- package/dist/commands/dom/get.js +32 -14
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/query.d.ts +27 -3
- package/dist/commands/dom/helpers/query.js +152 -64
- package/dist/commands/dom/helpers/screenshot.js +13 -13
- package/dist/commands/dom/index.js +10 -3
- package/dist/commands/dom/query.d.ts +20 -2
- package/dist/commands/dom/query.js +39 -6
- package/dist/commands/dom/screenshot.js +3 -1
- package/dist/commands/dom/semanticUtils.d.ts +3 -2
- package/dist/commands/dom/semanticUtils.js +40 -9
- package/dist/commands/helpJson.d.ts +82 -19
- package/dist/commands/helpJson.js +112 -41
- package/dist/commands/helpTopic.d.ts +16 -1
- package/dist/commands/helpTopic.js +59 -1
- package/dist/commands/installSkill.d.ts +15 -5
- package/dist/commands/installSkill.js +86 -16
- package/dist/commands/network/list.js +65 -12
- package/dist/commands/optionBehaviors.d.ts +25 -2
- package/dist/commands/optionBehaviors.js +81 -46
- package/dist/commands/peek.js +3 -0
- package/dist/commands/shared/CommandRunner.js +13 -13
- package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
- package/dist/commands/shared/daemonErrorHandler.js +21 -10
- package/dist/commands/shared/dataFetcher.d.ts +14 -4
- package/dist/commands/shared/dataFetcher.js +20 -4
- package/dist/commands/shared/followMode.d.ts +9 -1
- package/dist/commands/shared/followMode.js +22 -4
- package/dist/commands/shared/handleValidationError.js +3 -3
- package/dist/commands/shared/optionTypes.d.ts +17 -3
- package/dist/commands/shared/outputFile.js +6 -1
- package/dist/commands/shared/startHelpers.js +3 -3
- package/dist/commands/start.d.ts +7 -5
- package/dist/commands/start.js +65 -21
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.js +24 -1
- package/dist/commands.js +1 -1
- package/dist/connection/cdp.d.ts +7 -0
- package/dist/connection/cdp.js +9 -0
- package/dist/connection/chromeIdentity.d.ts +8 -2
- package/dist/connection/chromeIdentity.js +85 -13
- package/dist/connection/launcher.js +3 -2
- package/dist/constants.d.ts +29 -1
- package/dist/constants.js +35 -1
- package/dist/daemon/SessionController.js +8 -1
- package/dist/daemon/launcher.d.ts +3 -2
- package/dist/daemon/launcher.js +47 -3
- package/dist/daemon/session/Session.d.ts +5 -1
- package/dist/daemon/session/Session.js +42 -3
- package/dist/daemon/session/TelemetryStore.d.ts +15 -1
- package/dist/daemon/session/TelemetryStore.js +19 -1
- package/dist/daemon/session/commandRegistry.js +52 -18
- package/dist/daemon/session/interactions.d.ts +2 -1
- package/dist/daemon/session/interactions.js +13 -1
- package/dist/daemon/session/matchedStylesReset.d.ts +26 -0
- package/dist/daemon/session/matchedStylesReset.js +46 -0
- package/dist/daemon/session/plugins.js +17 -2
- package/dist/daemon/session/teardown.js +1 -1
- package/dist/daemon/session/triggeredRequests.d.ts +0 -5
- package/dist/daemon/session/triggeredRequests.js +13 -7
- package/dist/daemon.js +2385 -1229
- package/dist/errors/messages.d.ts +62 -11
- package/dist/errors/messages.js +119 -22
- package/dist/index.js +14995 -9866
- package/dist/ipc/client.d.ts +18 -2
- package/dist/ipc/client.js +26 -5
- package/dist/ipc/protocol/auditTypes.d.ts +8 -2
- package/dist/ipc/protocol/commands.d.ts +16 -0
- package/dist/ipc/protocol/domTypes.d.ts +12 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +7 -2
- package/dist/ipc/session/types.d.ts +7 -1
- package/dist/program.d.ts +14 -0
- package/dist/program.js +53 -0
- package/dist/runtime/dom/actionEffects.d.ts +5 -1
- package/dist/runtime/dom/actionEffects.js +26 -14
- package/dist/runtime/dom/audit.js +3 -2
- package/dist/runtime/dom/auditModel.js +6 -1
- package/dist/runtime/dom/auditScripts.d.ts +9 -3
- package/dist/runtime/dom/auditScripts.js +41 -5
- package/dist/runtime/dom/elementGeometry.d.ts +33 -3
- package/dist/runtime/dom/elementGeometry.js +44 -19
- package/dist/runtime/dom/elementInfo.d.ts +76 -18
- package/dist/runtime/dom/elementInfo.js +190 -40
- package/dist/runtime/dom/evalHelpers.d.ts +12 -2
- package/dist/runtime/dom/evalHelpers.js +67 -7
- package/dist/runtime/dom/formDiscovery.d.ts +6 -2
- package/dist/runtime/dom/formDiscovery.js +20 -3
- package/dist/runtime/dom/formFillHelpers/fill.js +7 -11
- package/dist/runtime/dom/formFillHelpers/pressKey.js +2 -2
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +16 -10
- package/dist/runtime/dom/formFillHelpers/shared.js +19 -52
- package/dist/runtime/dom/formSubmitHelpers.js +4 -3
- package/dist/runtime/dom/frameLayout.js +1 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +7 -0
- package/dist/runtime/dom/frameScopedConnection.js +2 -2
- package/dist/runtime/dom/inspect.d.ts +17 -3
- package/dist/runtime/dom/inspect.js +45 -32
- package/dist/runtime/dom/inspectAllStyles.js +1 -0
- package/dist/runtime/dom/inspectHints.d.ts +1 -1
- package/dist/runtime/dom/inspectModel.d.ts +5 -4
- package/dist/runtime/dom/inspectModel.js +7 -3
- package/dist/runtime/dom/inspectPaintModel.d.ts +2 -0
- package/dist/runtime/dom/inspectPaintModel.js +3 -1
- package/dist/runtime/dom/inspectRules.d.ts +29 -3
- package/dist/runtime/dom/inspectRules.js +205 -11
- package/dist/runtime/dom/inspectScripts.d.ts +29 -2
- package/dist/runtime/dom/inspectScripts.js +49 -10
- package/dist/runtime/dom/layout.d.ts +0 -2
- package/dist/runtime/dom/layout.js +10 -9
- package/dist/runtime/dom/reactEventHelpers.d.ts +17 -4
- package/dist/runtime/dom/reactEventHelpers.js +71 -28
- package/dist/runtime/dom/targetNode.d.ts +27 -10
- package/dist/runtime/dom/targetNode.js +283 -16
- package/dist/runtime/dom/wait.js +2 -1
- package/dist/runtime/page/bdgWorld.d.ts +57 -0
- package/dist/runtime/page/bdgWorld.js +180 -0
- package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
- package/dist/runtime/page/replacedBuiltins.js +136 -0
- package/dist/session/QueryCacheManager.d.ts +4 -1
- package/dist/session/QueryCacheManager.js +5 -2
- package/dist/session/chrome.d.ts +4 -1
- package/dist/session/chrome.js +7 -1
- package/dist/session/cleanup/staleSession.d.ts +21 -4
- package/dist/session/cleanup/staleSession.js +79 -9
- package/dist/session/cleanup/userCommands.d.ts +4 -1
- package/dist/session/cleanup/userCommands.js +10 -5
- package/dist/session/daemonSocket.d.ts +10 -0
- package/dist/session/daemonSocket.js +22 -0
- package/dist/session/lastSession.d.ts +6 -3
- package/dist/session/lastSession.js +11 -5
- package/dist/session/paths.d.ts +3 -1
- package/dist/session/paths.js +5 -5
- package/dist/session/portClaims.js +4 -3
- package/dist/session/sessionList.d.ts +13 -5
- package/dist/session/sessionList.js +31 -7
- package/dist/telemetry/a11y.d.ts +15 -1
- package/dist/telemetry/a11y.js +85 -2
- package/dist/telemetry/console.d.ts +2 -1
- package/dist/telemetry/console.js +30 -21
- package/dist/telemetry/har/builder.js +1 -1
- package/dist/telemetry/network.d.ts +13 -16
- package/dist/telemetry/network.js +30 -52
- package/dist/telemetry/networkRetention.d.ts +83 -0
- package/dist/telemetry/networkRetention.js +117 -0
- package/dist/telemetry/pageCrash.d.ts +26 -0
- package/dist/telemetry/pageCrash.js +53 -0
- package/dist/types.d.ts +42 -0
- package/dist/ui/OutputBuilder.d.ts +10 -0
- package/dist/ui/OutputBuilder.js +12 -0
- package/dist/ui/formatters/a11y.d.ts +5 -7
- package/dist/ui/formatters/a11y.js +7 -61
- package/dist/ui/formatters/audit.js +14 -5
- package/dist/ui/formatters/cdp.d.ts +138 -0
- package/dist/ui/formatters/cdp.js +131 -0
- package/dist/ui/formatters/console/chronological.js +7 -5
- package/dist/ui/formatters/console/follow.d.ts +5 -2
- package/dist/ui/formatters/console/follow.js +7 -4
- package/dist/ui/formatters/console/json.d.ts +4 -7
- package/dist/ui/formatters/console/json.js +16 -14
- package/dist/ui/formatters/console/shared.d.ts +47 -2
- package/dist/ui/formatters/console/shared.js +33 -0
- package/dist/ui/formatters/console/summarize.d.ts +9 -2
- package/dist/ui/formatters/console/summarize.js +57 -11
- package/dist/ui/formatters/console.d.ts +3 -2
- package/dist/ui/formatters/console.js +8 -10
- package/dist/ui/formatters/details.js +4 -2
- package/dist/ui/formatters/dom.d.ts +14 -5
- package/dist/ui/formatters/dom.js +30 -13
- package/dist/ui/formatters/helpFormatters.js +1 -1
- package/dist/ui/formatters/inspect.js +9 -3
- package/dist/ui/formatters/installSkill.d.ts +9 -1
- package/dist/ui/formatters/installSkill.js +32 -6
- package/dist/ui/formatters/layout.js +4 -2
- package/dist/ui/formatters/longValues.d.ts +14 -0
- package/dist/ui/formatters/longValues.js +23 -0
- package/dist/ui/formatters/networkList.d.ts +8 -2
- package/dist/ui/formatters/networkList.js +11 -3
- package/dist/ui/formatters/preview.d.ts +6 -1
- package/dist/ui/formatters/preview.js +67 -15
- package/dist/ui/formatters/sessions.d.ts +2 -2
- package/dist/ui/formatters/sessions.js +9 -2
- package/dist/ui/formatters/status.js +7 -0
- package/dist/ui/formatters/triggeredRequests.js +2 -1
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/chrome.d.ts +20 -1
- package/dist/ui/messages/chrome.js +29 -3
- package/dist/ui/messages/commands.d.ts +153 -12
- package/dist/ui/messages/commands.js +198 -15
- package/dist/ui/messages/consoleMessages.d.ts +24 -0
- package/dist/ui/messages/consoleMessages.js +32 -0
- package/dist/ui/messages/networkMessages.d.ts +24 -0
- package/dist/ui/messages/networkMessages.js +45 -0
- package/dist/ui/messages/preview.d.ts +6 -0
- package/dist/ui/messages/preview.js +9 -1
- package/dist/ui/messages/session.d.ts +13 -2
- package/dist/ui/messages/session.js +22 -3
- package/dist/utils/directories.d.ts +34 -0
- package/dist/utils/directories.js +88 -0
- package/dist/utils/display.d.ts +16 -0
- package/dist/utils/display.js +42 -0
- package/dist/utils/exitCodes.d.ts +1 -0
- package/dist/utils/exitCodes.js +6 -0
- package/dist/utils/http.d.ts +9 -2
- package/dist/utils/http.js +4 -3
- package/dist/utils/process.d.ts +12 -0
- package/dist/utils/process.js +25 -0
- package/dist/utils/strings.d.ts +19 -0
- package/dist/utils/strings.js +16 -0
- package/package.json +2 -2
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the network collector keeps of a long session: the newest finished
|
|
3
|
+
* requests up to a cap, and the newest response bodies up to a total size.
|
|
4
|
+
*/
|
|
5
|
+
import type { NetworkRequest } from '../types.js';
|
|
6
|
+
/** Counts of what the session let go at its limits */
|
|
7
|
+
export interface NetworkEvictions {
|
|
8
|
+
/** Finished requests dropped at the request cap, oldest first */
|
|
9
|
+
requestsDropped: number;
|
|
10
|
+
/** Response bodies replaced by a placeholder at the total body budget, oldest first */
|
|
11
|
+
bodiesEvicted: number;
|
|
12
|
+
}
|
|
13
|
+
/** Limits of {@link RequestRetention} */
|
|
14
|
+
export interface RetentionLimits {
|
|
15
|
+
/** Finished requests kept at most */
|
|
16
|
+
maxRequests: number;
|
|
17
|
+
/** Total size of the stored response bodies (bytes) */
|
|
18
|
+
maxTotalBodyBytes: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Keeps finished requests, oldest first, dropping the oldest past the cap
|
|
22
|
+
* (requests in flight are never in the list, so never dropped), and tracks
|
|
23
|
+
* the size of their stored bodies, replacing the oldest bodies past the
|
|
24
|
+
* budget with a placeholder that says why.
|
|
25
|
+
*
|
|
26
|
+
* Stored bodies are kept in a Map, which iterates in insertion order: its
|
|
27
|
+
* first entry is the oldest body, and a dropped request's body is removed in
|
|
28
|
+
* O(1). Dropping from the front of the list is `Array.shift`, which V8 does
|
|
29
|
+
* without copying for arrays of this size.
|
|
30
|
+
*/
|
|
31
|
+
export declare class RequestRetention {
|
|
32
|
+
private readonly requests;
|
|
33
|
+
private readonly limits;
|
|
34
|
+
private readonly evictions;
|
|
35
|
+
private readonly bodySizes;
|
|
36
|
+
private storedBodyBytes;
|
|
37
|
+
/**
|
|
38
|
+
* @param requests - Finished requests, oldest first (updated in place)
|
|
39
|
+
* @param limits - Request cap and body budget
|
|
40
|
+
* @param evictions - Counters updated on each drop and eviction
|
|
41
|
+
*/
|
|
42
|
+
constructor(requests: NetworkRequest[], limits: RetentionLimits, evictions: NetworkEvictions);
|
|
43
|
+
/**
|
|
44
|
+
* Add a finished request, dropping the oldest one past the cap.
|
|
45
|
+
*
|
|
46
|
+
* @param request - Finished request
|
|
47
|
+
* @returns The dropped request, if one was
|
|
48
|
+
*/
|
|
49
|
+
add(request: NetworkRequest): NetworkRequest | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Store a fetched response body on a kept request, then evict the oldest
|
|
52
|
+
* bodies until the total fits the budget (a body larger than the whole
|
|
53
|
+
* budget is evicted itself). Storing a body again replaces the earlier one.
|
|
54
|
+
*
|
|
55
|
+
* @param request - Request the body belongs to
|
|
56
|
+
* @param body - Body as Chrome returned it
|
|
57
|
+
* @param base64Encoded - Whether `body` is base64
|
|
58
|
+
*/
|
|
59
|
+
storeBody(request: NetworkRequest, body: string, base64Encoded: boolean): void;
|
|
60
|
+
/** Evict the oldest stored bodies while their total is over the budget. */
|
|
61
|
+
private enforceBodyBudget;
|
|
62
|
+
/**
|
|
63
|
+
* Stop counting a request's stored body.
|
|
64
|
+
*
|
|
65
|
+
* @param request - Request whose body is let go
|
|
66
|
+
*/
|
|
67
|
+
private forgetBody;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Placeholder stored instead of a response body that was not fetched.
|
|
71
|
+
*
|
|
72
|
+
* @param reason - Why the body was skipped
|
|
73
|
+
* @returns Placeholder text shown by `bdg details`
|
|
74
|
+
*/
|
|
75
|
+
export declare function skippedBodyPlaceholder(reason: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Extract the reason from a skipped-body placeholder.
|
|
78
|
+
*
|
|
79
|
+
* @param body - Stored response body
|
|
80
|
+
* @returns Reason if `body` is a placeholder, otherwise undefined
|
|
81
|
+
*/
|
|
82
|
+
export declare function skippedBodyReason(body: string | undefined): string | undefined;
|
|
83
|
+
//# sourceMappingURL=networkRetention.d.ts.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the network collector keeps of a long session: the newest finished
|
|
3
|
+
* requests up to a cap, and the newest response bodies up to a total size.
|
|
4
|
+
*/
|
|
5
|
+
import { bodyEvictedReason } from '../ui/messages/networkMessages.js';
|
|
6
|
+
/**
|
|
7
|
+
* Keeps finished requests, oldest first, dropping the oldest past the cap
|
|
8
|
+
* (requests in flight are never in the list, so never dropped), and tracks
|
|
9
|
+
* the size of their stored bodies, replacing the oldest bodies past the
|
|
10
|
+
* budget with a placeholder that says why.
|
|
11
|
+
*
|
|
12
|
+
* Stored bodies are kept in a Map, which iterates in insertion order: its
|
|
13
|
+
* first entry is the oldest body, and a dropped request's body is removed in
|
|
14
|
+
* O(1). Dropping from the front of the list is `Array.shift`, which V8 does
|
|
15
|
+
* without copying for arrays of this size.
|
|
16
|
+
*/
|
|
17
|
+
export class RequestRetention {
|
|
18
|
+
requests;
|
|
19
|
+
limits;
|
|
20
|
+
evictions;
|
|
21
|
+
bodySizes = new Map();
|
|
22
|
+
storedBodyBytes = 0;
|
|
23
|
+
/**
|
|
24
|
+
* @param requests - Finished requests, oldest first (updated in place)
|
|
25
|
+
* @param limits - Request cap and body budget
|
|
26
|
+
* @param evictions - Counters updated on each drop and eviction
|
|
27
|
+
*/
|
|
28
|
+
constructor(requests, limits, evictions) {
|
|
29
|
+
this.requests = requests;
|
|
30
|
+
this.limits = limits;
|
|
31
|
+
this.evictions = evictions;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Add a finished request, dropping the oldest one past the cap.
|
|
35
|
+
*
|
|
36
|
+
* @param request - Finished request
|
|
37
|
+
* @returns The dropped request, if one was
|
|
38
|
+
*/
|
|
39
|
+
add(request) {
|
|
40
|
+
this.requests.push(request);
|
|
41
|
+
if (this.requests.length <= this.limits.maxRequests)
|
|
42
|
+
return undefined;
|
|
43
|
+
const dropped = this.requests.shift();
|
|
44
|
+
if (!dropped)
|
|
45
|
+
return undefined;
|
|
46
|
+
this.evictions.requestsDropped++;
|
|
47
|
+
this.forgetBody(dropped);
|
|
48
|
+
return dropped;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Store a fetched response body on a kept request, then evict the oldest
|
|
52
|
+
* bodies until the total fits the budget (a body larger than the whole
|
|
53
|
+
* budget is evicted itself). Storing a body again replaces the earlier one.
|
|
54
|
+
*
|
|
55
|
+
* @param request - Request the body belongs to
|
|
56
|
+
* @param body - Body as Chrome returned it
|
|
57
|
+
* @param base64Encoded - Whether `body` is base64
|
|
58
|
+
*/
|
|
59
|
+
storeBody(request, body, base64Encoded) {
|
|
60
|
+
this.forgetBody(request);
|
|
61
|
+
request.responseBody = body;
|
|
62
|
+
if (base64Encoded)
|
|
63
|
+
request.responseBodyBase64 = true;
|
|
64
|
+
if (body) {
|
|
65
|
+
request.decodedBodyLength = Buffer.byteLength(body, base64Encoded ? 'base64' : 'utf-8');
|
|
66
|
+
}
|
|
67
|
+
const size = Buffer.byteLength(body);
|
|
68
|
+
this.bodySizes.set(request, size);
|
|
69
|
+
this.storedBodyBytes += size;
|
|
70
|
+
this.enforceBodyBudget();
|
|
71
|
+
}
|
|
72
|
+
/** Evict the oldest stored bodies while their total is over the budget. */
|
|
73
|
+
enforceBodyBudget() {
|
|
74
|
+
while (this.storedBodyBytes > this.limits.maxTotalBodyBytes) {
|
|
75
|
+
const oldest = this.bodySizes.keys().next();
|
|
76
|
+
if (oldest.done)
|
|
77
|
+
return;
|
|
78
|
+
const request = oldest.value;
|
|
79
|
+
this.forgetBody(request);
|
|
80
|
+
request.responseBody = skippedBodyPlaceholder(bodyEvictedReason(this.limits.maxTotalBodyBytes));
|
|
81
|
+
delete request.responseBodyBase64;
|
|
82
|
+
this.evictions.bodiesEvicted++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Stop counting a request's stored body.
|
|
87
|
+
*
|
|
88
|
+
* @param request - Request whose body is let go
|
|
89
|
+
*/
|
|
90
|
+
forgetBody(request) {
|
|
91
|
+
const size = this.bodySizes.get(request);
|
|
92
|
+
if (size === undefined)
|
|
93
|
+
return;
|
|
94
|
+
this.bodySizes.delete(request);
|
|
95
|
+
this.storedBodyBytes -= size;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const SKIPPED_BODY_PATTERN = /^\[SKIPPED: (.*)\]$/s;
|
|
99
|
+
/**
|
|
100
|
+
* Placeholder stored instead of a response body that was not fetched.
|
|
101
|
+
*
|
|
102
|
+
* @param reason - Why the body was skipped
|
|
103
|
+
* @returns Placeholder text shown by `bdg details`
|
|
104
|
+
*/
|
|
105
|
+
export function skippedBodyPlaceholder(reason) {
|
|
106
|
+
return `[SKIPPED: ${reason}]`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Extract the reason from a skipped-body placeholder.
|
|
110
|
+
*
|
|
111
|
+
* @param body - Stored response body
|
|
112
|
+
* @returns Reason if `body` is a placeholder, otherwise undefined
|
|
113
|
+
*/
|
|
114
|
+
export function skippedBodyReason(body) {
|
|
115
|
+
return body === undefined ? undefined : SKIPPED_BODY_PATTERN.exec(body)?.[1];
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=networkRetention.js.map
|
|
@@ -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
|
@@ -204,6 +204,8 @@ export interface ConsoleMessage {
|
|
|
204
204
|
stackTrace?: StackFrame[];
|
|
205
205
|
/** Browser subsystem of a browser message (`network`, `security`, ...); absent for page console calls */
|
|
206
206
|
source?: Protocol.Log.LogEntry['source'];
|
|
207
|
+
/** Original length of `text` when JSON output cut it (`--full` keeps it whole) */
|
|
208
|
+
truncatedFrom?: number;
|
|
207
209
|
}
|
|
208
210
|
/**
|
|
209
211
|
* Console message level categories for user-facing filtering.
|
|
@@ -226,10 +228,18 @@ export interface BdgOutput {
|
|
|
226
228
|
};
|
|
227
229
|
/** Navigation id of the page currently loaded (live previews) */
|
|
228
230
|
currentNavigationId?: number;
|
|
231
|
+
/** When the page's renderer crashed (epoch ms), while it is not loaded again */
|
|
232
|
+
pageCrashedAt?: number;
|
|
229
233
|
/** Counts of all captured items matching the request (e.g. `peek --type`), when `data` holds only the most recent ones */
|
|
230
234
|
totals?: {
|
|
231
235
|
network: number;
|
|
232
236
|
console: number;
|
|
237
|
+
/** Console messages dropped at the limit, oldest first (indices start after them) */
|
|
238
|
+
consoleDropped?: number;
|
|
239
|
+
/** Finished network requests dropped at the request cap, oldest first */
|
|
240
|
+
networkDropped?: number;
|
|
241
|
+
/** Response bodies evicted at the total body budget, oldest first */
|
|
242
|
+
networkBodiesEvicted?: number;
|
|
233
243
|
};
|
|
234
244
|
error?: string;
|
|
235
245
|
partial?: boolean;
|
|
@@ -282,6 +292,24 @@ export interface A11yTree {
|
|
|
282
292
|
/** Total node count */
|
|
283
293
|
count: number;
|
|
284
294
|
}
|
|
295
|
+
/** An accessibility node as `dom a11y tree` lists it */
|
|
296
|
+
export type ListedA11yNode = Omit<A11yNode, 'childIds'> & {
|
|
297
|
+
/** Indentation level (0 = root; left-out wrappers add none) */
|
|
298
|
+
depth: number;
|
|
299
|
+
};
|
|
300
|
+
/**
|
|
301
|
+
* The part of an accessibility tree `dom a11y tree` lists (`--limit`, `--depth`).
|
|
302
|
+
*/
|
|
303
|
+
export interface ListedA11yTree {
|
|
304
|
+
/** Listed nodes, depth-first from the root */
|
|
305
|
+
nodes: ListedA11yNode[];
|
|
306
|
+
/** Nodes in the whole tree (listed + omitted + skipped) */
|
|
307
|
+
count: number;
|
|
308
|
+
/** Nodes left out by `--limit` or `--depth` */
|
|
309
|
+
omitted?: number;
|
|
310
|
+
/** Nodes never listed: text boxes, blank or repeated text, nameless layout wrappers */
|
|
311
|
+
skipped?: number;
|
|
312
|
+
}
|
|
285
313
|
/**
|
|
286
314
|
* Query pattern for searching accessibility tree.
|
|
287
315
|
*
|
|
@@ -327,6 +355,8 @@ export interface DomContext {
|
|
|
327
355
|
children?: string[];
|
|
328
356
|
/** Number of child elements, for an element without text */
|
|
329
357
|
childCount?: number;
|
|
358
|
+
/** The children listed are those of its shadow root (a web component) */
|
|
359
|
+
shadowChildren?: boolean;
|
|
330
360
|
/** Attributes that identify it by its type (see {@link KeyAttributes}) */
|
|
331
361
|
attributes?: KeyAttributes;
|
|
332
362
|
/** A field holding a secret (password, card, one-time code): its value is shown masked */
|
|
@@ -438,6 +468,14 @@ export interface DomQueryResult {
|
|
|
438
468
|
/** Unique selector for this node (set by form discovery) */
|
|
439
469
|
selector?: string;
|
|
440
470
|
}>;
|
|
471
|
+
/** Matches not listed (`--limit`); `count` is all of them */
|
|
472
|
+
omitted?: number;
|
|
473
|
+
/** Matches usable by index (described and cached), when fewer than `count` */
|
|
474
|
+
indexed?: number;
|
|
475
|
+
/** First matches whose viewport position was checked (`inViewport`), when more are listed */
|
|
476
|
+
viewportChecked?: number;
|
|
477
|
+
/** Identity of the page document the matches belong to (cached results only) */
|
|
478
|
+
document?: string;
|
|
441
479
|
}
|
|
442
480
|
/**
|
|
443
481
|
* Result of a DOM get operation.
|
|
@@ -449,6 +487,8 @@ export interface DomGetResult {
|
|
|
449
487
|
attributes?: Record<string, unknown>;
|
|
450
488
|
classes?: string[];
|
|
451
489
|
outerHTML?: string;
|
|
490
|
+
/** Original length of `outerHTML` when JSON output cut it (`--full` keeps it whole) */
|
|
491
|
+
truncatedFrom?: number;
|
|
452
492
|
}>;
|
|
453
493
|
}
|
|
454
494
|
/**
|
|
@@ -679,5 +719,7 @@ export interface InstalledSkill {
|
|
|
679
719
|
target: SkillTarget;
|
|
680
720
|
path: string;
|
|
681
721
|
status: 'installed' | 'updated' | 'unchanged';
|
|
722
|
+
/** Where the replaced copy was kept (`updated` only) */
|
|
723
|
+
backup?: string;
|
|
682
724
|
}
|
|
683
725
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -9,6 +9,16 @@ import type { BdgResponse } from '../types.js';
|
|
|
9
9
|
* @returns `{ version, success: true, data }`
|
|
10
10
|
*/
|
|
11
11
|
export declare function buildSuccessResponse<T>(data: T): BdgResponse<T>;
|
|
12
|
+
/**
|
|
13
|
+
* Serialize a `--json` response envelope for stdout.
|
|
14
|
+
*
|
|
15
|
+
* Indented by two spaces when stdout is a terminal, so a person can read it;
|
|
16
|
+
* on one line otherwise, since agents and pipes only pay for the whitespace.
|
|
17
|
+
*
|
|
18
|
+
* @param envelope - Response envelope (or other `--json` payload)
|
|
19
|
+
* @returns JSON text
|
|
20
|
+
*/
|
|
21
|
+
export declare function stringifyEnvelope(envelope: unknown): string;
|
|
12
22
|
/** Builders for JSON error envelopes. */
|
|
13
23
|
export declare class OutputBuilder {
|
|
14
24
|
/**
|
package/dist/ui/OutputBuilder.js
CHANGED
|
@@ -11,6 +11,18 @@ import { VERSION } from '../utils/version.js';
|
|
|
11
11
|
export function buildSuccessResponse(data) {
|
|
12
12
|
return { version: VERSION, success: true, data };
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Serialize a `--json` response envelope for stdout.
|
|
16
|
+
*
|
|
17
|
+
* Indented by two spaces when stdout is a terminal, so a person can read it;
|
|
18
|
+
* on one line otherwise, since agents and pipes only pay for the whitespace.
|
|
19
|
+
*
|
|
20
|
+
* @param envelope - Response envelope (or other `--json` payload)
|
|
21
|
+
* @returns JSON text
|
|
22
|
+
*/
|
|
23
|
+
export function stringifyEnvelope(envelope) {
|
|
24
|
+
return process.stdout.isTTY ? JSON.stringify(envelope, null, 2) : JSON.stringify(envelope);
|
|
25
|
+
}
|
|
14
26
|
/** Builders for JSON error envelopes. */
|
|
15
27
|
export class OutputBuilder {
|
|
16
28
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DomContext } from '../../types.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { A11yQueryResult, A11yNode, ListedA11yTree } from '../../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Data structure for a11y node with DOM context.
|
|
5
5
|
*/
|
|
@@ -8,15 +8,13 @@ interface A11yNodeWithContext {
|
|
|
8
8
|
domContext: DomContext | null;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Format accessibility tree for human-readable output
|
|
11
|
+
* Format the listed part of an accessibility tree for human-readable output:
|
|
12
|
+
* one indented line per node, and when nodes were cut, how to see more.
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
-
* Shows up to 50 nodes by default for manageable output.
|
|
15
|
-
*
|
|
16
|
-
* @param tree - Accessibility tree data
|
|
14
|
+
* @param tree - Listed accessibility tree
|
|
17
15
|
* @returns Formatted output string
|
|
18
16
|
*/
|
|
19
|
-
export declare function formatA11yTree(tree:
|
|
17
|
+
export declare function formatA11yTree(tree: ListedA11yTree): string;
|
|
20
18
|
/**
|
|
21
19
|
* Format query result for human-readable output.
|
|
22
20
|
*
|
|
@@ -1,79 +1,25 @@
|
|
|
1
1
|
import { OutputFormatter, areHintsHidden } from '../formatting.js';
|
|
2
|
-
import { a11yMoreMatchesNote } from '../messages/commands.js';
|
|
3
|
-
/**
|
|
4
|
-
* Maximum number of nodes to display in tree output before truncating.
|
|
5
|
-
* Prevents overwhelming terminal output for large accessibility trees.
|
|
6
|
-
*/
|
|
7
|
-
const MAX_TREE_NODES_DISPLAY = 50;
|
|
2
|
+
import { a11yMoreMatchesNote, a11yTreeMoreNote, a11yTreeShownNote, } from '../messages/commands.js';
|
|
8
3
|
/**
|
|
9
4
|
* Separator width for section dividers in formatted output.
|
|
10
5
|
*/
|
|
11
6
|
const SEPARATOR_WIDTH = 50;
|
|
12
7
|
/**
|
|
13
|
-
* Format accessibility tree for human-readable output
|
|
14
|
-
*
|
|
15
|
-
* Displays the tree structure with role, name, and key properties.
|
|
16
|
-
* Shows up to 50 nodes by default for manageable output.
|
|
8
|
+
* Format the listed part of an accessibility tree for human-readable output:
|
|
9
|
+
* one indented line per node, and when nodes were cut, how to see more.
|
|
17
10
|
*
|
|
18
|
-
* @param tree -
|
|
11
|
+
* @param tree - Listed accessibility tree
|
|
19
12
|
* @returns Formatted output string
|
|
20
13
|
*/
|
|
21
14
|
export function formatA11yTree(tree) {
|
|
22
15
|
const fmt = new OutputFormatter();
|
|
23
16
|
fmt.text(`Accessibility Tree (${tree.count} nodes)`).separator('─', SEPARATOR_WIDTH).blank();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fmt
|
|
28
|
-
.blank()
|
|
29
|
-
.text(`Showing the first ${MAX_TREE_NODES_DISPLAY} nodes (text boxes and repeated text left out)`)
|
|
30
|
-
.text('Use --json flag for complete output, or bdg dom a11y query "role:<role>" to search');
|
|
17
|
+
tree.nodes.forEach((node) => fmt.text(' '.repeat(node.depth) + formatA11yNodeOneLine(node)));
|
|
18
|
+
if (tree.omitted) {
|
|
19
|
+
fmt.blank().text(a11yTreeShownNote(tree.nodes.length)).text(a11yTreeMoreNote(tree.omitted));
|
|
31
20
|
}
|
|
32
21
|
return fmt.build();
|
|
33
22
|
}
|
|
34
|
-
/** Roles that only lay out their children and say nothing themselves */
|
|
35
|
-
const LAYOUT_ROLES = new Set([
|
|
36
|
-
'generic',
|
|
37
|
-
'none',
|
|
38
|
-
'presentation',
|
|
39
|
-
'LayoutTable',
|
|
40
|
-
'LayoutTableRow',
|
|
41
|
-
'LayoutTableCell',
|
|
42
|
-
]);
|
|
43
|
-
/**
|
|
44
|
-
* The tree as indented lines, depth-first from the root. Text boxes, blank
|
|
45
|
-
* text, text that repeats its parent's name, and nameless layout wrappers are left out
|
|
46
|
-
* (their children move up a level), so the budget goes to meaningful nodes.
|
|
47
|
-
*
|
|
48
|
-
* @param tree - Accessibility tree
|
|
49
|
-
* @returns Up to {@link MAX_TREE_NODES_DISPLAY} lines, and whether nodes were left
|
|
50
|
-
*/
|
|
51
|
-
function treeLines(tree) {
|
|
52
|
-
const lines = [];
|
|
53
|
-
const visited = new Set();
|
|
54
|
-
let truncated = false;
|
|
55
|
-
const visit = (node, depth, parentName) => {
|
|
56
|
-
if (visited.has(node.nodeId))
|
|
57
|
-
return;
|
|
58
|
-
visited.add(node.nodeId);
|
|
59
|
-
if (lines.length >= MAX_TREE_NODES_DISPLAY) {
|
|
60
|
-
truncated = true;
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const skip = node.role === 'InlineTextBox' ||
|
|
64
|
-
(node.role === 'StaticText' && (node.name === parentName || !node.name?.trim())) ||
|
|
65
|
-
(LAYOUT_ROLES.has(node.role) && !node.name);
|
|
66
|
-
if (!skip)
|
|
67
|
-
lines.push(' '.repeat(depth) + formatA11yNodeOneLine(node));
|
|
68
|
-
for (const childId of node.childIds ?? []) {
|
|
69
|
-
const child = tree.nodes.get(childId);
|
|
70
|
-
if (child)
|
|
71
|
-
visit(child, skip ? depth : depth + 1, node.name ?? parentName);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
visit(tree.root, 0, undefined);
|
|
75
|
-
return { lines, truncated };
|
|
76
|
-
}
|
|
77
23
|
/** Roles whose elements take a value (the next step is fill, not click) */
|
|
78
24
|
const FILLABLE_ROLES = new Set([
|
|
79
25
|
'textbox',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Human output of `bdg dom audit` and `bdg css search`.
|
|
3
3
|
*/
|
|
4
|
+
import { auditCanvasNote, auditUncertainContrastNote } from '../messages/commands.js';
|
|
4
5
|
import { truncateByLength } from '../../utils/strings.js';
|
|
5
6
|
/** Width of the text quoted in a finding */
|
|
6
7
|
const TEXT_WIDTH = 50;
|
|
@@ -15,7 +16,7 @@ export function formatAudit(data) {
|
|
|
15
16
|
data.contrast && contrastSection(data.contrast),
|
|
16
17
|
data.overflow && overflowSection(data.overflow),
|
|
17
18
|
data.layers && layersSection(data.layers),
|
|
18
|
-
data.animations && animationsSection(data.animations),
|
|
19
|
+
data.animations && animationsSection(data.animations, data.canvases),
|
|
19
20
|
].filter((section) => section !== undefined);
|
|
20
21
|
const capped = data.capped ? [`(stopped after ${data.walked} elements; the page has more)`] : [];
|
|
21
22
|
return [...sections.flatMap((lines) => [...lines, '']), ...capped].join('\n').trimEnd();
|
|
@@ -28,9 +29,14 @@ export function formatAudit(data) {
|
|
|
28
29
|
*/
|
|
29
30
|
function contrastSection(contrast) {
|
|
30
31
|
const head = `Contrast (${contrast.level}): ${contrast.failing} of ${contrast.checked} text elements below`;
|
|
31
|
-
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.
|
|
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)'}`);
|
|
32
33
|
const more = contrast.failing - contrast.items.length;
|
|
33
|
-
return [
|
|
34
|
+
return [
|
|
35
|
+
head,
|
|
36
|
+
...rows,
|
|
37
|
+
...(more > 0 ? [` (+${more} more; --limit to list them)`] : []),
|
|
38
|
+
...(contrast.uncertain ? [` ${auditUncertainContrastNote(contrast.uncertain)}`] : []),
|
|
39
|
+
];
|
|
34
40
|
}
|
|
35
41
|
/**
|
|
36
42
|
* The overflow section.
|
|
@@ -77,14 +83,17 @@ function layersSection(layers) {
|
|
|
77
83
|
* The animations section.
|
|
78
84
|
*
|
|
79
85
|
* @param animations - Running animations
|
|
86
|
+
* @param canvases - Visible canvas elements
|
|
80
87
|
* @returns Lines
|
|
81
88
|
*/
|
|
82
|
-
function animationsSection(animations) {
|
|
89
|
+
function animationsSection(animations, canvases) {
|
|
90
|
+
const note = canvases ? [` ${auditCanvasNote(canvases)}`] : [];
|
|
83
91
|
if (animations.length === 0)
|
|
84
|
-
return ['Animations: none running'];
|
|
92
|
+
return ['Animations: none running', ...note];
|
|
85
93
|
return [
|
|
86
94
|
`Animations: ${animations.length} running`,
|
|
87
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,
|
|
88
97
|
];
|
|
89
98
|
}
|
|
90
99
|
/**
|