lighthouse 11.6.0-dev.20240312 → 11.6.0-dev.20240314

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.
@@ -70,9 +70,7 @@ class InteractionToNextPaint extends Audit {
70
70
  return {score: null, notApplicable: true};
71
71
  }
72
72
 
73
- // TODO: remove workaround once 103.0.5052.0 is sufficiently released.
74
- const timing = interactionEvent.name === 'FallbackTiming' ?
75
- interactionEvent.duration : interactionEvent.args.data.duration;
73
+ const timing = interactionEvent.args.data.duration;
76
74
 
77
75
  return {
78
76
  score: Audit.computeLogNormalScore({p10: context.options.p10, median: context.options.median},
@@ -14,7 +14,6 @@ import {taskGroups} from '../lib/tracehouse/task-groups.js';
14
14
  import {TraceProcessor} from '../lib/tracehouse/trace-processor.js';
15
15
  import {getExecutionTimingsByURL} from '../lib/tracehouse/task-summary.js';
16
16
  import InteractionToNextPaint from './metrics/interaction-to-next-paint.js';
17
- import {LighthouseError} from '../lib/lh-error.js';
18
17
 
19
18
  /** @typedef {import('../computed/metrics/responsiveness.js').EventTimingEvent} EventTimingEvent */
20
19
  /** @typedef {import('../lib/tracehouse/main-thread-tasks.js').TaskNode} TaskNode */
@@ -243,13 +242,6 @@ class WorkDuringInteraction extends Audit {
243
242
  metricSavings: {INP: 0},
244
243
  };
245
244
  }
246
- // TODO: remove workaround once 103.0.5052.0 is sufficiently released.
247
- if (interactionEvent.name === 'FallbackTiming') {
248
- throw new LighthouseError(
249
- LighthouseError.errors.UNSUPPORTED_OLD_CHROME,
250
- {featureName: 'detailed EventTiming trace events'}
251
- );
252
- }
253
245
 
254
246
  const auditDetailsItems = [];
255
247
 
@@ -38,21 +38,13 @@ export type EventTimingEvent = LH.Trace.AsyncEvent & {
38
38
  data: EventTimingData;
39
39
  };
40
40
  };
41
- /**
42
- * A fallback EventTiming placeholder, used if updated EventTiming events are not available.
43
- * TODO: Remove once 103.0.5052.0 is sufficiently released.
44
- */
45
- export type FallbackTimingEvent = {
46
- name: 'FallbackTiming';
47
- duration: number;
48
- };
49
41
  declare const ResponsivenessComputed: typeof Responsiveness & {
50
42
  request: (dependencies: {
51
43
  trace: LH.Trace;
52
44
  settings: LH.Audit.Context['settings'];
53
45
  }, context: import("../../../types/utility-types.js").default.ImmutableObject<{
54
46
  computedCache: Map<string, import("../../lib/arbitrary-equality-map.js").ArbitraryEqualityMap>;
55
- }>) => Promise<EventTimingEvent | FallbackTimingEvent | null>;
47
+ }>) => Promise<EventTimingEvent | null>;
56
48
  };
57
49
  declare class Responsiveness {
58
50
  /**
@@ -70,18 +62,18 @@ declare class Responsiveness {
70
62
  * one interaction had this duration by returning the first found.
71
63
  * @param {ResponsivenessEvent} responsivenessEvent
72
64
  * @param {LH.Trace} trace
73
- * @return {EventTimingEvent|FallbackTimingEvent}
65
+ * @return {EventTimingEvent}
74
66
  */
75
- static findInteractionEvent(responsivenessEvent: ResponsivenessEvent, { traceEvents }: LH.Trace): EventTimingEvent | FallbackTimingEvent;
67
+ static findInteractionEvent(responsivenessEvent: ResponsivenessEvent, { traceEvents }: LH.Trace): EventTimingEvent;
76
68
  /**
77
69
  * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
78
70
  * @param {LH.Artifacts.ComputedContext} context
79
- * @return {Promise<EventTimingEvent|FallbackTimingEvent|null>}
71
+ * @return {Promise<EventTimingEvent|null>}
80
72
  */
81
73
  static compute_(data: {
82
74
  trace: LH.Trace;
83
75
  settings: LH.Audit.Context['settings'];
84
- }, context: LH.Artifacts.ComputedContext): Promise<EventTimingEvent | FallbackTimingEvent | null>;
76
+ }, context: LH.Artifacts.ComputedContext): Promise<EventTimingEvent | null>;
85
77
  }
86
78
  import { ProcessedTrace } from '../processed-trace.js';
87
79
  //# sourceMappingURL=responsiveness.d.ts.map
@@ -24,14 +24,10 @@
24
24
  * @property {number} interactionId
25
25
  */
26
26
  /** @typedef {LH.Trace.AsyncEvent & {name: 'EventTiming', args: {data: EventTimingData}}} EventTimingEvent */
27
- /**
28
- * A fallback EventTiming placeholder, used if updated EventTiming events are not available.
29
- * TODO: Remove once 103.0.5052.0 is sufficiently released.
30
- * @typedef {{name: 'FallbackTiming', duration: number}} FallbackTimingEvent
31
- */
32
27
 
33
28
  import {ProcessedTrace} from '../processed-trace.js';
34
29
  import {makeComputedArtifact} from '../computed-artifact.js';
30
+ import {LighthouseError} from '../../lib/lh-error.js';
35
31
 
36
32
  const KEYBOARD_EVENTS = new Set(['keydown', 'keypress', 'keyup']);
37
33
  const CLICK_TAP_DRAG_EVENTS = new Set([
@@ -79,7 +75,7 @@ class Responsiveness {
79
75
  * one interaction had this duration by returning the first found.
80
76
  * @param {ResponsivenessEvent} responsivenessEvent
81
77
  * @param {LH.Trace} trace
82
- * @return {EventTimingEvent|FallbackTimingEvent}
78
+ * @return {EventTimingEvent}
83
79
  */
84
80
  static findInteractionEvent(responsivenessEvent, {traceEvents}) {
85
81
  const candidates = traceEvents.filter(/** @return {evt is EventTimingEvent} */ evt => {
@@ -87,15 +83,15 @@ class Responsiveness {
87
83
  return evt.name === 'EventTiming' && evt.ph !== 'e';
88
84
  });
89
85
 
90
- // If trace is from < m103, the timestamps cannot be trusted, so we craft a fallback
91
- // <m103 traces (bad) had a args.frame
86
+ // If trace is from < m103, the timestamps cannot be trusted
87
+ // <m103 traces (bad) had a args.frame (we used to provide a fallback trace event, but not
88
+ // any more)
92
89
  // m103+ traces (good) have a args.data.frame (https://crrev.com/c/3632661)
93
- // TODO(compat): remove FallbackTiming handling when we don't care about <m103
94
90
  if (candidates.length && candidates.every(candidate => !candidate.args.data?.frame)) {
95
- return {
96
- name: 'FallbackTiming',
97
- duration: responsivenessEvent.args.data.maxDuration,
98
- };
91
+ throw new LighthouseError(
92
+ LighthouseError.errors.UNSUPPORTED_OLD_CHROME,
93
+ {featureName: 'detailed EventTiming trace events'}
94
+ );
99
95
  }
100
96
 
101
97
  const {maxDuration, interactionType} = responsivenessEvent.args.data;
@@ -136,7 +132,7 @@ class Responsiveness {
136
132
  /**
137
133
  * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
138
134
  * @param {LH.Artifacts.ComputedContext} context
139
- * @return {Promise<EventTimingEvent|FallbackTimingEvent|null>}
135
+ * @return {Promise<EventTimingEvent|null>}
140
136
  */
141
137
  static async compute_(data, context) {
142
138
  const {settings, trace} = data;
@@ -12,15 +12,7 @@ declare class CSSUsage extends BaseGatherer {
12
12
  /**
13
13
  * @param {LH.Crdp.CSS.StyleSheetAddedEvent} event
14
14
  */
15
- _onStylesheetAdded(event: LH.Crdp.CSS.StyleSheetAddedEvent): Promise<void>;
16
- /**
17
- * @param {LH.Gatherer.Context} context
18
- */
19
- startCSSUsageTracking(context: LH.Gatherer.Context): Promise<void>;
20
- /**
21
- * @param {LH.Gatherer.Context} context
22
- */
23
- stopCSSUsageTracking(context: LH.Gatherer.Context): Promise<void>;
15
+ _onStylesheetAdded(event: LH.Crdp.CSS.StyleSheetAddedEvent): void;
24
16
  /**
25
17
  * @param {LH.Gatherer.Context} context
26
18
  */
@@ -36,7 +36,7 @@ class CSSUsage extends BaseGatherer {
36
36
  /**
37
37
  * @param {LH.Crdp.CSS.StyleSheetAddedEvent} event
38
38
  */
39
- async _onStylesheetAdded(event) {
39
+ _onStylesheetAdded(event) {
40
40
  if (!this._session) throw new Error('Session not initialized');
41
41
  const styleSheetId = event.header.styleSheetId;
42
42
  const sheetPromise = this._session.sendCommand('CSS.getStyleSheetText', {styleSheetId})
@@ -66,41 +66,43 @@ class CSSUsage extends BaseGatherer {
66
66
  /**
67
67
  * @param {LH.Gatherer.Context} context
68
68
  */
69
- async startCSSUsageTracking(context) {
69
+ async startInstrumentation(context) {
70
70
  const session = context.driver.defaultSession;
71
71
  this._session = session;
72
- session.on('CSS.styleSheetAdded', this._onStylesheetAdded);
72
+
73
+ // Calling `CSS.enable` will emit events for stylesheets currently on the page.
74
+ // We want to ignore these events in navigation mode because they are not relevant to the
75
+ // navigation that is about to happen. Adding the event listener *after* calling `CSS.enable`
76
+ // ensures that the events for pre-existing stylesheets are ignored.
77
+ const isNavigation = context.gatherMode === 'navigation';
78
+ if (!isNavigation) {
79
+ session.on('CSS.styleSheetAdded', this._onStylesheetAdded);
80
+ }
73
81
 
74
82
  await session.sendCommand('DOM.enable');
75
83
  await session.sendCommand('CSS.enable');
76
84
  await session.sendCommand('CSS.startRuleUsageTracking');
85
+
86
+ if (isNavigation) {
87
+ session.on('CSS.styleSheetAdded', this._onStylesheetAdded);
88
+ }
77
89
  }
78
90
 
79
91
 
80
92
  /**
81
93
  * @param {LH.Gatherer.Context} context
82
94
  */
83
- async stopCSSUsageTracking(context) {
95
+ async stopInstrumentation(context) {
84
96
  const session = context.driver.defaultSession;
85
97
  const coverageResponse = await session.sendCommand('CSS.stopRuleUsageTracking');
86
98
  this._ruleUsage = coverageResponse.ruleUsage;
87
99
  session.off('CSS.styleSheetAdded', this._onStylesheetAdded);
88
- }
89
100
 
90
- /**
91
- * @param {LH.Gatherer.Context} context
92
- */
93
- async startInstrumentation(context) {
94
- if (context.gatherMode !== 'timespan') return;
95
- await this.startCSSUsageTracking(context);
96
- }
101
+ // Ensure we finish fetching all stylesheet contents before disabling the CSS domain
102
+ await Promise.all(this._sheetPromises.values());
97
103
 
98
- /**
99
- * @param {LH.Gatherer.Context} context
100
- */
101
- async stopInstrumentation(context) {
102
- if (context.gatherMode !== 'timespan') return;
103
- await this.stopCSSUsageTracking(context);
104
+ await session.sendCommand('CSS.disable');
105
+ await session.sendCommand('DOM.disable');
104
106
  }
105
107
 
106
108
  /**
@@ -108,17 +110,16 @@ class CSSUsage extends BaseGatherer {
108
110
  * @return {Promise<LH.Artifacts['CSSUsage']>}
109
111
  */
110
112
  async getArtifact(context) {
111
- const session = context.driver.defaultSession;
112
113
  const executionContext = context.driver.executionContext;
113
114
 
114
- if (context.gatherMode !== 'timespan') {
115
- await this.startCSSUsageTracking(context);
115
+ if (context.gatherMode === 'snapshot') {
116
+ await this.startInstrumentation(context);
116
117
 
117
118
  // Force style to recompute.
118
119
  // Doesn't appear to be necessary in newer versions of Chrome.
119
120
  await executionContext.evaluateAsync('getComputedStyle(document.body)');
120
121
 
121
- await this.stopCSSUsageTracking(context);
122
+ await this.stopInstrumentation(context);
122
123
  }
123
124
 
124
125
  /** @type {Map<string, LH.Artifacts.CSSStyleSheetInfo>} */
@@ -140,9 +141,6 @@ class CSSUsage extends BaseGatherer {
140
141
  dedupedStylesheets.set(sheet.content, sheet);
141
142
  }
142
143
 
143
- await session.sendCommand('CSS.disable');
144
- await session.sendCommand('DOM.disable');
145
-
146
144
  if (!this._ruleUsage) throw new Error('Issue collecting rule usages');
147
145
 
148
146
  return {
@@ -124,9 +124,7 @@ class RootCauses extends BaseGatherer {
124
124
  rootCauses.layoutShifts[layoutShiftEvents.indexOf(event)] = r;
125
125
  }
126
126
 
127
- // Yeah this gatherer enabled it, and so you'd think it should disable it too...
128
- // ...but we don't give gatherers their own session so this stomps on others.
129
- // await driver.defaultSession.sendCommand('DOM.disable');
127
+ await driver.defaultSession.sendCommand('DOM.disable');
130
128
  await driver.defaultSession.sendCommand('CSS.disable');
131
129
 
132
130
  return rootCauses;
@@ -155,7 +155,7 @@ class TraceElements extends BaseGatherer {
155
155
  const {settings} = context;
156
156
  try {
157
157
  const responsivenessEvent = await Responsiveness.request({trace, settings}, context);
158
- if (!responsivenessEvent || responsivenessEvent.name === 'FallbackTiming') return;
158
+ if (!responsivenessEvent) return;
159
159
  return {nodeId: responsivenessEvent.args.data.nodeId};
160
160
  } catch {
161
161
  // Don't let responsiveness errors sink the rest of the gatherer.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "11.6.0-dev.20240312",
4
+ "version": "11.6.0-dev.20240314",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {