lighthouse 11.5.0-dev.20240213 → 11.5.0-dev.20240215
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/layout-shifts.js +5 -2
- package/core/computed/metrics/cumulative-layout-shift.js +7 -1
- package/core/computed/trace-engine-result.d.ts +2 -16
- package/core/computed/trace-engine-result.js +12 -3
- package/core/gather/gatherers/root-causes.js +22 -9
- package/core/gather/gatherers/trace-elements.js +6 -2
- package/core/lib/trace-engine.d.ts +10 -6
- package/core/lib/trace-engine.js +3 -4
- package/package.json +5 -5
- package/types/artifacts.d.ts +4 -3
- package/types/trace-engine.d.ts +0 -1516
|
@@ -69,13 +69,16 @@ class LayoutShifts extends Audit {
|
|
|
69
69
|
|
|
70
70
|
/** @type {Item[]} */
|
|
71
71
|
const items = [];
|
|
72
|
-
const layoutShiftEvents =
|
|
72
|
+
const layoutShiftEvents =
|
|
73
|
+
/** @type {import('../lib/trace-engine.js').SaneSyntheticLayoutShift[]} */(
|
|
74
|
+
clusters.flatMap(c => c.events)
|
|
75
|
+
);
|
|
73
76
|
const topLayoutShiftEvents = layoutShiftEvents
|
|
74
77
|
.sort((a, b) => b.args.data.weighted_score_delta - a.args.data.weighted_score_delta)
|
|
75
78
|
.slice(0, MAX_LAYOUT_SHIFTS);
|
|
76
79
|
for (const event of topLayoutShiftEvents) {
|
|
77
80
|
const biggestImpactNodeId = TraceElements.getBiggestImpactNodeForShiftEvent(
|
|
78
|
-
event.args.data.impacted_nodes, impactByNodeId);
|
|
81
|
+
event.args.data.impacted_nodes || [], impactByNodeId);
|
|
79
82
|
const biggestImpactElement = traceElements.find(t => t.nodeId === biggestImpactNodeId);
|
|
80
83
|
|
|
81
84
|
// Turn root causes into sub-items.
|
|
@@ -159,7 +159,13 @@ class CumulativeLayoutShift {
|
|
|
159
159
|
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
|
|
160
160
|
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
161
161
|
});
|
|
162
|
-
|
|
162
|
+
// eslint-disable-next-line max-len
|
|
163
|
+
await processor.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ (
|
|
164
|
+
events
|
|
165
|
+
));
|
|
166
|
+
if (!processor.data) {
|
|
167
|
+
throw new Error('null trace engine result');
|
|
168
|
+
}
|
|
163
169
|
return processor.data.LayoutShifts.sessionMaxScore;
|
|
164
170
|
};
|
|
165
171
|
const cumulativeLayoutShift = await run(allFrameShiftEvents.map(e => e.event));
|
|
@@ -4,14 +4,7 @@ declare const TraceEngineResultComputed: typeof TraceEngineResult & {
|
|
|
4
4
|
trace: LH.Trace;
|
|
5
5
|
}, context: import("../../types/utility-types.js").default.ImmutableObject<{
|
|
6
6
|
computedCache: Map<string, import("../lib/arbitrary-equality-map.js").ArbitraryEqualityMap>;
|
|
7
|
-
}>) => Promise<
|
|
8
|
-
LayoutShifts: {
|
|
9
|
-
clusters: {
|
|
10
|
-
events: import("../../types/trace-engine.js").LayoutShiftTraceEvent[];
|
|
11
|
-
}[];
|
|
12
|
-
sessionMaxScore: number;
|
|
13
|
-
};
|
|
14
|
-
}>;
|
|
7
|
+
}>) => Promise<Readonly<import("@paulirish/trace_engine/models/trace/handlers/types.js").EnabledHandlerDataWithMeta<typeof import("@paulirish/trace_engine/models/trace/handlers/ModelHandlers.js")>>>;
|
|
15
8
|
};
|
|
16
9
|
/**
|
|
17
10
|
* @fileoverview Processes trace with the shared trace engine.
|
|
@@ -20,14 +13,7 @@ declare class TraceEngineResult {
|
|
|
20
13
|
/**
|
|
21
14
|
* @param {LH.TraceEvent[]} traceEvents
|
|
22
15
|
*/
|
|
23
|
-
static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<
|
|
24
|
-
LayoutShifts: {
|
|
25
|
-
clusters: {
|
|
26
|
-
events: import("../../types/trace-engine.js").LayoutShiftTraceEvent[];
|
|
27
|
-
}[];
|
|
28
|
-
sessionMaxScore: number;
|
|
29
|
-
};
|
|
30
|
-
}>;
|
|
16
|
+
static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<Readonly<import("@paulirish/trace_engine/models/trace/handlers/types.js").EnabledHandlerDataWithMeta<typeof import("@paulirish/trace_engine/models/trace/handlers/ModelHandlers.js")>>>;
|
|
31
17
|
/**
|
|
32
18
|
* @param {{trace: LH.Trace}} data
|
|
33
19
|
* @param {LH.Artifacts.ComputedContext} context
|
|
@@ -26,8 +26,13 @@ class TraceEngineResult {
|
|
|
26
26
|
Samples: TraceEngine.TraceHandlers.Samples,
|
|
27
27
|
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
28
28
|
});
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
// eslint-disable-next-line max-len
|
|
30
|
+
await engine.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ (
|
|
31
|
+
traceEvents
|
|
32
|
+
));
|
|
33
|
+
// TODO: use TraceEngine.TraceProcessor.createWithAllHandlers above.
|
|
34
|
+
return /** @type {import('@paulirish/trace_engine').Handlers.Types.TraceParseData} */(
|
|
35
|
+
engine.data);
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
/**
|
|
@@ -61,7 +66,11 @@ class TraceEngineResult {
|
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
const result = await TraceEngineResult.runTraceEngine(traceEvents);
|
|
70
|
+
if (!result) {
|
|
71
|
+
throw new Error('null trace engine result');
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
65
74
|
}
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -32,26 +32,33 @@ class RootCauses extends BaseGatherer {
|
|
|
32
32
|
// nodeIds if the DOM domain was enabled before this gatherer, invoke it to be safe.
|
|
33
33
|
await driver.defaultSession.sendCommand('DOM.getDocument', {depth: -1, pierce: true});
|
|
34
34
|
|
|
35
|
+
/** @type {import('@paulirish/trace_engine').RootCauses.RootCauses.RootCauseProtocolInterface} */
|
|
35
36
|
const protocolInterface = {
|
|
36
37
|
/** @param {string} url */
|
|
37
38
|
// eslint-disable-next-line no-unused-vars
|
|
38
39
|
getInitiatorForRequest(url) {
|
|
39
40
|
return null;
|
|
40
41
|
},
|
|
41
|
-
/** @param {
|
|
42
|
+
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.BackendNodeId[]} backendNodeIds */
|
|
42
43
|
async pushNodesByBackendIdsToFrontend(backendNodeIds) {
|
|
43
44
|
const response = await driver.defaultSession.sendCommand(
|
|
44
45
|
'DOM.pushNodesByBackendIdsToFrontend', {backendNodeIds});
|
|
45
|
-
|
|
46
|
+
const nodeIds =
|
|
47
|
+
/** @type {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId[]} */(
|
|
48
|
+
response.nodeIds);
|
|
49
|
+
return nodeIds;
|
|
46
50
|
},
|
|
47
|
-
/** @param {
|
|
51
|
+
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId} nodeId */
|
|
48
52
|
async getNode(nodeId) {
|
|
49
53
|
try {
|
|
50
54
|
const response = await driver.defaultSession.sendCommand('DOM.describeNode', {nodeId});
|
|
51
55
|
// This always zero, so let's fix it here.
|
|
52
56
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1515175
|
|
53
57
|
response.node.nodeId = nodeId;
|
|
54
|
-
|
|
58
|
+
const node =
|
|
59
|
+
/** @type {import('@paulirish/trace_engine/generated/protocol.js').DOM.Node} */(
|
|
60
|
+
response.node);
|
|
61
|
+
return node;
|
|
55
62
|
} catch (err) {
|
|
56
63
|
if (err.message.includes('Could not find node with given id')) {
|
|
57
64
|
// TODO: when injecting an iframe, the engine gets the node of that frame's document element.
|
|
@@ -64,7 +71,8 @@ class RootCauses extends BaseGatherer {
|
|
|
64
71
|
// When this is fixed, remove this try/catch.
|
|
65
72
|
// Note: this could be buggy by giving the wrong node detail if a node id meant for a non-main frame
|
|
66
73
|
// happens to match one from the main frame ... which is pretty likely...
|
|
67
|
-
|
|
74
|
+
// TODO: fix trace engine type to allow returning null.
|
|
75
|
+
return /** @type {any} */(null);
|
|
68
76
|
}
|
|
69
77
|
throw err;
|
|
70
78
|
}
|
|
@@ -79,17 +87,20 @@ class RootCauses extends BaseGatherer {
|
|
|
79
87
|
return [];
|
|
80
88
|
}
|
|
81
89
|
},
|
|
82
|
-
/** @param {
|
|
90
|
+
/** @param {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId} nodeId */
|
|
83
91
|
async getMatchedStylesForNode(nodeId) {
|
|
84
92
|
try {
|
|
85
93
|
const response = await driver.defaultSession.sendCommand(
|
|
86
94
|
'CSS.getMatchedStylesForNode', {nodeId});
|
|
87
|
-
return response;
|
|
88
|
-
} catch {
|
|
89
|
-
return
|
|
95
|
+
return {...response, getError() {}};
|
|
96
|
+
} catch (err) {
|
|
97
|
+
return /** @type {any} */({getError() {
|
|
98
|
+
return err.toString();
|
|
99
|
+
}});
|
|
90
100
|
}
|
|
91
101
|
},
|
|
92
102
|
/** @param {string} url */
|
|
103
|
+
// @ts-expect-error not using, dont care about type error.
|
|
93
104
|
// eslint-disable-next-line no-unused-vars
|
|
94
105
|
async fontFaceForSource(url) {
|
|
95
106
|
return null;
|
|
@@ -104,6 +115,8 @@ class RootCauses extends BaseGatherer {
|
|
|
104
115
|
const layoutShiftEvents = traceEngineResult.LayoutShifts.clusters.flatMap(c => c.events);
|
|
105
116
|
for (const event of layoutShiftEvents) {
|
|
106
117
|
const r = await rootCausesEngine.layoutShifts.rootCausesForEvent(traceEngineResult, event);
|
|
118
|
+
if (!r) continue;
|
|
119
|
+
|
|
107
120
|
for (const cause of r.fontChanges) {
|
|
108
121
|
// TODO: why isn't trace engine unwrapping this promise ...
|
|
109
122
|
cause.fontFace = await cause.fontFace;
|
|
@@ -117,15 +117,19 @@ class TraceElements extends BaseGatherer {
|
|
|
117
117
|
static async getTopLayoutShifts(trace, traceEngineResult, rootCauses, context) {
|
|
118
118
|
const {impactByNodeId} = await CumulativeLayoutShift.request(trace, context);
|
|
119
119
|
const clusters = traceEngineResult.LayoutShifts.clusters ?? [];
|
|
120
|
-
const layoutShiftEvents =
|
|
120
|
+
const layoutShiftEvents =
|
|
121
|
+
/** @type {import('../../lib/trace-engine.js').SaneSyntheticLayoutShift[]} */(
|
|
122
|
+
clusters.flatMap(c => c.events)
|
|
123
|
+
);
|
|
121
124
|
|
|
122
125
|
return layoutShiftEvents
|
|
123
126
|
.sort((a, b) => b.args.data.weighted_score_delta - a.args.data.weighted_score_delta)
|
|
124
127
|
.slice(0, MAX_LAYOUT_SHIFTS)
|
|
125
128
|
.flatMap(event => {
|
|
126
129
|
const nodeIds = [];
|
|
130
|
+
const impactedNodes = event.args.data.impacted_nodes || [];
|
|
127
131
|
const biggestImpactedNodeId =
|
|
128
|
-
this.getBiggestImpactNodeForShiftEvent(
|
|
132
|
+
this.getBiggestImpactNodeForShiftEvent(impactedNodes, impactByNodeId);
|
|
129
133
|
if (biggestImpactedNodeId !== undefined) {
|
|
130
134
|
nodeIds.push(biggestImpactedNodeId);
|
|
131
135
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
export type SyntheticLayoutShift = import('@paulirish/trace_engine').Types.TraceEvents.SyntheticLayoutShift;
|
|
2
|
+
export type SaneSyntheticLayoutShift = SyntheticLayoutShift & {
|
|
3
|
+
args: {
|
|
4
|
+
data: NonNullable<SyntheticLayoutShift['args']['data']>;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export const TraceProcessor: typeof TraceEngine.Processor.TraceProcessor;
|
|
8
|
+
export const TraceHandlers: typeof TraceEngine.Handlers.ModelHandlers;
|
|
9
|
+
export const RootCauses: typeof TraceEngine.RootCauses.RootCauses.RootCauses;
|
|
10
|
+
import * as TraceEngine from '@paulirish/trace_engine';
|
|
7
11
|
//# sourceMappingURL=trace-engine.d.ts.map
|
package/core/lib/trace-engine.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
// @ts-expect-error missing types
|
|
2
1
|
import * as TraceEngine from '@paulirish/trace_engine';
|
|
3
2
|
|
|
4
3
|
import {polyfillDOMRect} from './polyfill-dom-rect.js';
|
|
5
4
|
|
|
5
|
+
/** @typedef {import('@paulirish/trace_engine').Types.TraceEvents.SyntheticLayoutShift} SyntheticLayoutShift */
|
|
6
|
+
/** @typedef {SyntheticLayoutShift & {args: {data: NonNullable<SyntheticLayoutShift['args']['data']>}}} SaneSyntheticLayoutShift */
|
|
7
|
+
|
|
6
8
|
polyfillDOMRect();
|
|
7
9
|
|
|
8
|
-
/** @type {import('../../types/trace-engine.js').TraceProcessor & typeof import('../../types/trace-engine.js').TraceProcessor} */
|
|
9
10
|
const TraceProcessor = TraceEngine.Processor.TraceProcessor;
|
|
10
|
-
/** @type {import('../../types/trace-engine.js').TraceHandlers} */
|
|
11
11
|
const TraceHandlers = TraceEngine.Handlers.ModelHandlers;
|
|
12
|
-
/** @type {import('../../types/trace-engine.js').RootCauses & typeof import('../../types/trace-engine.js').RootCauses} */
|
|
13
12
|
const RootCauses = TraceEngine.RootCauses.RootCauses.RootCauses;
|
|
14
13
|
|
|
15
14
|
export {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "11.5.0-dev.
|
|
4
|
+
"version": "11.5.0-dev.20240215",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -180,13 +180,13 @@
|
|
|
180
180
|
"webtreemap-cdt": "^3.2.1"
|
|
181
181
|
},
|
|
182
182
|
"dependencies": {
|
|
183
|
-
"@paulirish/trace_engine": "^0.0.
|
|
183
|
+
"@paulirish/trace_engine": "^0.0.12",
|
|
184
184
|
"@sentry/node": "^6.17.4",
|
|
185
185
|
"axe-core": "^4.8.4",
|
|
186
186
|
"chrome-launcher": "^1.1.0",
|
|
187
187
|
"configstore": "^5.0.1",
|
|
188
188
|
"csp_evaluator": "1.1.1",
|
|
189
|
-
"devtools-protocol": "0.0.
|
|
189
|
+
"devtools-protocol": "0.0.1232444",
|
|
190
190
|
"enquirer": "^2.3.6",
|
|
191
191
|
"http-link-header": "^1.1.1",
|
|
192
192
|
"intl-messageformat": "^10.5.3",
|
|
@@ -211,8 +211,8 @@
|
|
|
211
211
|
"yargs-parser": "^21.0.0"
|
|
212
212
|
},
|
|
213
213
|
"resolutions": {
|
|
214
|
-
"puppeteer/**/devtools-protocol": "0.0.
|
|
215
|
-
"puppeteer-core/**/devtools-protocol": "0.0.
|
|
214
|
+
"puppeteer/**/devtools-protocol": "0.0.1232444",
|
|
215
|
+
"puppeteer-core/**/devtools-protocol": "0.0.1232444"
|
|
216
216
|
},
|
|
217
217
|
"repository": "GoogleChrome/lighthouse",
|
|
218
218
|
"keywords": [
|
package/types/artifacts.d.ts
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Protocol as Crdp} from 'devtools-protocol/types/protocol.js';
|
|
8
|
+
import * as TraceEngine from '@paulirish/trace_engine';
|
|
9
|
+
import {LayoutShiftRootCausesData} from '@paulirish/trace_engine/models/trace/root-causes/LayoutShift.js';
|
|
8
10
|
|
|
9
11
|
import {parseManifest} from '../core/lib/manifest-parser.js';
|
|
10
12
|
import {Simulator} from '../core/lib/dependency-graph/simulator/simulator.js';
|
|
@@ -23,7 +25,6 @@ import LHResult from './lhr/lhr.js'
|
|
|
23
25
|
import Protocol from './protocol.js';
|
|
24
26
|
import Util from './utility-types.js';
|
|
25
27
|
import Audit from './audit.js';
|
|
26
|
-
import {TraceProcessor, LayoutShiftRootCauses} from './trace-engine.js';
|
|
27
28
|
|
|
28
29
|
export type Artifacts = BaseArtifacts & GathererArtifacts;
|
|
29
30
|
|
|
@@ -569,10 +570,10 @@ declare module Artifacts {
|
|
|
569
570
|
type?: string;
|
|
570
571
|
}
|
|
571
572
|
|
|
572
|
-
type TraceEngineResult =
|
|
573
|
+
type TraceEngineResult = TraceEngine.Handlers.Types.TraceParseData;
|
|
573
574
|
|
|
574
575
|
interface TraceEngineRootCauses {
|
|
575
|
-
layoutShifts: Record<number,
|
|
576
|
+
layoutShifts: Record<number, LayoutShiftRootCausesData>;
|
|
576
577
|
}
|
|
577
578
|
|
|
578
579
|
interface ViewportDimensions {
|