lighthouse 12.1.0-dev.20240805 → 12.1.0-dev.20240806

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.
@@ -101,10 +101,13 @@ class ThirdPartySummary extends Audit {
101
101
  const taskDuration = task.selfTime * cpuMultiplier;
102
102
  // The amount of time spent on main thread is the sum of all durations.
103
103
  urlSummary.mainThreadTime += taskDuration;
104
- // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms.
105
- // Note that this is not totally equivalent to the TBT definition since it fails to account for FCP,
106
- // but a majority of third-party work occurs after FCP and should yield largely similar numbers.
107
- urlSummary.blockingTime += Math.max(taskDuration - 50, 0);
104
+ // Blocking time is the amount of time spent on the main thread *over* 50ms.
105
+ // This value is interpolated because not all tasks attributed to this URL are at the top level.
106
+ //
107
+ // Note that this is not totally equivalent to the TBT definition since it fails to account for
108
+ // the FCP&TTI bounds of TBT.
109
+ urlSummary.blockingTime += task.selfBlockingTime;
110
+ // TBT impact is similar to blocking time, but it accounts for the FCP&TTI bounds of TBT.
108
111
  urlSummary.tbtImpact += task.selfTbtImpact;
109
112
  byURL.set(attributableURL, urlSummary);
110
113
  }
@@ -16,8 +16,8 @@ class LanternFirstContentfulPaint extends Lantern.Metrics.FirstContentfulPaint {
16
16
  * @return {Promise<LH.Artifacts.LanternMetric>}
17
17
  */
18
18
  static async computeMetricWithGraphs(data, context, extras) {
19
- return this.compute(await getComputationDataParams(data, context), extras)
20
- .catch(lanternErrorAdapter);
19
+ const params = await getComputationDataParams(data, context);
20
+ return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter);
21
21
  }
22
22
 
23
23
  /**
@@ -17,8 +17,8 @@ class LanternInteractive extends Lantern.Metrics.Interactive {
17
17
  * @return {Promise<LH.Artifacts.LanternMetric>}
18
18
  */
19
19
  static async computeMetricWithGraphs(data, context, extras) {
20
- return this.compute(await getComputationDataParams(data, context), extras)
21
- .catch(lanternErrorAdapter);
20
+ const params = await getComputationDataParams(data, context);
21
+ return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter);
22
22
  }
23
23
 
24
24
  /**
@@ -17,8 +17,8 @@ class LanternLargestContentfulPaint extends Lantern.Metrics.LargestContentfulPai
17
17
  * @return {Promise<LH.Artifacts.LanternMetric>}
18
18
  */
19
19
  static async computeMetricWithGraphs(data, context, extras) {
20
- return this.compute(await getComputationDataParams(data, context), extras)
21
- .catch(lanternErrorAdapter);
20
+ const params = await getComputationDataParams(data, context);
21
+ return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter);
22
22
  }
23
23
 
24
24
  /**
@@ -17,8 +17,8 @@ class LanternMaxPotentialFID extends Lantern.Metrics.MaxPotentialFID {
17
17
  * @return {Promise<LH.Artifacts.LanternMetric>}
18
18
  */
19
19
  static async computeMetricWithGraphs(data, context, extras) {
20
- return this.compute(await getComputationDataParams(data, context), extras)
21
- .catch(lanternErrorAdapter);
20
+ const params = await getComputationDataParams(data, context);
21
+ return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter);
22
22
  }
23
23
 
24
24
  /**
@@ -18,8 +18,8 @@ class LanternSpeedIndex extends Lantern.Metrics.SpeedIndex {
18
18
  * @return {Promise<LH.Artifacts.LanternMetric>}
19
19
  */
20
20
  static async computeMetricWithGraphs(data, context, extras) {
21
- return this.compute(await getComputationDataParams(data, context), extras)
22
- .catch(lanternErrorAdapter);
21
+ const params = await getComputationDataParams(data, context);
22
+ return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter);
23
23
  }
24
24
 
25
25
  /**
@@ -11,6 +11,6 @@ declare class NavigationInsights {
11
11
  * @param {LH.Trace} trace
12
12
  * @param {LH.Artifacts.ComputedContext} context
13
13
  */
14
- static compute_(trace: LH.Trace, context: LH.Artifacts.ComputedContext): Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").NavigationInsightData<typeof import("@paulirish/trace_engine/models/trace/handlers/ModelHandlers.js")>>;
14
+ static compute_(trace: LH.Trace, context: LH.Artifacts.ComputedContext): Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").NavigationInsightData>;
15
15
  }
16
16
  //# sourceMappingURL=navigation-insights.d.ts.map
@@ -20,8 +20,9 @@ declare class TBTImpactTasks {
20
20
  /**
21
21
  * @param {LH.Artifacts.TaskNode[]} tasks
22
22
  * @param {Map<LH.Artifacts.TaskNode, number>} taskToImpact
23
+ * @param {Map<LH.Artifacts.TaskNode, number>} taskToBlockingTime
23
24
  */
24
- static createImpactTasks(tasks: LH.Artifacts.TaskNode[], taskToImpact: Map<LH.Artifacts.TaskNode, number>): import("../index.js").Artifacts.TBTImpactTask[];
25
+ static createImpactTasks(tasks: LH.Artifacts.TaskNode[], taskToImpact: Map<LH.Artifacts.TaskNode, number>, taskToBlockingTime: Map<LH.Artifacts.TaskNode, number>): import("../index.js").Artifacts.TBTImpactTask[];
25
26
  /**
26
27
  * @param {LH.Artifacts.TaskNode[]} tasks
27
28
  * @param {number} startTimeMs
@@ -64,8 +64,9 @@ class TBTImpactTasks {
64
64
  /**
65
65
  * @param {LH.Artifacts.TaskNode[]} tasks
66
66
  * @param {Map<LH.Artifacts.TaskNode, number>} taskToImpact
67
+ * @param {Map<LH.Artifacts.TaskNode, number>} taskToBlockingTime
67
68
  */
68
- static createImpactTasks(tasks, taskToImpact) {
69
+ static createImpactTasks(tasks, taskToImpact, taskToBlockingTime) {
69
70
  /** @type {LH.Artifacts.TBTImpactTask[]} */
70
71
  const tbtImpactTasks = [];
71
72
 
@@ -73,15 +74,25 @@ class TBTImpactTasks {
73
74
  const tbtImpact = taskToImpact.get(task) || 0;
74
75
  let selfTbtImpact = tbtImpact;
75
76
 
77
+ const blockingTime = taskToBlockingTime.get(task) || 0;
78
+ let selfBlockingTime = blockingTime;
79
+
76
80
  for (const child of task.children) {
77
81
  const childTbtImpact = taskToImpact.get(child) || 0;
78
82
  selfTbtImpact -= childTbtImpact;
83
+
84
+ const childBlockingTime = taskToBlockingTime.get(child) || 0;
85
+ selfBlockingTime -= childBlockingTime;
79
86
  }
80
87
 
81
88
  tbtImpactTasks.push({
82
89
  ...task,
83
- tbtImpact,
84
- selfTbtImpact,
90
+ // Floating point numbers are not perfectly precise, so the subtraction operations above
91
+ // can sometimes output negative numbers close to 0 here. To prevent potentially confusing
92
+ // output we should bump those values to 0.
93
+ tbtImpact: Math.max(tbtImpact, 0),
94
+ selfTbtImpact: Math.max(selfTbtImpact, 0),
95
+ selfBlockingTime: Math.max(selfBlockingTime, 0),
85
96
  });
86
97
  }
87
98
 
@@ -98,6 +109,9 @@ class TBTImpactTasks {
98
109
  /** @type {Map<LH.Artifacts.TaskNode, number>} */
99
110
  const taskToImpact = new Map();
100
111
 
112
+ /** @type {Map<LH.Artifacts.TaskNode, number>} */
113
+ const taskToBlockingTime = new Map();
114
+
101
115
  for (const task of tasks) {
102
116
  const event = {
103
117
  start: task.startTime,
@@ -113,11 +127,13 @@ class TBTImpactTasks {
113
127
  };
114
128
 
115
129
  const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs, topLevelEvent);
130
+ const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity, topLevelEvent);
116
131
 
117
132
  taskToImpact.set(task, tbtImpact);
133
+ taskToBlockingTime.set(task, blockingTime);
118
134
  }
119
135
 
120
- return this.createImpactTasks(tasks, taskToImpact);
136
+ return this.createImpactTasks(tasks, taskToImpact, taskToBlockingTime);
121
137
  }
122
138
 
123
139
  /**
@@ -131,6 +147,9 @@ class TBTImpactTasks {
131
147
  /** @type {Map<LH.Artifacts.TaskNode, number>} */
132
148
  const taskToImpact = new Map();
133
149
 
150
+ /** @type {Map<LH.Artifacts.TaskNode, number>} */
151
+ const taskToBlockingTime = new Map();
152
+
134
153
  /** @type {Map<LH.Artifacts.TaskNode, {start: number, end: number, duration: number}>} */
135
154
  const topLevelTaskToEvent = new Map();
136
155
 
@@ -151,19 +170,21 @@ class TBTImpactTasks {
151
170
  };
152
171
 
153
172
  const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs);
173
+ const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity);
154
174
 
155
175
  const task = traceEventToTask.get(node.event);
156
176
  if (!task) continue;
157
177
 
158
178
  topLevelTaskToEvent.set(task, event);
159
179
  taskToImpact.set(task, tbtImpact);
180
+ taskToBlockingTime.set(task, blockingTime);
160
181
  }
161
182
 
162
183
  // Interpolate the TBT impact of remaining tasks using the top level ancestor tasks.
163
184
  // We don't have any lantern estimates for tasks that are not top level, so we need to estimate
164
185
  // the lantern timing based on the task's observed timing relative to it's top level task's observed timing.
165
186
  for (const task of tasks) {
166
- if (taskToImpact.has(task)) continue;
187
+ if (taskToImpact.has(task) || taskToBlockingTime.has(task)) continue;
167
188
 
168
189
  const topLevelTask = this.getTopLevelTask(task);
169
190
 
@@ -183,11 +204,13 @@ class TBTImpactTasks {
183
204
  };
184
205
 
185
206
  const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs, topLevelEvent);
207
+ const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity, topLevelEvent);
186
208
 
187
209
  taskToImpact.set(task, tbtImpact);
210
+ taskToBlockingTime.set(task, blockingTime);
188
211
  }
189
212
 
190
- return this.createImpactTasks(tasks, taskToImpact);
213
+ return this.createImpactTasks(tasks, taskToImpact, taskToBlockingTime);
191
214
  }
192
215
 
193
216
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "12.1.0-dev.20240805",
4
+ "version": "12.1.0-dev.20240806",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -167,7 +167,7 @@
167
167
  "pako": "^2.0.3",
168
168
  "preact": "^10.7.2",
169
169
  "pretty-json-stringify": "^0.0.2",
170
- "puppeteer": "^22.13.1",
170
+ "puppeteer": "^22.15.0",
171
171
  "resolve": "^1.22.1",
172
172
  "rollup": "^2.52.7",
173
173
  "rollup-plugin-polyfill-node": "^0.12.0",
@@ -181,7 +181,7 @@
181
181
  "webtreemap-cdt": "^3.2.1"
182
182
  },
183
183
  "dependencies": {
184
- "@paulirish/trace_engine": "0.0.28",
184
+ "@paulirish/trace_engine": "0.0.32",
185
185
  "@sentry/node": "^6.17.4",
186
186
  "axe-core": "^4.9.1",
187
187
  "chrome-launcher": "^1.1.2",
@@ -200,11 +200,11 @@
200
200
  "metaviewport-parser": "0.3.0",
201
201
  "open": "^8.4.0",
202
202
  "parse-cache-control": "1.0.1",
203
- "puppeteer-core": "^22.13.1",
203
+ "puppeteer-core": "^22.15.0",
204
204
  "robots-parser": "^3.0.1",
205
205
  "semver": "^5.3.0",
206
206
  "speedline-core": "^1.4.3",
207
- "third-party-web": "^0.24.3",
207
+ "third-party-web": "^0.24.5",
208
208
  "tldts-icann": "^6.1.16",
209
209
  "ws": "^7.0.0",
210
210
  "yargs": "^17.3.1",
@@ -163,7 +163,7 @@ declare module Artifacts {
163
163
 
164
164
  type NetworkRequest = _NetworkRequest;
165
165
  type TaskNode = _TaskNode;
166
- type TBTImpactTask = TaskNode & {tbtImpact: number, selfTbtImpact: number};
166
+ type TBTImpactTask = TaskNode & {tbtImpact: number, selfTbtImpact: number, selfBlockingTime: number};
167
167
  type MetaElement = Artifacts['MetaElements'][0];
168
168
 
169
169
  interface URL {
@@ -511,7 +511,7 @@ declare module Artifacts {
511
511
 
512
512
  interface TraceEngineResult {
513
513
  data: TraceEngine.Handlers.Types.TraceParseData;
514
- insights: TraceEngine.Insights.Types.TraceInsightData<typeof TraceEngine.Handlers.ModelHandlers>;
514
+ insights: TraceEngine.Insights.Types.TraceInsightData;
515
515
  }
516
516
 
517
517
  interface TraceEngineRootCauses {