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.
@@ -69,13 +69,16 @@ class LayoutShifts extends Audit {
69
69
 
70
70
  /** @type {Item[]} */
71
71
  const items = [];
72
- const layoutShiftEvents = clusters.flatMap(c => c.events);
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
- await processor.parse(events);
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
- await engine.parse(traceEvents);
30
- return engine.data;
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
- return TraceEngineResult.runTraceEngine(traceEvents);
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 {number[]} backendNodeIds */
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
- return response.nodeIds;
46
+ const nodeIds =
47
+ /** @type {import('@paulirish/trace_engine/generated/protocol.js').DOM.NodeId[]} */(
48
+ response.nodeIds);
49
+ return nodeIds;
46
50
  },
47
- /** @param {number} nodeId */
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
- return response.node;
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
- return null;
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 {number} nodeId */
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 = clusters.flatMap(c => c.events);
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(event.args.data.impacted_nodes, impactByNodeId);
132
+ this.getBiggestImpactNodeForShiftEvent(impactedNodes, impactByNodeId);
129
133
  if (biggestImpactedNodeId !== undefined) {
130
134
  nodeIds.push(biggestImpactedNodeId);
131
135
  }
@@ -1,7 +1,11 @@
1
- /** @type {import('../../types/trace-engine.js').TraceProcessor & typeof import('../../types/trace-engine.js').TraceProcessor} */
2
- export const TraceProcessor: import('../../types/trace-engine.js').TraceProcessor & typeof import('../../types/trace-engine.js').TraceProcessor;
3
- /** @type {import('../../types/trace-engine.js').TraceHandlers} */
4
- export const TraceHandlers: any;
5
- /** @type {import('../../types/trace-engine.js').RootCauses & typeof import('../../types/trace-engine.js').RootCauses} */
6
- export const RootCauses: import('../../types/trace-engine.js').RootCauses & typeof import('../../types/trace-engine.js').RootCauses;
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
@@ -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.20240213",
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.7",
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.1211954",
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.1211954",
215
- "puppeteer-core/**/devtools-protocol": "0.0.1211954"
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": [
@@ -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 = TraceProcessor['data'];
573
+ type TraceEngineResult = TraceEngine.Handlers.Types.TraceParseData;
573
574
 
574
575
  interface TraceEngineRootCauses {
575
- layoutShifts: Record<number, LayoutShiftRootCauses>;
576
+ layoutShifts: Record<number, LayoutShiftRootCausesData>;
576
577
  }
577
578
 
578
579
  interface ViewportDimensions {