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.
- package/core/audits/metrics/interaction-to-next-paint.js +1 -3
- package/core/audits/work-during-interaction.js +0 -8
- package/core/computed/metrics/responsiveness.d.ts +5 -13
- package/core/computed/metrics/responsiveness.js +10 -14
- package/core/gather/gatherers/css-usage.d.ts +1 -9
- package/core/gather/gatherers/css-usage.js +23 -25
- package/core/gather/gatherers/root-causes.js +1 -3
- package/core/gather/gatherers/trace-elements.js +1 -1
- package/package.json +1 -1
|
@@ -70,9 +70,7 @@ class InteractionToNextPaint extends Audit {
|
|
|
70
70
|
return {score: null, notApplicable: true};
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
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 |
|
|
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
|
|
65
|
+
* @return {EventTimingEvent}
|
|
74
66
|
*/
|
|
75
|
-
static findInteractionEvent(responsivenessEvent: ResponsivenessEvent, { traceEvents }: LH.Trace): EventTimingEvent
|
|
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|
|
|
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 |
|
|
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
|
|
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
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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|
|
|
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):
|
|
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
|
-
|
|
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
|
|
69
|
+
async startInstrumentation(context) {
|
|
70
70
|
const session = context.driver.defaultSession;
|
|
71
71
|
this._session = session;
|
|
72
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
115
|
-
await this.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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