lighthouse 10.2.0 → 10.3.0-dev.20230614

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 (133) hide show
  1. package/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +4 -6
  2. package/core/audits/accessibility/html-xml-lang-mismatch.d.ts +10 -0
  3. package/core/audits/accessibility/html-xml-lang-mismatch.js +47 -0
  4. package/core/audits/accessibility/input-button-name.d.ts +10 -0
  5. package/core/audits/accessibility/input-button-name.js +44 -0
  6. package/core/audits/accessibility/table-fake-caption.d.ts +10 -0
  7. package/core/audits/accessibility/table-fake-caption.js +47 -0
  8. package/core/audits/accessibility/td-has-header.d.ts +10 -0
  9. package/core/audits/accessibility/td-has-header.js +45 -0
  10. package/core/audits/audit.d.ts +2 -1
  11. package/core/audits/audit.js +5 -2
  12. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +3 -3
  13. package/core/audits/byte-efficiency/byte-efficiency-audit.js +14 -19
  14. package/core/audits/deprecations.js +1 -1
  15. package/core/audits/largest-contentful-paint-element.d.ts +14 -2
  16. package/core/audits/largest-contentful-paint-element.js +49 -31
  17. package/core/audits/layout-shift-elements.d.ts +3 -2
  18. package/core/audits/layout-shift-elements.js +10 -2
  19. package/core/audits/metrics.js +0 -2
  20. package/core/audits/network-requests.js +6 -0
  21. package/core/audits/seo/crawlable-anchors.js +4 -0
  22. package/core/audits/server-response-time.d.ts +2 -1
  23. package/core/audits/server-response-time.js +17 -3
  24. package/core/audits/uses-rel-preconnect.js +20 -4
  25. package/core/computed/entity-classification.d.ts +14 -1
  26. package/core/computed/entity-classification.js +61 -6
  27. package/core/computed/metrics/cumulative-layout-shift.d.ts +2 -9
  28. package/core/computed/metrics/cumulative-layout-shift.js +3 -16
  29. package/core/computed/metrics/time-to-first-byte.js +10 -7
  30. package/core/computed/metrics/timing-summary.js +0 -3
  31. package/core/config/default-config.js +8 -0
  32. package/core/gather/driver/execution-context.js +13 -5
  33. package/core/gather/driver/target-manager.d.ts +13 -0
  34. package/core/gather/driver/target-manager.js +49 -0
  35. package/core/gather/gatherers/accessibility.js +19 -20
  36. package/core/gather/gatherers/anchor-elements.js +2 -0
  37. package/core/gather/gatherers/global-listeners.js +38 -21
  38. package/core/gather/gatherers/inspector-issues.js +2 -1
  39. package/core/gather/gatherers/trace-elements.d.ts +3 -2
  40. package/core/gather/gatherers/trace-elements.js +10 -19
  41. package/core/legacy/config/config.d.ts +1 -1
  42. package/core/legacy/config/config.js +1 -1
  43. package/core/legacy/gather/driver.d.ts +1 -0
  44. package/core/legacy/gather/driver.js +11 -0
  45. package/core/lib/asset-saver.d.ts +4 -0
  46. package/core/lib/asset-saver.js +19 -0
  47. package/core/lib/bf-cache-strings.d.ts +3 -0
  48. package/core/lib/bf-cache-strings.js +248 -232
  49. package/core/lib/cdt/generated/SourceMap.d.ts +18 -31
  50. package/core/lib/cdt/generated/SourceMap.js +51 -101
  51. package/core/lib/dependency-graph/simulator/network-analyzer.d.ts +6 -2
  52. package/core/lib/dependency-graph/simulator/network-analyzer.js +45 -13
  53. package/core/lib/deprecation-description.d.ts +17 -0
  54. package/core/lib/deprecation-description.js +71 -0
  55. package/core/lib/deprecations-strings.d.ts +282 -63
  56. package/core/lib/deprecations-strings.js +282 -551
  57. package/core/lib/lh-error.d.ts +9 -4
  58. package/core/lib/lh-error.js +15 -11
  59. package/core/lib/network-request.d.ts +13 -6
  60. package/core/lib/network-request.js +39 -14
  61. package/core/lib/stack-packs.js +4 -0
  62. package/core/lib/tracehouse/trace-processor.js +1 -1
  63. package/core/lib/url-utils.js +4 -0
  64. package/core/runner.js +4 -2
  65. package/dist/report/bundle.esm.js +24 -7
  66. package/dist/report/flow.js +3 -3
  67. package/dist/report/standalone.js +8 -8
  68. package/package.json +13 -13
  69. package/readme.md +7 -0
  70. package/report/assets/styles.css +18 -2
  71. package/report/assets/templates.html +4 -0
  72. package/report/renderer/category-renderer.js +5 -2
  73. package/report/renderer/components.js +2 -2
  74. package/report/renderer/dom.d.ts +4 -1
  75. package/report/renderer/dom.js +3 -2
  76. package/shared/localization/locales/ar-XB.json +20 -170
  77. package/shared/localization/locales/ar.json +20 -170
  78. package/shared/localization/locales/bg.json +19 -169
  79. package/shared/localization/locales/ca.json +19 -169
  80. package/shared/localization/locales/cs.json +19 -169
  81. package/shared/localization/locales/da.json +19 -169
  82. package/shared/localization/locales/de.json +19 -169
  83. package/shared/localization/locales/el.json +19 -169
  84. package/shared/localization/locales/en-GB.json +9 -159
  85. package/shared/localization/locales/en-US.json +166 -70
  86. package/shared/localization/locales/en-XA.json +20 -170
  87. package/shared/localization/locales/en-XL.json +166 -70
  88. package/shared/localization/locales/es-419.json +19 -169
  89. package/shared/localization/locales/es.json +19 -169
  90. package/shared/localization/locales/fi.json +19 -169
  91. package/shared/localization/locales/fil.json +17 -167
  92. package/shared/localization/locales/fr.json +18 -168
  93. package/shared/localization/locales/he.json +19 -169
  94. package/shared/localization/locales/hi.json +20 -170
  95. package/shared/localization/locales/hr.json +19 -169
  96. package/shared/localization/locales/hu.json +19 -169
  97. package/shared/localization/locales/id.json +19 -169
  98. package/shared/localization/locales/it.json +19 -169
  99. package/shared/localization/locales/ja.json +19 -169
  100. package/shared/localization/locales/ko.json +19 -169
  101. package/shared/localization/locales/lt.json +20 -170
  102. package/shared/localization/locales/lv.json +20 -170
  103. package/shared/localization/locales/nl.json +18 -168
  104. package/shared/localization/locales/no.json +19 -169
  105. package/shared/localization/locales/pl.json +19 -169
  106. package/shared/localization/locales/pt-PT.json +19 -169
  107. package/shared/localization/locales/pt.json +19 -169
  108. package/shared/localization/locales/ro.json +19 -169
  109. package/shared/localization/locales/ru.json +19 -169
  110. package/shared/localization/locales/sk.json +20 -170
  111. package/shared/localization/locales/sl.json +19 -169
  112. package/shared/localization/locales/sr-Latn.json +19 -169
  113. package/shared/localization/locales/sr.json +19 -169
  114. package/shared/localization/locales/sv.json +19 -169
  115. package/shared/localization/locales/ta.json +19 -169
  116. package/shared/localization/locales/te.json +19 -169
  117. package/shared/localization/locales/th.json +19 -169
  118. package/shared/localization/locales/tr.json +19 -169
  119. package/shared/localization/locales/uk.json +19 -169
  120. package/shared/localization/locales/vi.json +20 -170
  121. package/shared/localization/locales/zh-HK.json +19 -169
  122. package/shared/localization/locales/zh-TW.json +19 -169
  123. package/shared/localization/locales/zh.json +19 -169
  124. package/shared/util.d.ts +6 -0
  125. package/shared/util.js +14 -1
  126. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -1
  127. package/tsconfig-base.json +1 -1
  128. package/types/artifacts.d.ts +10 -8
  129. package/types/audit.d.ts +5 -0
  130. package/types/gatherer.d.ts +1 -0
  131. package/types/lhr/audit-details.d.ts +1 -0
  132. package/types/lhr/audit-result.d.ts +10 -0
  133. package/types/internal/es-main.d.ts +0 -18
@@ -53,6 +53,7 @@ function collectAnchorElements() {
53
53
  text: node.innerText, // we don't want to return hidden text, so use innerText
54
54
  rel: node.rel,
55
55
  target: node.target,
56
+ id: node.getAttribute('id') || '',
56
57
  // @ts-expect-error - getNodeDetails put into scope via stringification
57
58
  node: getNodeDetails(node),
58
59
  };
@@ -66,6 +67,7 @@ function collectAnchorElements() {
66
67
  text: node.textContent || '',
67
68
  rel: '',
68
69
  target: node.target.baseVal || '',
70
+ id: node.getAttribute('id') || '',
69
71
  // @ts-expect-error - getNodeDetails put into scope via stringification
70
72
  node: getNodeDetails(node),
71
73
  };
@@ -11,6 +11,8 @@
11
11
  * around page unload, but this can be expanded in the future.
12
12
  */
13
13
 
14
+ import log from 'lighthouse-logger';
15
+
14
16
  import FRGatherer from '../base-gatherer.js';
15
17
 
16
18
  class GlobalListeners extends FRGatherer {
@@ -61,30 +63,45 @@ class GlobalListeners extends FRGatherer {
61
63
  async getArtifact(passContext) {
62
64
  const session = passContext.driver.defaultSession;
63
65
 
64
- // Get a RemoteObject handle to `window`.
65
- const {result: {objectId}} = await session.sendCommand('Runtime.evaluate', {
66
- expression: 'window',
67
- returnByValue: false,
68
- });
69
- if (!objectId) {
70
- throw new Error('Error fetching information about the global object');
71
- }
66
+ /** @type {Array<LH.Artifacts.GlobalListener>} */
67
+ const listeners = [];
72
68
 
73
- // And get all its listeners of interest.
74
- const {listeners} = await session.sendCommand('DOMDebugger.getEventListeners', {objectId});
75
- const filteredListeners = listeners.filter(GlobalListeners._filterForAllowlistedTypes)
76
- .map(listener => {
77
- const {type, scriptId, lineNumber, columnNumber} = listener;
78
- return {
79
- type,
80
- scriptId,
81
- lineNumber,
82
- columnNumber,
83
- };
84
- });
69
+ for (const executionContext of passContext.driver.targetManager.mainFrameExecutionContexts()) {
70
+ // Get a RemoteObject handle to `window`.
71
+ let objectId;
72
+ try {
73
+ const {result} = await session.sendCommand('Runtime.evaluate', {
74
+ expression: 'window',
75
+ returnByValue: false,
76
+ uniqueContextId: executionContext.uniqueId,
77
+ });
78
+ if (!result.objectId) {
79
+ throw new Error('Error fetching information about the global object');
80
+ }
81
+ objectId = result.objectId;
82
+ } catch (err) {
83
+ // Execution context is no longer valid, but don't let that fail the gatherer.
84
+ log.warn('Execution context is no longer valid', executionContext, err);
85
+ continue;
86
+ }
87
+
88
+ // And get all its listeners of interest.
89
+ const response = await session.sendCommand('DOMDebugger.getEventListeners', {objectId});
90
+ for (const listener of response.listeners) {
91
+ if (GlobalListeners._filterForAllowlistedTypes(listener)) {
92
+ const {type, scriptId, lineNumber, columnNumber} = listener;
93
+ listeners.push({
94
+ type,
95
+ scriptId,
96
+ lineNumber,
97
+ columnNumber,
98
+ });
99
+ }
100
+ }
101
+ }
85
102
 
86
103
  // Dedupe listeners with same underlying data.
87
- return this.dedupeListeners(filteredListeners);
104
+ return this.dedupeListeners(listeners);
88
105
  }
89
106
  }
90
107
 
@@ -75,7 +75,8 @@ class InspectorIssues extends FRGatherer {
75
75
  quirksModeIssue: [],
76
76
  cookieIssue: [],
77
77
  sharedArrayBufferIssue: [],
78
- twaQualityEnforcement: [],
78
+ stylesheetLoadingIssue: [],
79
+ federatedAuthUserInfoRequestIssue: [],
79
80
  };
80
81
  const keys = /** @type {Array<keyof LH.Artifacts['InspectorIssues']>} */(Object.keys(artifact));
81
82
  for (const key of keys) {
@@ -21,10 +21,10 @@ declare class TraceElements extends FRGatherer {
21
21
  * We calculate the score per element by taking the 'score' of each layout shift event and
22
22
  * distributing it between all the nodes that were shifted, proportianal to the impact region of
23
23
  * each shifted element.
24
- * @param {Array<LH.TraceEvent>} mainThreadEvents
24
+ * @param {LH.Artifacts.ProcessedTrace} processedTrace
25
25
  * @return {Array<TraceElementData>}
26
26
  */
27
- static getTopLayoutShiftElements(mainThreadEvents: Array<LH.TraceEvent>): Array<TraceElementData>;
27
+ static getTopLayoutShiftElements(processedTrace: LH.Artifacts.ProcessedTrace): Array<TraceElementData>;
28
28
  /**
29
29
  * @param {LH.Trace} trace
30
30
  * @param {LH.Gatherer.FRTransitionalContext} context
@@ -80,4 +80,5 @@ declare class TraceElements extends FRGatherer {
80
80
  }
81
81
  import FRGatherer from '../base-gatherer.js';
82
82
  import Trace from './trace.js';
83
+ import { ProcessedTrace } from '../../computed/processed-trace.js';
83
84
  //# sourceMappingURL=trace-elements.d.ts.map
@@ -22,6 +22,7 @@ import {ProcessedTrace} from '../../computed/processed-trace.js';
22
22
  import {ProcessedNavigation} from '../../computed/processed-navigation.js';
23
23
  import {LighthouseError} from '../../lib/lh-error.js';
24
24
  import {Responsiveness} from '../../computed/metrics/responsiveness.js';
25
+ import {CumulativeLayoutShift} from '../../computed/metrics/cumulative-layout-shift.js';
25
26
 
26
27
  /** @typedef {{nodeId: number, score?: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[], type?: string}} TraceElementData */
27
28
 
@@ -80,34 +81,24 @@ class TraceElements extends FRGatherer {
80
81
  * We calculate the score per element by taking the 'score' of each layout shift event and
81
82
  * distributing it between all the nodes that were shifted, proportianal to the impact region of
82
83
  * each shifted element.
83
- * @param {Array<LH.TraceEvent>} mainThreadEvents
84
+ * @param {LH.Artifacts.ProcessedTrace} processedTrace
84
85
  * @return {Array<TraceElementData>}
85
86
  */
86
- static getTopLayoutShiftElements(mainThreadEvents) {
87
+ static getTopLayoutShiftElements(processedTrace) {
87
88
  /** @type {Map<number, number>} */
88
89
  const clsPerNode = new Map();
89
- const shiftEvents = mainThreadEvents
90
- .filter(e => e.name === 'LayoutShift')
91
- .map(e => e.args?.data);
92
- const indexFirstEventWithoutInput =
93
- shiftEvents.findIndex(event => event && !event.had_recent_input);
94
-
95
- shiftEvents.forEach((event, index) => {
96
- if (!event || !event.impacted_nodes || !event.score) {
97
- return;
98
- }
90
+ const shiftEvents = CumulativeLayoutShift.getLayoutShiftEvents(processedTrace);
99
91
 
100
- // Ignore events with input, unless it's one of the initial events.
101
- // See comment in computed/metrics/cumulative-layout-shift.js.
102
- if (indexFirstEventWithoutInput !== -1 && index >= indexFirstEventWithoutInput) {
103
- if (event.had_recent_input) return;
92
+ shiftEvents.forEach((event) => {
93
+ if (!event || !event.impactedNodes) {
94
+ return;
104
95
  }
105
96
 
106
97
  let totalAreaOfImpact = 0;
107
98
  /** @type {Map<number, number>} */
108
99
  const pixelsMovedPerNode = new Map();
109
100
 
110
- event.impacted_nodes.forEach(node => {
101
+ event.impactedNodes.forEach(node => {
111
102
  if (!node.node_id || !node.old_rect || !node.new_rect) {
112
103
  return;
113
104
  }
@@ -124,7 +115,7 @@ class TraceElements extends FRGatherer {
124
115
 
125
116
  for (const [nodeId, pixelsMoved] of pixelsMovedPerNode.entries()) {
126
117
  let clsContribution = clsPerNode.get(nodeId) || 0;
127
- clsContribution += (pixelsMoved / totalAreaOfImpact) * event.score;
118
+ clsContribution += (pixelsMoved / totalAreaOfImpact) * event.weightedScore;
128
119
  clsPerNode.set(nodeId, clsContribution);
129
120
  }
130
121
  });
@@ -272,7 +263,7 @@ class TraceElements extends FRGatherer {
272
263
  const {mainThreadEvents} = processedTrace;
273
264
 
274
265
  const lcpNodeData = await TraceElements.getLcpElement(trace, context);
275
- const clsNodeData = TraceElements.getTopLayoutShiftElements(mainThreadEvents);
266
+ const clsNodeData = TraceElements.getTopLayoutShiftElements(processedTrace);
276
267
  const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
277
268
  const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
278
269
 
@@ -77,7 +77,7 @@ export class LegacyResolvedConfig implements LH.Config.LegacyResolvedConfig {
77
77
  */
78
78
  static requireGatherers(passes: Array<Required<LH.Config.PassJson>> | null, configDir?: string | undefined): Promise<LegacyResolvedConfig['passes']>;
79
79
  /**
80
- * @deprecated `Config.fromJson` should be used instead.
80
+ * @deprecated `LegacyResolvedConfig.fromJson` should be used instead.
81
81
  * @constructor
82
82
  * @param {LH.Config} config
83
83
  * @param {{settings: LH.Config.Settings, passes: ?LH.Config.Pass[], audits: ?LH.Config.AuditDefn[]}} opts
@@ -205,7 +205,7 @@ class LegacyResolvedConfig {
205
205
  }
206
206
 
207
207
  /**
208
- * @deprecated `Config.fromJson` should be used instead.
208
+ * @deprecated `LegacyResolvedConfig.fromJson` should be used instead.
209
209
  * @constructor
210
210
  * @param {LH.Config} config
211
211
  * @param {{settings: LH.Config.Settings, passes: ?LH.Config.Pass[], audits: ?LH.Config.AuditDefn[]}} opts
@@ -43,6 +43,7 @@ export class Driver implements LH.Gatherer.FRTransitionalDriver {
43
43
  private evaluateAsync;
44
44
  targetManager: {
45
45
  rootSession: () => Driver;
46
+ mainFrameExecutionContexts: () => LH.Crdp.Runtime.ExecutionContextDescription[];
46
47
  /**
47
48
  * Bind to *any* protocol event.
48
49
  * @param {'protocolevent'} event
@@ -101,6 +101,17 @@ class Driver {
101
101
  rootSession: () => {
102
102
  return this.defaultSession;
103
103
  },
104
+ // For legacy driver, only bother supporting access to the default execution context.
105
+ mainFrameExecutionContexts: () => {
106
+ // @ts-expect-error - undefined ids are OK for purposes of calling protocol commands like Runtime.evaluate.
107
+ return [/** @type {LH.Crdp.Runtime.ExecutionContextDescription} */({
108
+ id: undefined,
109
+ uniqueId: undefined,
110
+ origin: '',
111
+ name: '',
112
+ auxData: {isDefault: true, type: 'default', frameId: ''},
113
+ })];
114
+ },
104
115
  /**
105
116
  * Bind to *any* protocol event.
106
117
  * @param {'protocolevent'} event
@@ -98,4 +98,8 @@ export function stringifyReplacer(key: string, value: any): any;
98
98
  * @param {LH.Result.MeasureEntry[]} timings
99
99
  */
100
100
  export function normalizeTimingEntries(timings: LH.Result.MeasureEntry[]): void;
101
+ /**
102
+ * @param {LH.Result} lhr
103
+ */
104
+ export function elideAuditErrorStacks(lhr: LH.Result): void;
101
105
  //# sourceMappingURL=asset-saver.d.ts.map
@@ -7,6 +7,7 @@
7
7
  import fs from 'fs';
8
8
  import path from 'path';
9
9
  import stream from 'stream';
10
+ import url from 'url';
10
11
 
11
12
  import log from 'lighthouse-logger';
12
13
 
@@ -16,6 +17,7 @@ import {MetricTraceEvents} from './traces/metric-trace-events.js';
16
17
  import {NetworkAnalysis} from '../computed/network-analysis.js';
17
18
  import {LoadSimulator} from '../computed/load-simulator.js';
18
19
  import {LighthouseError} from '../lib/lh-error.js';
20
+ import {LH_ROOT} from '../../root.js';
19
21
 
20
22
  const optionsFilename = 'options.json';
21
23
  const artifactsFilename = 'artifacts.json';
@@ -425,6 +427,22 @@ function normalizeTimingEntries(timings) {
425
427
  }
426
428
  }
427
429
 
430
+ /**
431
+ * @param {LH.Result} lhr
432
+ */
433
+ function elideAuditErrorStacks(lhr) {
434
+ const baseCallFrameUrl = url.pathToFileURL(LH_ROOT);
435
+ for (const auditResult of Object.values(lhr.audits)) {
436
+ if (auditResult.errorStack) {
437
+ auditResult.errorStack = auditResult.errorStack
438
+ // Make paths relative to the repo root.
439
+ .replaceAll(baseCallFrameUrl.pathname, '')
440
+ // Remove line/col info.
441
+ .replaceAll(/:\d+:\d+/g, '');
442
+ }
443
+ }
444
+ }
445
+
428
446
  export {
429
447
  saveArtifacts,
430
448
  saveFlowArtifacts,
@@ -438,4 +456,5 @@ export {
438
456
  saveLanternNetworkData,
439
457
  stringifyReplacer,
440
458
  normalizeTimingEntries,
459
+ elideAuditErrorStacks,
441
460
  };
@@ -117,5 +117,8 @@ export namespace UIStrings {
117
117
  const errorDocument: string;
118
118
  const fencedFramesEmbedder: string;
119
119
  const keepaliveRequest: string;
120
+ const authorizationHeader: string;
121
+ const indexedDBEvent: string;
122
+ const cookieDisabled: string;
120
123
  }
121
124
  //# sourceMappingURL=bf-cache-strings.d.ts.map