lighthouse 11.2.0-dev.20231017 → 11.2.0-dev.20231019

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 (37) hide show
  1. package/cli/test/smokehouse/frontends/smokehouse-bin.js +18 -7
  2. package/cli/test/smokehouse/lighthouse-runners/bundle.d.ts +2 -4
  3. package/cli/test/smokehouse/lighthouse-runners/bundle.js +8 -4
  4. package/cli/test/smokehouse/lighthouse-runners/cli.d.ts +2 -4
  5. package/cli/test/smokehouse/lighthouse-runners/cli.js +5 -3
  6. package/cli/test/smokehouse/lighthouse-runners/devtools.d.ts +2 -1
  7. package/cli/test/smokehouse/lighthouse-runners/devtools.js +3 -1
  8. package/cli/test/smokehouse/smokehouse.d.ts +4 -2
  9. package/cli/test/smokehouse/smokehouse.js +10 -7
  10. package/core/config/config.d.ts +1 -2
  11. package/core/config/config.js +18 -62
  12. package/core/config/constants.d.ts +1 -3
  13. package/core/config/constants.js +2 -18
  14. package/core/config/filters.d.ts +0 -8
  15. package/core/config/filters.js +0 -28
  16. package/core/config/validation.d.ts +4 -15
  17. package/core/config/validation.js +18 -63
  18. package/core/gather/base-artifacts.d.ts +2 -2
  19. package/core/gather/base-artifacts.js +5 -5
  20. package/core/gather/driver/navigation.d.ts +1 -1
  21. package/core/gather/driver/navigation.js +1 -1
  22. package/core/gather/driver/prepare.d.ts +3 -18
  23. package/core/gather/driver/prepare.js +14 -38
  24. package/core/gather/gatherers/inspector-issues.js +1 -0
  25. package/core/gather/navigation-runner.d.ts +3 -31
  26. package/core/gather/navigation-runner.js +39 -112
  27. package/core/lib/navigation-error.d.ts +1 -2
  28. package/core/lib/navigation-error.js +2 -6
  29. package/dist/report/bundle.esm.js +4 -4
  30. package/dist/report/flow.js +7 -7
  31. package/dist/report/standalone.js +5 -5
  32. package/package.json +5 -5
  33. package/report/renderer/performance-category-renderer.js +2 -1
  34. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +1 -0
  35. package/types/artifacts.d.ts +1 -0
  36. package/types/config.d.ts +0 -38
  37. package/types/internal/smokehouse.d.ts +10 -5
@@ -14,7 +14,6 @@ import * as prepare from './driver/prepare.js';
14
14
  import {gotoURL} from './driver/navigation.js';
15
15
  import * as storage from './driver/storage.js';
16
16
  import * as emulation from '../lib/emulation.js';
17
- import {defaultNavigationConfig} from '../config/constants.js';
18
17
  import {initializeConfig} from '../config/config.js';
19
18
  import {getBaseArtifacts, finalizeArtifacts} from './base-artifacts.js';
20
19
  import * as format from '../../shared/localization/format.js';
@@ -30,7 +29,6 @@ import {NetworkRecords} from '../computed/network-records.js';
30
29
  * @property {Driver} driver
31
30
  * @property {LH.Puppeteer.Page} page
32
31
  * @property {LH.Config.ResolvedConfig} resolvedConfig
33
- * @property {LH.Config.NavigationDefn} navigation
34
32
  * @property {LH.NavigationRequestor} requestor
35
33
  * @property {LH.BaseArtifacts} baseArtifacts
36
34
  * @property {Map<string, LH.ArbitraryEqualityMap>} computedCache
@@ -50,36 +48,23 @@ async function _setup({driver, resolvedConfig, requestor}) {
50
48
 
51
49
  // We can't trigger the navigation through user interaction if we reset the page before starting.
52
50
  if (typeof requestor === 'string' && !resolvedConfig.settings.skipAboutBlank) {
53
- await gotoURL(driver, defaultNavigationConfig.blankPage, {waitUntil: ['navigated']});
51
+ // Disable network monitor on the blank page to prevent it from picking up network requests and
52
+ // frame navigated events before the run starts.
53
+ await driver._networkMonitor?.disable();
54
+
55
+ await gotoURL(driver, resolvedConfig.settings.blankPage, {waitUntil: ['navigated']});
56
+
57
+ await driver._networkMonitor?.enable();
54
58
  }
55
59
 
56
60
  const baseArtifacts = await getBaseArtifacts(resolvedConfig, driver, {gatherMode: 'navigation'});
57
61
 
58
- await prepare.prepareTargetForNavigationMode(driver, resolvedConfig.settings);
59
-
60
- return {baseArtifacts};
61
- }
62
+ const {warnings} =
63
+ await prepare.prepareTargetForNavigationMode(driver, resolvedConfig.settings, requestor);
62
64
 
63
- /**
64
- * @param {NavigationContext} navigationContext
65
- * @return {Promise<{warnings: Array<LH.IcuMessage>}>}
66
- */
67
- async function _setupNavigation({requestor, driver, navigation, resolvedConfig}) {
68
- // We can't trigger the navigation through user interaction if we reset the page before starting.
69
- if (typeof requestor === 'string' && !resolvedConfig.settings.skipAboutBlank) {
70
- await gotoURL(driver, navigation.blankPage, {...navigation, waitUntil: ['navigated']});
71
- }
65
+ baseArtifacts.LighthouseRunWarnings.push(...warnings);
72
66
 
73
- const {warnings} = await prepare.prepareTargetForIndividualNavigation(
74
- driver.defaultSession,
75
- resolvedConfig.settings,
76
- {
77
- ...navigation,
78
- requestor,
79
- }
80
- );
81
-
82
- return {warnings};
67
+ return {baseArtifacts};
83
68
  }
84
69
 
85
70
  /**
@@ -91,20 +76,20 @@ async function _cleanupNavigation({driver}) {
91
76
 
92
77
  /**
93
78
  * @param {NavigationContext} navigationContext
94
- * @return {Promise<{requestedUrl: string, mainDocumentUrl: string, navigationError: LH.LighthouseError | undefined, warnings: Array<LH.IcuMessage>}>}
79
+ * @return {Promise<{requestedUrl: string, mainDocumentUrl: string, navigationError: LH.LighthouseError | undefined}>}
95
80
  */
96
81
  async function _navigate(navigationContext) {
97
82
  const {driver, resolvedConfig, requestor} = navigationContext;
98
83
 
99
84
  try {
100
85
  const {requestedUrl, mainDocumentUrl, warnings} = await gotoURL(driver, requestor, {
101
- ...navigationContext.navigation,
102
- debugNavigation: resolvedConfig.settings.debugNavigation,
103
- maxWaitForFcp: resolvedConfig.settings.maxWaitForFcp,
104
- maxWaitForLoad: resolvedConfig.settings.maxWaitForLoad,
105
- waitUntil: navigationContext.navigation.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'],
86
+ ...resolvedConfig.settings,
87
+ waitUntil: resolvedConfig.settings.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'],
106
88
  });
107
- return {requestedUrl, mainDocumentUrl, navigationError: undefined, warnings};
89
+
90
+ navigationContext.baseArtifacts.LighthouseRunWarnings.push(...warnings);
91
+
92
+ return {requestedUrl, mainDocumentUrl, navigationError: undefined};
108
93
  } catch (err) {
109
94
  if (!(err instanceof LighthouseError)) throw err;
110
95
  if (err.code !== 'NO_FCP' && err.code !== 'PAGE_HUNG') throw err;
@@ -115,7 +100,6 @@ async function _navigate(navigationContext) {
115
100
  requestedUrl: requestor,
116
101
  mainDocumentUrl: requestor,
117
102
  navigationError: err,
118
- warnings: [],
119
103
  };
120
104
  }
121
105
  }
@@ -158,36 +142,32 @@ async function _collectDebugData(navigationContext, phaseState) {
158
142
  /**
159
143
  * @param {NavigationContext} navigationContext
160
144
  * @param {PhaseState} phaseState
161
- * @param {Awaited<ReturnType<typeof _setupNavigation>>} setupResult
162
145
  * @param {Awaited<ReturnType<typeof _navigate>>} navigateResult
163
- * @return {Promise<{artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
146
+ * @return {Promise<Partial<LH.GathererArtifacts>>}
164
147
  */
165
148
  async function _computeNavigationResult(
166
149
  navigationContext,
167
150
  phaseState,
168
- setupResult,
169
151
  navigateResult
170
152
  ) {
171
- const {navigationError, mainDocumentUrl} = navigateResult;
172
- const warnings = [...setupResult.warnings, ...navigateResult.warnings];
153
+ const {navigationError, requestedUrl, mainDocumentUrl} = navigateResult;
173
154
  const debugData = await _collectDebugData(navigationContext, phaseState);
174
155
  const pageLoadError = debugData.records
175
156
  ? getPageLoadError(navigationError, {
176
157
  url: mainDocumentUrl,
177
- loadFailureMode: navigationContext.navigation.loadFailureMode,
178
158
  networkRecords: debugData.records,
179
- warnings,
159
+ warnings: navigationContext.baseArtifacts.LighthouseRunWarnings,
180
160
  })
181
161
  : navigationError;
182
162
 
183
163
  if (pageLoadError) {
184
164
  const locale = navigationContext.resolvedConfig.settings.locale;
185
165
  const localizedMessage = format.getFormatted(pageLoadError.friendlyMessage, locale);
186
- log.error('NavigationRunner', localizedMessage, navigateResult.requestedUrl);
166
+ log.error('NavigationRunner', localizedMessage, requestedUrl);
187
167
 
188
168
  /** @type {Partial<LH.GathererArtifacts>} */
189
169
  const artifacts = {};
190
- const pageLoadErrorId = `pageLoadError-${navigationContext.navigation.id}`;
170
+ const pageLoadErrorId = 'pageLoadError-defaultPass';
191
171
  if (debugData.devtoolsLog) {
192
172
  artifacts.DevtoolsLogError = debugData.devtoolsLog;
193
173
  artifacts.devtoolsLogs = {[pageLoadErrorId]: debugData.devtoolsLog};
@@ -197,20 +177,14 @@ async function _computeNavigationResult(
197
177
  artifacts.traces = {[pageLoadErrorId]: debugData.trace};
198
178
  }
199
179
 
200
- return {
201
- pageLoadError,
202
- artifacts,
203
- warnings: [...warnings, pageLoadError.friendlyMessage],
204
- };
180
+ navigationContext.baseArtifacts.LighthouseRunWarnings.push(pageLoadError.friendlyMessage);
181
+ navigationContext.baseArtifacts.PageLoadError = pageLoadError;
182
+
183
+ return artifacts;
205
184
  } else {
206
185
  await collectPhaseArtifacts({phase: 'getArtifact', ...phaseState});
207
186
 
208
- const artifacts = await awaitArtifacts(phaseState.artifactState);
209
- return {
210
- artifacts,
211
- warnings,
212
- pageLoadError: undefined,
213
- };
187
+ return await awaitArtifacts(phaseState.artifactState);
214
188
  }
215
189
  }
216
190
 
@@ -219,6 +193,10 @@ async function _computeNavigationResult(
219
193
  * @return {ReturnType<typeof _computeNavigationResult>}
220
194
  */
221
195
  async function _navigation(navigationContext) {
196
+ if (!navigationContext.resolvedConfig.artifacts) {
197
+ throw new Error('No artifacts were defined on the config');
198
+ }
199
+
222
200
  const artifactState = getEmptyArtifactState();
223
201
  const phaseState = {
224
202
  url: await navigationContext.driver.url(),
@@ -226,14 +204,12 @@ async function _navigation(navigationContext) {
226
204
  driver: navigationContext.driver,
227
205
  page: navigationContext.page,
228
206
  computedCache: navigationContext.computedCache,
229
- artifactDefinitions: navigationContext.navigation.artifacts,
207
+ artifactDefinitions: navigationContext.resolvedConfig.artifacts,
230
208
  artifactState,
231
209
  baseArtifacts: navigationContext.baseArtifacts,
232
210
  settings: navigationContext.resolvedConfig.settings,
233
211
  };
234
212
 
235
- const setupResult = await _setupNavigation(navigationContext);
236
-
237
213
  const disableAsyncStacks =
238
214
  await prepare.enableAsyncStacks(navigationContext.driver.defaultSession);
239
215
 
@@ -262,58 +238,7 @@ async function _navigation(navigationContext) {
262
238
 
263
239
  await _cleanupNavigation(navigationContext);
264
240
 
265
- return _computeNavigationResult(navigationContext, phaseState, setupResult, navigateResult);
266
- }
267
-
268
- /**
269
- * @param {{driver: Driver, page: LH.Puppeteer.Page, resolvedConfig: LH.Config.ResolvedConfig, requestor: LH.NavigationRequestor; baseArtifacts: LH.BaseArtifacts, computedCache: NavigationContext['computedCache']}} args
270
- * @return {Promise<{artifacts: Partial<LH.Artifacts & LH.BaseArtifacts>}>}
271
- */
272
- async function _navigations(args) {
273
- const {
274
- driver,
275
- page,
276
- resolvedConfig,
277
- requestor,
278
- baseArtifacts,
279
- computedCache,
280
- } = args;
281
-
282
- if (!resolvedConfig.artifacts || !resolvedConfig.navigations) {
283
- throw new Error('No artifacts were defined on the config');
284
- }
285
-
286
- /** @type {Partial<LH.Artifacts & LH.BaseArtifacts>} */
287
- const artifacts = {};
288
- /** @type {Array<LH.IcuMessage>} */
289
- const LighthouseRunWarnings = [];
290
-
291
- for (const navigation of resolvedConfig.navigations) {
292
- const navigationContext = {
293
- driver,
294
- page,
295
- navigation,
296
- requestor,
297
- resolvedConfig,
298
- baseArtifacts,
299
- computedCache,
300
- };
301
-
302
- let shouldHaltNavigations = false;
303
- const navigationResult = await _navigation(navigationContext);
304
- if (navigation.loadFailureMode === 'fatal') {
305
- if (navigationResult.pageLoadError) {
306
- artifacts.PageLoadError = navigationResult.pageLoadError;
307
- shouldHaltNavigations = true;
308
- }
309
- }
310
-
311
- LighthouseRunWarnings.push(...navigationResult.warnings);
312
- Object.assign(artifacts, navigationResult.artifacts);
313
- if (shouldHaltNavigations) break;
314
- }
315
-
316
- return {artifacts: {...artifacts, LighthouseRunWarnings}};
241
+ return _computeNavigationResult(navigationContext, phaseState, navigateResult);
317
242
  }
318
243
 
319
244
  /**
@@ -369,11 +294,15 @@ async function navigationGather(page, requestor, options = {}) {
369
294
  driver,
370
295
  lhBrowser,
371
296
  lhPage,
297
+ page,
372
298
  resolvedConfig,
373
299
  requestor: normalizedRequestor,
300
+ computedCache: new Map(),
374
301
  };
375
302
  const {baseArtifacts} = await _setup(context);
376
- const {artifacts} = await _navigations({...context, page, baseArtifacts, computedCache});
303
+
304
+ const artifacts = await _navigation({...context, baseArtifacts});
305
+
377
306
  await _cleanup(context);
378
307
 
379
308
  return finalizeArtifacts(baseArtifacts, artifacts);
@@ -386,9 +315,7 @@ async function navigationGather(page, requestor, options = {}) {
386
315
  export {
387
316
  navigationGather,
388
317
  _setup,
389
- _setupNavigation,
390
318
  _navigate,
391
319
  _navigation,
392
- _navigations,
393
320
  _cleanup,
394
321
  };
@@ -15,12 +15,11 @@ export function getInterstitialError(mainRecord: LH.Artifacts.NetworkRequest | u
15
15
  * Returns an error if the page load should be considered failed, e.g. from a
16
16
  * main document request failure, a security issue, etc.
17
17
  * @param {LH.LighthouseError|undefined} navigationError
18
- * @param {{url: string, loadFailureMode: LH.Config.SharedPassNavigationJson['loadFailureMode'], networkRecords: Array<LH.Artifacts.NetworkRequest>, warnings: Array<string | LH.IcuMessage>}} context
18
+ * @param {{url: string, networkRecords: Array<LH.Artifacts.NetworkRequest>, warnings: Array<string | LH.IcuMessage>}} context
19
19
  * @return {LH.LighthouseError|undefined}
20
20
  */
21
21
  export function getPageLoadError(navigationError: LH.LighthouseError | undefined, context: {
22
22
  url: string;
23
- loadFailureMode: LH.Config.SharedPassNavigationJson['loadFailureMode'];
24
23
  networkRecords: Array<LH.Artifacts.NetworkRequest>;
25
24
  warnings: Array<string | LH.IcuMessage>;
26
25
  }): LH.LighthouseError | undefined;
@@ -113,11 +113,11 @@ function getNonHtmlError(finalRecord) {
113
113
  * Returns an error if the page load should be considered failed, e.g. from a
114
114
  * main document request failure, a security issue, etc.
115
115
  * @param {LH.LighthouseError|undefined} navigationError
116
- * @param {{url: string, loadFailureMode: LH.Config.SharedPassNavigationJson['loadFailureMode'], networkRecords: Array<LH.Artifacts.NetworkRequest>, warnings: Array<string | LH.IcuMessage>}} context
116
+ * @param {{url: string, networkRecords: Array<LH.Artifacts.NetworkRequest>, warnings: Array<string | LH.IcuMessage>}} context
117
117
  * @return {LH.LighthouseError|undefined}
118
118
  */
119
119
  function getPageLoadError(navigationError, context) {
120
- const {url, loadFailureMode, networkRecords} = context;
120
+ const {url, networkRecords} = context;
121
121
  /** @type {LH.Artifacts.NetworkRequest|undefined} */
122
122
  let mainRecord = NetworkAnalyzer.findResourceForUrl(networkRecords, url);
123
123
 
@@ -148,10 +148,6 @@ function getPageLoadError(navigationError, context) {
148
148
  const interstitialError = getInterstitialError(mainRecord, networkRecords);
149
149
  const nonHtmlError = getNonHtmlError(finalRecord);
150
150
 
151
- // Check to see if we need to ignore the page load failure.
152
- // e.g. When the driver is offline, the load will fail without page offline support.
153
- if (loadFailureMode === 'ignore') return;
154
-
155
151
  // We want to special-case the interstitial beyond FAILED_DOCUMENT_REQUEST. See https://github.com/GoogleChrome/lighthouse/pull/8865#issuecomment-497507618
156
152
  if (interstitialError) return interstitialError;
157
153