lighthouse 9.5.0-dev.20230201 → 9.5.0-dev.20230202
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/core/gather/driver/prepare.d.ts +6 -0
- package/core/gather/driver/prepare.js +26 -12
- package/core/gather/gatherers/bf-cache-failures.js +4 -1
- package/core/gather/navigation-runner.js +10 -0
- package/core/gather/timespan-runner.js +10 -1
- package/core/legacy/gather/driver.d.ts +4 -3
- package/core/legacy/gather/driver.js +6 -3
- package/core/legacy/gather/gather-runner.js +1 -1
- package/package.json +1 -1
|
@@ -43,4 +43,10 @@ export function prepareTargetForIndividualNavigation(session: LH.Gatherer.FRProt
|
|
|
43
43
|
}): Promise<{
|
|
44
44
|
warnings: Array<LH.IcuMessage>;
|
|
45
45
|
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Enables `Debugger` domain to receive async stacktrace information on network request initiators.
|
|
48
|
+
* This is critical for tracking attribution of tasks and performance simulation accuracy.
|
|
49
|
+
* @param {LH.Gatherer.FRProtocolSession} session
|
|
50
|
+
*/
|
|
51
|
+
export function enableAsyncStacks(session: LH.Gatherer.FRProtocolSession): Promise<() => Promise<void>>;
|
|
46
52
|
//# sourceMappingURL=prepare.d.ts.map
|
|
@@ -22,17 +22,33 @@ async function enableAsyncStacks(session) {
|
|
|
22
22
|
await session.sendCommand('Debugger.setAsyncCallStackDepth', {maxDepth: 8});
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Resume any pauses that make it through `setSkipAllPauses`
|
|
27
|
+
*/
|
|
28
|
+
function onDebuggerPaused() {
|
|
29
|
+
session.sendCommand('Debugger.resume');
|
|
30
|
+
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
/**
|
|
33
|
+
* `Debugger.setSkipAllPauses` is reset after every navigation, so retrigger it on main frame navigations.
|
|
34
|
+
* See https://bugs.chromium.org/p/chromium/issues/detail?id=990945&q=setSkipAllPauses&can=2
|
|
35
|
+
* @param {LH.Crdp.Page.FrameNavigatedEvent} event
|
|
36
|
+
*/
|
|
37
|
+
function onFrameNavigated(event) {
|
|
31
38
|
if (event.frame.parentId) return;
|
|
32
39
|
enable().catch(err => log.error('Driver', err));
|
|
33
|
-
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
session.on('Debugger.paused', onDebuggerPaused);
|
|
43
|
+
session.on('Page.frameNavigated', onFrameNavigated);
|
|
34
44
|
|
|
35
45
|
await enable();
|
|
46
|
+
|
|
47
|
+
return async () => {
|
|
48
|
+
await session.sendCommand('Debugger.disable');
|
|
49
|
+
session.off('Debugger.paused', onDebuggerPaused);
|
|
50
|
+
session.off('Page.frameNavigated', onFrameNavigated);
|
|
51
|
+
};
|
|
36
52
|
}
|
|
37
53
|
|
|
38
54
|
/**
|
|
@@ -128,15 +144,12 @@ async function prepareThrottlingAndNetwork(session, settings, options) {
|
|
|
128
144
|
* @param {LH.Gatherer.FRTransitionalDriver} driver
|
|
129
145
|
* @param {LH.Config.Settings} settings
|
|
130
146
|
*/
|
|
131
|
-
async function
|
|
147
|
+
async function prepareDeviceEmulation(driver, settings) {
|
|
132
148
|
// Enable network domain here so future calls to `emulate()` don't clear cache (https://github.com/GoogleChrome/lighthouse/issues/12631)
|
|
133
149
|
await driver.defaultSession.sendCommand('Network.enable');
|
|
134
150
|
|
|
135
151
|
// Emulate our target device screen and user agent.
|
|
136
152
|
await emulation.emulate(driver.defaultSession, settings);
|
|
137
|
-
|
|
138
|
-
// Enable better stacks on network requests.
|
|
139
|
-
await enableAsyncStacks(driver.defaultSession);
|
|
140
153
|
}
|
|
141
154
|
|
|
142
155
|
/**
|
|
@@ -149,7 +162,7 @@ async function prepareTargetForTimespanMode(driver, settings) {
|
|
|
149
162
|
const status = {msg: 'Preparing target for timespan mode', id: 'lh:prepare:timespanMode'};
|
|
150
163
|
log.time(status);
|
|
151
164
|
|
|
152
|
-
await
|
|
165
|
+
await prepareDeviceEmulation(driver, settings);
|
|
153
166
|
await prepareThrottlingAndNetwork(driver.defaultSession, settings, {
|
|
154
167
|
disableThrottling: false,
|
|
155
168
|
blockedUrlPatterns: undefined,
|
|
@@ -171,7 +184,7 @@ async function prepareTargetForNavigationMode(driver, settings) {
|
|
|
171
184
|
const status = {msg: 'Preparing target for navigation mode', id: 'lh:prepare:navigationMode'};
|
|
172
185
|
log.time(status);
|
|
173
186
|
|
|
174
|
-
await
|
|
187
|
+
await prepareDeviceEmulation(driver, settings);
|
|
175
188
|
|
|
176
189
|
// Automatically handle any JavaScript dialogs to prevent a hung renderer.
|
|
177
190
|
await dismissJavaScriptDialogs(driver.defaultSession);
|
|
@@ -227,4 +240,5 @@ export {
|
|
|
227
240
|
prepareTargetForTimespanMode,
|
|
228
241
|
prepareTargetForNavigationMode,
|
|
229
242
|
prepareTargetForIndividualNavigation,
|
|
243
|
+
enableAsyncStacks,
|
|
230
244
|
};
|
|
@@ -9,6 +9,7 @@ import {waitForFrameNavigated, waitForLoadEvent} from '../driver/wait-for-condit
|
|
|
9
9
|
import DevtoolsLog from './devtools-log.js';
|
|
10
10
|
|
|
11
11
|
const FAILURE_EVENT_TIMEOUT = 100;
|
|
12
|
+
const TEMP_PAGE_PAUSE_TIMEOUT = 100;
|
|
12
13
|
|
|
13
14
|
class BFCacheFailures extends FRGatherer {
|
|
14
15
|
/** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
|
|
@@ -109,7 +110,9 @@ class BFCacheFailures extends FRGatherer {
|
|
|
109
110
|
// https://github.com/GoogleChrome/lighthouse/issues/14665
|
|
110
111
|
await Promise.all([
|
|
111
112
|
session.sendCommand('Page.navigate', {url: 'chrome://terms'}),
|
|
112
|
-
|
|
113
|
+
// DevTools e2e tests can sometimes fail on the next command if we progress too fast.
|
|
114
|
+
// The only reliable way to prevent this is to wait for an arbitrary period of time after load.
|
|
115
|
+
waitForLoadEvent(session, TEMP_PAGE_PAUSE_TIMEOUT).promise,
|
|
113
116
|
]);
|
|
114
117
|
|
|
115
118
|
const [, frameNavigatedEvent] = await Promise.all([
|
|
@@ -227,6 +227,10 @@ async function _navigation(navigationContext) {
|
|
|
227
227
|
};
|
|
228
228
|
|
|
229
229
|
const setupResult = await _setupNavigation(navigationContext);
|
|
230
|
+
|
|
231
|
+
const disableAsyncStacks =
|
|
232
|
+
await prepare.enableAsyncStacks(navigationContext.driver.defaultSession);
|
|
233
|
+
|
|
230
234
|
await collectPhaseArtifacts({phase: 'startInstrumentation', ...phaseState});
|
|
231
235
|
await collectPhaseArtifacts({phase: 'startSensitiveInstrumentation', ...phaseState});
|
|
232
236
|
const navigateResult = await _navigate(navigationContext);
|
|
@@ -244,6 +248,12 @@ async function _navigation(navigationContext) {
|
|
|
244
248
|
|
|
245
249
|
await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseState});
|
|
246
250
|
await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseState});
|
|
251
|
+
|
|
252
|
+
// bf-cache-failures can emit `Page.frameNavigated` at the end of the run.
|
|
253
|
+
// This can cause us to issue protocol commands after the target closes.
|
|
254
|
+
// We should disable our `Page.frameNavigated` handlers before that.
|
|
255
|
+
await disableAsyncStacks();
|
|
256
|
+
|
|
247
257
|
await _cleanupNavigation(navigationContext);
|
|
248
258
|
|
|
249
259
|
return _computeNavigationResult(navigationContext, phaseState, setupResult, navigateResult);
|
|
@@ -9,7 +9,7 @@ import log from 'lighthouse-logger';
|
|
|
9
9
|
import {Driver} from './driver.js';
|
|
10
10
|
import {Runner} from '../runner.js';
|
|
11
11
|
import {getEmptyArtifactState, collectPhaseArtifacts, awaitArtifacts} from './runner-helpers.js';
|
|
12
|
-
import {prepareTargetForTimespanMode} from './driver/prepare.js';
|
|
12
|
+
import {enableAsyncStacks, prepareTargetForTimespanMode} from './driver/prepare.js';
|
|
13
13
|
import {initializeConfig} from '../config/config.js';
|
|
14
14
|
import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js';
|
|
15
15
|
|
|
@@ -44,6 +44,9 @@ async function startTimespanGather(page, options = {}) {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
await prepareTargetForTimespanMode(driver, resolvedConfig.settings);
|
|
47
|
+
|
|
48
|
+
const disableAsyncStacks = await enableAsyncStacks(driver.defaultSession);
|
|
49
|
+
|
|
47
50
|
await collectPhaseArtifacts({phase: 'startInstrumentation', ...phaseOptions});
|
|
48
51
|
await collectPhaseArtifacts({phase: 'startSensitiveInstrumentation', ...phaseOptions});
|
|
49
52
|
|
|
@@ -58,6 +61,12 @@ async function startTimespanGather(page, options = {}) {
|
|
|
58
61
|
|
|
59
62
|
await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseOptions});
|
|
60
63
|
await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseOptions});
|
|
64
|
+
|
|
65
|
+
// bf-cache-failures can emit `Page.frameNavigated` at the end of the run.
|
|
66
|
+
// This can cause us to issue protocol commands after the target closes.
|
|
67
|
+
// We should disable our `Page.frameNavigated` handlers before that.
|
|
68
|
+
await disableAsyncStacks();
|
|
69
|
+
|
|
61
70
|
await collectPhaseArtifacts({phase: 'getArtifact', ...phaseOptions});
|
|
62
71
|
await driver.disconnect();
|
|
63
72
|
|
|
@@ -200,12 +200,13 @@ export class Driver implements LH.Gatherer.FRTransitionalDriver {
|
|
|
200
200
|
/**
|
|
201
201
|
* Begin recording devtools protocol messages.
|
|
202
202
|
*/
|
|
203
|
-
beginDevtoolsLog(): void
|
|
203
|
+
beginDevtoolsLog(): Promise<void>;
|
|
204
|
+
_disableAsyncStacks: (() => Promise<void>) | undefined;
|
|
204
205
|
/**
|
|
205
206
|
* Stop recording to devtoolsLog and return log contents.
|
|
206
|
-
* @return {LH.DevtoolsLog}
|
|
207
|
+
* @return {Promise<LH.DevtoolsLog>}
|
|
207
208
|
*/
|
|
208
|
-
endDevtoolsLog(): LH.DevtoolsLog
|
|
209
|
+
endDevtoolsLog(): Promise<LH.DevtoolsLog>;
|
|
209
210
|
url(): Promise<string>;
|
|
210
211
|
}
|
|
211
212
|
import * as LH from "../../../types/lh.js";
|
|
@@ -16,6 +16,7 @@ import {fetchResponseBodyFromCache} from '../../gather/driver/network.js';
|
|
|
16
16
|
import {DevtoolsMessageLog} from '../../gather/gatherers/devtools-log.js';
|
|
17
17
|
import TraceGatherer from '../../gather/gatherers/trace.js';
|
|
18
18
|
import {getBrowserVersion} from '../../gather/driver/environment.js';
|
|
19
|
+
import {enableAsyncStacks} from '../../gather/driver/prepare.js';
|
|
19
20
|
|
|
20
21
|
// Controls how long to wait for a response after sending a DevTools protocol command.
|
|
21
22
|
const DEFAULT_PROTOCOL_TIMEOUT = 30000;
|
|
@@ -443,17 +444,19 @@ class Driver {
|
|
|
443
444
|
/**
|
|
444
445
|
* Begin recording devtools protocol messages.
|
|
445
446
|
*/
|
|
446
|
-
beginDevtoolsLog() {
|
|
447
|
+
async beginDevtoolsLog() {
|
|
448
|
+
this._disableAsyncStacks = await enableAsyncStacks(this);
|
|
447
449
|
this._devtoolsLog.reset();
|
|
448
450
|
this._devtoolsLog.beginRecording();
|
|
449
451
|
}
|
|
450
452
|
|
|
451
453
|
/**
|
|
452
454
|
* Stop recording to devtoolsLog and return log contents.
|
|
453
|
-
* @return {LH.DevtoolsLog}
|
|
455
|
+
* @return {Promise<LH.DevtoolsLog>}
|
|
454
456
|
*/
|
|
455
|
-
endDevtoolsLog() {
|
|
457
|
+
async endDevtoolsLog() {
|
|
456
458
|
this._devtoolsLog.endRecording();
|
|
459
|
+
await this._disableAsyncStacks?.();
|
|
457
460
|
return this._devtoolsLog.messages;
|
|
458
461
|
}
|
|
459
462
|
|
|
@@ -235,7 +235,7 @@ class GatherRunner {
|
|
|
235
235
|
id: `lh:gather:getDevtoolsLog`,
|
|
236
236
|
};
|
|
237
237
|
log.time(status);
|
|
238
|
-
const devtoolsLog = driver.endDevtoolsLog();
|
|
238
|
+
const devtoolsLog = await driver.endDevtoolsLog();
|
|
239
239
|
const networkRecords = await NetworkRecords.request(devtoolsLog, passContext);
|
|
240
240
|
log.timeEnd(status);
|
|
241
241
|
|
package/package.json
CHANGED