browser-debugger-cli 0.12.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.
- package/.claude/skills/bdg/SKILL.md +4 -4
- package/README.md +1 -0
- 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 +62 -12
- package/dist/commands/dom/DomElementResolver.d.ts +3 -1
- package/dist/commands/dom/DomElementResolver.js +10 -3
- package/dist/commands/dom/a11y.js +3 -2
- package/dist/commands/dom/eval.d.ts +3 -2
- package/dist/commands/dom/eval.js +11 -5
- package/dist/commands/dom/form.js +10 -9
- package/dist/commands/dom/formInteraction.js +8 -7
- package/dist/commands/dom/get.js +8 -8
- 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 +4 -2
- package/dist/commands/dom/query.d.ts +19 -2
- package/dist/commands/dom/query.js +37 -6
- package/dist/commands/dom/screenshot.js +2 -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 +111 -40
- 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 +22 -12
- package/dist/commands/optionBehaviors.js +33 -11
- package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
- package/dist/commands/shared/daemonErrorHandler.js +20 -9
- package/dist/commands/shared/dataFetcher.d.ts +12 -4
- package/dist/commands/shared/dataFetcher.js +12 -4
- package/dist/commands/shared/followMode.d.ts +9 -1
- package/dist/commands/shared/followMode.js +22 -4
- package/dist/commands/shared/optionTypes.d.ts +4 -1
- package/dist/commands/shared/outputFile.js +6 -1
- 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/launcher.js +3 -2
- package/dist/daemon/SessionController.js +6 -1
- package/dist/daemon/launcher.d.ts +3 -2
- package/dist/daemon/launcher.js +47 -3
- package/dist/daemon/session/Session.d.ts +4 -1
- package/dist/daemon/session/Session.js +33 -2
- package/dist/daemon/session/TelemetryStore.d.ts +8 -1
- package/dist/daemon/session/TelemetryStore.js +13 -1
- package/dist/daemon/session/commandRegistry.js +29 -13
- package/dist/daemon/session/interactions.d.ts +2 -1
- package/dist/daemon/session/interactions.js +13 -1
- package/dist/daemon/session/plugins.js +16 -2
- package/dist/daemon/session/teardown.js +1 -1
- package/dist/daemon.js +1622 -748
- package/dist/errors/messages.d.ts +54 -11
- package/dist/errors/messages.js +109 -22
- package/dist/index.js +13733 -8796
- 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 +12 -0
- package/dist/ipc/protocol/domTypes.d.ts +12 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +2 -0
- package/dist/ipc/session/types.d.ts +2 -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 +10 -3
- package/dist/runtime/dom/elementGeometry.js +27 -4
- package/dist/runtime/dom/elementInfo.d.ts +74 -18
- package/dist/runtime/dom/elementInfo.js +187 -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/inspect.js +5 -6
- package/dist/runtime/dom/inspectAllStyles.js +1 -0
- package/dist/runtime/dom/inspectHints.d.ts +1 -1
- package/dist/runtime/dom/inspectModel.d.ts +2 -1
- 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/inspectScripts.d.ts +29 -2
- package/dist/runtime/dom/inspectScripts.js +49 -10
- package/dist/runtime/dom/layout.js +9 -7
- package/dist/runtime/dom/reactEventHelpers.d.ts +14 -4
- package/dist/runtime/dom/reactEventHelpers.js +63 -27
- package/dist/runtime/dom/targetNode.d.ts +18 -5
- package/dist/runtime/dom/targetNode.js +268 -8
- 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.js +2 -2
- package/dist/telemetry/console.d.ts +2 -1
- package/dist/telemetry/console.js +30 -21
- package/dist/telemetry/pageCrash.d.ts +26 -0
- package/dist/telemetry/pageCrash.js +53 -0
- package/dist/types.d.ts +16 -0
- 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 +3 -1
- package/dist/ui/formatters/console/follow.d.ts +2 -1
- package/dist/ui/formatters/console/follow.js +2 -2
- package/dist/ui/formatters/console/json.d.ts +2 -2
- package/dist/ui/formatters/console/json.js +11 -5
- package/dist/ui/formatters/console/shared.d.ts +30 -0
- package/dist/ui/formatters/console/shared.js +16 -0
- package/dist/ui/formatters/console/summarize.d.ts +9 -2
- package/dist/ui/formatters/console/summarize.js +40 -9
- package/dist/ui/formatters/console.d.ts +2 -1
- package/dist/ui/formatters/console.js +7 -5
- package/dist/ui/formatters/details.js +3 -1
- package/dist/ui/formatters/dom.d.ts +1 -1
- package/dist/ui/formatters/dom.js +5 -6
- 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 +2 -1
- package/dist/ui/formatters/networkList.d.ts +1 -1
- package/dist/ui/formatters/networkList.js +1 -2
- package/dist/ui/formatters/preview.d.ts +2 -0
- package/dist/ui/formatters/preview.js +17 -7
- package/dist/ui/formatters/sessions.d.ts +2 -2
- package/dist/ui/formatters/sessions.js +9 -2
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/commands.d.ts +124 -4
- package/dist/ui/messages/commands.js +162 -7
- package/dist/ui/messages/consoleMessages.d.ts +24 -0
- package/dist/ui/messages/consoleMessages.js +32 -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/process.d.ts +12 -0
- package/dist/utils/process.js +25 -0
- package/package.json +1 -1
|
@@ -18,6 +18,7 @@ import { readPageLoadingState } from '../../runtime/page/loadingState.js';
|
|
|
18
18
|
import { reapOrphanedChrome, removeSessionFiles } from '../../session/cleanup/staleSession.js';
|
|
19
19
|
import { writeSessionMetadata } from '../../session/metadata.js';
|
|
20
20
|
import { getSessionPort } from '../../session/port.js';
|
|
21
|
+
import { pageCrashedCommandError } from '../../telemetry/pageCrash.js';
|
|
21
22
|
import { createLogger } from '../../ui/logging/index.js';
|
|
22
23
|
import { formatChromeNotice } from '../../ui/messages/chrome.js';
|
|
23
24
|
import { delay } from '../../utils/async.js';
|
|
@@ -31,6 +32,26 @@ const log = createLogger('session');
|
|
|
31
32
|
const CRASH_SETTLE_MS = 500;
|
|
32
33
|
/** Ports tried when automatically chosen ports turn out to be taken */
|
|
33
34
|
const PORT_ATTEMPTS = 3;
|
|
35
|
+
/**
|
|
36
|
+
* Commands that still work after the page's renderer crashed: they read what
|
|
37
|
+
* the session collected, load the page again (`page reload`/`navigate`) or
|
|
38
|
+
* send raw CDP. Every other command needs the page and fails at once.
|
|
39
|
+
*/
|
|
40
|
+
const RUN_ON_CRASHED_PAGE = new Set([
|
|
41
|
+
'session_peek',
|
|
42
|
+
'session_details',
|
|
43
|
+
'session_status',
|
|
44
|
+
'session_har_data',
|
|
45
|
+
'session_network_headers',
|
|
46
|
+
'page_navigate',
|
|
47
|
+
'cdp_call',
|
|
48
|
+
]);
|
|
49
|
+
/**
|
|
50
|
+
* CDP methods `bdg cdp` may still send after a renderer crash: loading the
|
|
51
|
+
* page again, and domains the browser process answers. Others wait for the
|
|
52
|
+
* renderer, which never answers.
|
|
53
|
+
*/
|
|
54
|
+
const CRASH_SAFE_CDP = /^(Page\.(navigate|reload|getNavigationHistory|navigateToHistoryEntry)|Target\.|Browser\.|Inspector\.|Network\.(?!getResponseBody|getRequestPostData)|Storage\.|SystemInfo\.)/;
|
|
34
55
|
/**
|
|
35
56
|
* Whether a launch failed because another process holds the port.
|
|
36
57
|
*
|
|
@@ -127,7 +148,10 @@ export class Session {
|
|
|
127
148
|
}
|
|
128
149
|
}
|
|
129
150
|
/**
|
|
130
|
-
* Execute a registered command against this session.
|
|
151
|
+
* Execute a registered command against this session. After a renderer
|
|
152
|
+
* crash only {@link RUN_ON_CRASHED_PAGE} commands run (`bdg cdp` only for
|
|
153
|
+
* {@link CRASH_SAFE_CDP} methods); others fail with exit 107 instead of
|
|
154
|
+
* waiting for a page that cannot answer.
|
|
131
155
|
*
|
|
132
156
|
* @param name - Command name
|
|
133
157
|
* @param params - Command parameters
|
|
@@ -137,6 +161,13 @@ export class Session {
|
|
|
137
161
|
if (!this.cdp || !this.started || this.stopping) {
|
|
138
162
|
return Promise.reject(new Error('No active session'));
|
|
139
163
|
}
|
|
164
|
+
const crashedAt = this.store.pageCrashedAt;
|
|
165
|
+
const cdpMethod = name === 'cdp_call' ? params.method : undefined;
|
|
166
|
+
const needsPage = !RUN_ON_CRASHED_PAGE.has(name) ||
|
|
167
|
+
(cdpMethod !== undefined && !CRASH_SAFE_CDP.test(cdpMethod));
|
|
168
|
+
if (crashedAt !== undefined && needsPage) {
|
|
169
|
+
return Promise.reject(pageCrashedCommandError(crashedAt));
|
|
170
|
+
}
|
|
140
171
|
return this.registry[name](this.cdp, params);
|
|
141
172
|
}
|
|
142
173
|
/**
|
|
@@ -223,7 +254,7 @@ export class Session {
|
|
|
223
254
|
await this.releaseResources();
|
|
224
255
|
if (!this.started)
|
|
225
256
|
return;
|
|
226
|
-
removeSessionFiles();
|
|
257
|
+
removeSessionFiles(process.pid);
|
|
227
258
|
this.onEnded(reason);
|
|
228
259
|
})();
|
|
229
260
|
return this.stopping;
|
|
@@ -7,11 +7,18 @@ export declare class TelemetryStore {
|
|
|
7
7
|
/** Requests still in flight, keyed by CDP requestId */
|
|
8
8
|
readonly pendingNetworkRequests: Map<string, PendingRequest>;
|
|
9
9
|
readonly consoleMessages: ConsoleMessage[];
|
|
10
|
+
/**
|
|
11
|
+
* Console messages dropped at the limit, oldest first: the index of
|
|
12
|
+
* `consoleMessages[i]` in the session is `consoleDropped + i`
|
|
13
|
+
*/
|
|
14
|
+
consoleDropped: number;
|
|
10
15
|
readonly navigationEvents: NavigationEvent[];
|
|
11
16
|
readonly websocketConnections: WebSocketConnection[];
|
|
12
17
|
/** JavaScript dialogs accepted during the session */
|
|
13
18
|
readonly dialogs: DialogInfo[];
|
|
14
19
|
activeTelemetry: TelemetryType[];
|
|
20
|
+
/** When the page's renderer crashed (epoch ms); undefined while the page is alive */
|
|
21
|
+
pageCrashedAt: number | undefined;
|
|
15
22
|
getCurrentNavigationId: (() => number) | null;
|
|
16
23
|
sessionStartTime: number;
|
|
17
24
|
targetInfo: CDPTarget | null;
|
|
@@ -21,7 +28,7 @@ export declare class TelemetryStore {
|
|
|
21
28
|
/**
|
|
22
29
|
* Record an accepted dialog, and show it among the console messages when
|
|
23
30
|
* console telemetry is collected (it is otherwise invisible: bdg accepts it
|
|
24
|
-
* before anyone could see it).
|
|
31
|
+
* before anyone could see it), dropping the oldest message at the limit.
|
|
25
32
|
*
|
|
26
33
|
* @param dialog - Dialog type and text
|
|
27
34
|
*/
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
+
import { MAX_CONSOLE_MESSAGES } from '../../constants.js';
|
|
1
2
|
import { dialogConsoleText } from '../../ui/messages/commands.js';
|
|
2
3
|
export class TelemetryStore {
|
|
3
4
|
networkRequests = [];
|
|
4
5
|
/** Requests still in flight, keyed by CDP requestId */
|
|
5
6
|
pendingNetworkRequests = new Map();
|
|
6
7
|
consoleMessages = [];
|
|
8
|
+
/**
|
|
9
|
+
* Console messages dropped at the limit, oldest first: the index of
|
|
10
|
+
* `consoleMessages[i]` in the session is `consoleDropped + i`
|
|
11
|
+
*/
|
|
12
|
+
consoleDropped = 0;
|
|
7
13
|
navigationEvents = [];
|
|
8
14
|
websocketConnections = [];
|
|
9
15
|
/** JavaScript dialogs accepted during the session */
|
|
10
16
|
dialogs = [];
|
|
11
17
|
activeTelemetry = [];
|
|
18
|
+
/** When the page's renderer crashed (epoch ms); undefined while the page is alive */
|
|
19
|
+
pageCrashedAt;
|
|
12
20
|
getCurrentNavigationId = null;
|
|
13
21
|
sessionStartTime = Date.now();
|
|
14
22
|
targetInfo = null;
|
|
@@ -24,7 +32,7 @@ export class TelemetryStore {
|
|
|
24
32
|
/**
|
|
25
33
|
* Record an accepted dialog, and show it among the console messages when
|
|
26
34
|
* console telemetry is collected (it is otherwise invisible: bdg accepts it
|
|
27
|
-
* before anyone could see it).
|
|
35
|
+
* before anyone could see it), dropping the oldest message at the limit.
|
|
28
36
|
*
|
|
29
37
|
* @param dialog - Dialog type and text
|
|
30
38
|
*/
|
|
@@ -32,6 +40,10 @@ export class TelemetryStore {
|
|
|
32
40
|
this.dialogs.push(dialog);
|
|
33
41
|
if (!this.activeTelemetry.includes('console'))
|
|
34
42
|
return;
|
|
43
|
+
if (this.consoleMessages.length >= MAX_CONSOLE_MESSAGES) {
|
|
44
|
+
this.consoleMessages.shift();
|
|
45
|
+
this.consoleDropped++;
|
|
46
|
+
}
|
|
35
47
|
this.consoleMessages.push({
|
|
36
48
|
type: 'info',
|
|
37
49
|
text: dialogConsoleText(dialog),
|
|
@@ -17,10 +17,12 @@ import { inspectElement } from '../../runtime/dom/inspect.js';
|
|
|
17
17
|
import { inspectLayout } from '../../runtime/dom/layout.js';
|
|
18
18
|
import { onScriptTarget } from '../../runtime/dom/targetNode.js';
|
|
19
19
|
import { waitForCondition } from '../../runtime/dom/wait.js';
|
|
20
|
+
import { evaluateInBdgWorld, sendForBdgScript } from '../../runtime/page/bdgWorld.js';
|
|
20
21
|
import { emulatePage, pageAppearance } from '../../runtime/page/emulation.js';
|
|
21
22
|
import { readDocumentReadyState } from '../../runtime/page/loadingState.js';
|
|
22
23
|
import { navigatePage } from '../../runtime/page/navigation.js';
|
|
23
24
|
import { skippedBodyReason } from '../../telemetry/network.js';
|
|
25
|
+
import { consoleMessageDroppedError } from '../../ui/messages/consoleMessages.js';
|
|
24
26
|
import { sessionCommand } from '../../ui/messages/sessionCommand.js';
|
|
25
27
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
26
28
|
import { filterDefined } from '../../utils/objects.js';
|
|
@@ -187,24 +189,28 @@ function findNetworkRequestOrThrow(store, id) {
|
|
|
187
189
|
return request;
|
|
188
190
|
}
|
|
189
191
|
/**
|
|
190
|
-
* Find console message by index or throw.
|
|
192
|
+
* Find console message by its session index or throw.
|
|
191
193
|
*
|
|
192
|
-
* @param messages -
|
|
194
|
+
* @param messages - Console messages kept
|
|
193
195
|
* @param indexStr - Index as string
|
|
196
|
+
* @param dropped - Messages dropped before the first kept one (its index)
|
|
194
197
|
* @returns Found message
|
|
195
|
-
* @throws
|
|
198
|
+
* @throws CommandError if the index is invalid, dropped or not found
|
|
196
199
|
*/
|
|
197
|
-
function findConsoleMessageOrThrow(messages, indexStr) {
|
|
200
|
+
function findConsoleMessageOrThrow(messages, indexStr, dropped) {
|
|
198
201
|
if (!/^\d+$/.test(indexStr)) {
|
|
199
202
|
throw new CommandError(`Invalid console message index: ${indexStr}`, { suggestion: `Use a 0-based index from: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.INVALID_ARGUMENTS);
|
|
200
203
|
}
|
|
201
204
|
const index = parseInt(indexStr, 10);
|
|
202
|
-
if (index
|
|
205
|
+
if (index < dropped) {
|
|
206
|
+
throw new CommandError(consoleMessageDroppedError(index, dropped), { suggestion: `List messages with: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.RESOURCE_NOT_FOUND);
|
|
207
|
+
}
|
|
208
|
+
if (index - dropped >= messages.length) {
|
|
203
209
|
throw new CommandError(messages.length === 0
|
|
204
210
|
? `Console message not found at index: ${indexStr} (no messages captured yet)`
|
|
205
|
-
: `Console message not found at index: ${indexStr} (available:
|
|
211
|
+
: `Console message not found at index: ${indexStr} (available: ${dropped}-${dropped + messages.length - 1})`, { suggestion: `List messages with: ${sessionCommand('bdg console --list')}` }, EXIT_CODES.RESOURCE_NOT_FOUND);
|
|
206
212
|
}
|
|
207
|
-
const message = messages[index];
|
|
213
|
+
const message = messages[index - dropped];
|
|
208
214
|
if (!message) {
|
|
209
215
|
throw new CommandError(`Console message not found at index: ${indexStr}`, {}, EXIT_CODES.RESOURCE_NOT_FOUND);
|
|
210
216
|
}
|
|
@@ -312,6 +318,7 @@ export function createCommandRegistry(store, emulation) {
|
|
|
312
318
|
const allNetwork = allNetworkRequests(store);
|
|
313
319
|
const totalNetwork = allNetwork.length;
|
|
314
320
|
const totalConsole = store.consoleMessages.length;
|
|
321
|
+
const dropped = store.consoleDropped;
|
|
315
322
|
const networkBounds = calculateSliceBounds(totalNetwork, lastN, offset);
|
|
316
323
|
const consoleBounds = calculateSliceBounds(totalConsole, lastN, offset);
|
|
317
324
|
const recentNetwork = params.only === 'console'
|
|
@@ -323,7 +330,7 @@ export function createCommandRegistry(store, emulation) {
|
|
|
323
330
|
? []
|
|
324
331
|
: store.consoleMessages
|
|
325
332
|
.slice(consoleBounds.start, consoleBounds.end)
|
|
326
|
-
.map((msg, i) => mapConsoleMessageToPreview(msg, consoleBounds.start + i));
|
|
333
|
+
.map((msg, i) => mapConsoleMessageToPreview(msg, dropped + consoleBounds.start + i));
|
|
327
334
|
return Promise.resolve({
|
|
328
335
|
version: VERSION,
|
|
329
336
|
startTime: store.sessionStartTime,
|
|
@@ -334,10 +341,12 @@ export function createCommandRegistry(store, emulation) {
|
|
|
334
341
|
},
|
|
335
342
|
activeTelemetry: store.activeTelemetry,
|
|
336
343
|
currentNavigationId: store.getCurrentNavigationId?.() ?? 0,
|
|
344
|
+
...(store.pageCrashedAt !== undefined && { pageCrashedAt: store.pageCrashedAt }),
|
|
337
345
|
network: recentNetwork,
|
|
338
346
|
console: recentConsole,
|
|
339
347
|
totalNetwork,
|
|
340
348
|
totalConsole,
|
|
349
|
+
...(dropped > 0 && { droppedConsole: dropped }),
|
|
341
350
|
hasMoreNetwork: networkBounds.start > 0,
|
|
342
351
|
hasMoreConsole: consoleBounds.start > 0,
|
|
343
352
|
});
|
|
@@ -348,7 +357,7 @@ export function createCommandRegistry(store, emulation) {
|
|
|
348
357
|
return Promise.resolve({ item: withBodyNotCaptured(request) });
|
|
349
358
|
}
|
|
350
359
|
if (params.itemType === 'console') {
|
|
351
|
-
const message = findConsoleMessageOrThrow(store.consoleMessages, params.id);
|
|
360
|
+
const message = findConsoleMessageOrThrow(store.consoleMessages, params.id, store.consoleDropped);
|
|
352
361
|
return Promise.resolve({ item: message });
|
|
353
362
|
}
|
|
354
363
|
return Promise.reject(new Error(`Unknown itemType: ${String(params.itemType)}. Expected 'network' or 'console'.`));
|
|
@@ -363,7 +372,9 @@ export function createCommandRegistry(store, emulation) {
|
|
|
363
372
|
target: {
|
|
364
373
|
url: store.targetInfo?.url ?? '',
|
|
365
374
|
title: store.targetInfo?.title ?? '',
|
|
366
|
-
...(
|
|
375
|
+
...(store.pageCrashedAt === undefined
|
|
376
|
+
? await pageAppearance(cdp)
|
|
377
|
+
: { crashedAt: store.pageCrashedAt }),
|
|
367
378
|
},
|
|
368
379
|
activeTelemetry: store.activeTelemetry,
|
|
369
380
|
activity: filterDefined({
|
|
@@ -401,10 +412,15 @@ export function createCommandRegistry(store, emulation) {
|
|
|
401
412
|
});
|
|
402
413
|
},
|
|
403
414
|
cdp_call: async (cdp, params) => {
|
|
404
|
-
const
|
|
415
|
+
const send = params.isolated
|
|
416
|
+
? sendForBdgScript(cdp, params.method, params.params ?? {})
|
|
417
|
+
: cdp.send(params.method, params.params ?? {});
|
|
418
|
+
const result = await withBusyPageRecovery(cdp, send.catch((error) => {
|
|
405
419
|
throw callerError(params.method, error) ?? error;
|
|
406
420
|
}));
|
|
407
|
-
const detectionResult =
|
|
421
|
+
const detectionResult = params.isolated
|
|
422
|
+
? { shouldShow: false, pattern: undefined }
|
|
423
|
+
: patternDetector.trackCommand(params.method);
|
|
408
424
|
let hint;
|
|
409
425
|
if (detectionResult.shouldShow && detectionResult.pattern) {
|
|
410
426
|
hint = {
|
|
@@ -475,7 +491,7 @@ export function createCommandRegistry(store, emulation) {
|
|
|
475
491
|
return { emulated, ...(await pageAppearance(cdp)) };
|
|
476
492
|
},
|
|
477
493
|
dom_form_discover: async (cdp) => {
|
|
478
|
-
const response = await withBusyPageRecovery(cdp, cdp
|
|
494
|
+
const response = await withBusyPageRecovery(cdp, evaluateInBdgWorld(cdp, {
|
|
479
495
|
expression: FORM_DISCOVERY_SCRIPT,
|
|
480
496
|
returnByValue: true,
|
|
481
497
|
}));
|
|
@@ -51,7 +51,8 @@ export type InteractionRunner = <T extends object>(cdp: CDPConnection, action: (
|
|
|
51
51
|
* queued. After each one, the bound target (`window.__bdgTarget`) is removed
|
|
52
52
|
* from the page (without waiting: during a pending navigation that takes until
|
|
53
53
|
* the new page commits), and the dialogs it opened, what it changed on the
|
|
54
|
-
* page (see {@link watchActionEffects}
|
|
54
|
+
* page (see {@link watchActionEffects}; a console message logged meanwhile
|
|
55
|
+
* counts as an effect) and the network requests it
|
|
55
56
|
* triggered (see {@link watchTriggeredRequests}) are added to its result,
|
|
56
57
|
* and, when asked, what the page was still working on (see
|
|
57
58
|
* {@link pendingChanges}). They are attributed by time: a dialog or request
|
|
@@ -18,6 +18,15 @@ const log = createLogger('dom');
|
|
|
18
18
|
function succeeded(result) {
|
|
19
19
|
return !('success' in result) || result.success !== false;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Console messages the session has logged, dropped ones included.
|
|
23
|
+
*
|
|
24
|
+
* @param store - Session store
|
|
25
|
+
* @returns Count that only grows
|
|
26
|
+
*/
|
|
27
|
+
function consoleMessagesLogged(store) {
|
|
28
|
+
return store.consoleDropped + store.consoleMessages.length;
|
|
29
|
+
}
|
|
21
30
|
/**
|
|
22
31
|
* Create the runner for a session's interactions.
|
|
23
32
|
*
|
|
@@ -26,7 +35,8 @@ function succeeded(result) {
|
|
|
26
35
|
* queued. After each one, the bound target (`window.__bdgTarget`) is removed
|
|
27
36
|
* from the page (without waiting: during a pending navigation that takes until
|
|
28
37
|
* the new page commits), and the dialogs it opened, what it changed on the
|
|
29
|
-
* page (see {@link watchActionEffects}
|
|
38
|
+
* page (see {@link watchActionEffects}; a console message logged meanwhile
|
|
39
|
+
* counts as an effect) and the network requests it
|
|
30
40
|
* triggered (see {@link watchTriggeredRequests}) are added to its result,
|
|
31
41
|
* and, when asked, what the page was still working on (see
|
|
32
42
|
* {@link pendingChanges}). They are attributed by time: a dialog or request
|
|
@@ -41,6 +51,7 @@ export function createInteractionRunner(store) {
|
|
|
41
51
|
return (cdp, action, options = {}) => {
|
|
42
52
|
const run = queue.then(async () => {
|
|
43
53
|
const firstDialog = store.dialogs.length;
|
|
54
|
+
const firstConsoleMessage = consoleMessagesLogged(store);
|
|
44
55
|
const collectRequests = options.reportRequests === false ? undefined : watchTriggeredRequests(store);
|
|
45
56
|
const effects = options.reportEffects === false ? undefined : watchActionEffects(cdp);
|
|
46
57
|
try {
|
|
@@ -50,6 +61,7 @@ export function createInteractionRunner(store) {
|
|
|
50
61
|
return { ...result, ...(dialogs.length > 0 && { dialogs }) };
|
|
51
62
|
const collected = await effects?.collect({
|
|
52
63
|
dialogs: dialogs.length,
|
|
64
|
+
consoleMessages: () => consoleMessagesLogged(store) - firstConsoleMessage,
|
|
53
65
|
detectNoEffect: options.detectNoEffect === true,
|
|
54
66
|
reportShown: options.reportShown === true,
|
|
55
67
|
detectUnsettled: options.detectUnsettled === true,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { hideHeadlessUserAgent } from '../../runtime/page/userAgent.js';
|
|
1
2
|
import { startConsoleCollection } from '../../telemetry/console.js';
|
|
2
3
|
import { startDialogHandling } from '../../telemetry/dialogs.js';
|
|
3
4
|
import { prepareDOMCollection } from '../../telemetry/dom.js';
|
|
4
5
|
import { startNavigationTracking } from '../../telemetry/navigation.js';
|
|
5
6
|
import { startNetworkCollection, startWebSocketCollection } from '../../telemetry/network.js';
|
|
7
|
+
import { pageCrashedCommandError, startCrashTracking } from '../../telemetry/pageCrash.js';
|
|
6
8
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
7
|
-
import { hideHeadlessUserAgent } from '../../runtime/page/userAgent.js';
|
|
8
9
|
import { filterDefined } from '../../utils/objects.js';
|
|
9
10
|
/** Delay before reading the title after a same-document navigation */
|
|
10
11
|
const TITLE_REFRESH_DELAY_MS = 300;
|
|
@@ -103,6 +104,17 @@ export function createDefaultTelemetryPlugins() {
|
|
|
103
104
|
return () => undefined;
|
|
104
105
|
},
|
|
105
106
|
},
|
|
107
|
+
{
|
|
108
|
+
name: 'page-crash',
|
|
109
|
+
runAlways: true,
|
|
110
|
+
async start({ cdp, store }) {
|
|
111
|
+
return startCrashTracking(cdp, (crashedAt) => {
|
|
112
|
+
store.pageCrashedAt = crashedAt;
|
|
113
|
+
if (crashedAt !== undefined)
|
|
114
|
+
cdp.rejectPending(pageCrashedCommandError(crashedAt));
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
},
|
|
106
118
|
{
|
|
107
119
|
name: 'navigation',
|
|
108
120
|
runAlways: true,
|
|
@@ -143,7 +155,9 @@ export function createDefaultTelemetryPlugins() {
|
|
|
143
155
|
name: 'console',
|
|
144
156
|
telemetry: 'console',
|
|
145
157
|
async start({ cdp, config, store }) {
|
|
146
|
-
return startConsoleCollection(cdp, store.consoleMessages, config.includeAll ?? false, store.getCurrentNavigationId ?? undefined)
|
|
158
|
+
return startConsoleCollection(cdp, store.consoleMessages, config.includeAll ?? false, store.getCurrentNavigationId ?? undefined, () => {
|
|
159
|
+
store.consoleDropped++;
|
|
160
|
+
});
|
|
147
161
|
},
|
|
148
162
|
},
|
|
149
163
|
{
|