lighthouse 12.4.0-dev.20250312 → 12.4.0-dev.20250313

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.
@@ -2,13 +2,12 @@ export default LegacyJavascript;
2
2
  export type Pattern = {
3
3
  name: string;
4
4
  expression: string;
5
- estimateBytes?: (result: PatternMatchResult) => number;
5
+ estimateBytes?: (content: string) => number;
6
6
  };
7
7
  export type PatternMatchResult = {
8
8
  name: string;
9
9
  line: number;
10
10
  column: number;
11
- count: number;
12
11
  };
13
12
  export type ByteEfficiencyProduct = import("./byte-efficiency-audit.js").ByteEfficiencyProduct;
14
13
  export type Item = LH.Audit.ByteEfficiencyItem & {
@@ -50,10 +49,11 @@ declare class LegacyJavascript extends ByteEfficiencyAudit {
50
49
  */
51
50
  static detectAcrossScripts(matcher: CodePatternMatcher, scripts: LH.Artifacts["Scripts"], bundles: LH.Artifacts.Bundle[]): Map<LH.Artifacts.Script, PatternMatchResult[]>;
52
51
  /**
52
+ * @param {LH.Artifacts.Script} script
53
53
  * @param {PatternMatchResult[]} matches
54
54
  * @return {number}
55
55
  */
56
- static estimateWastedBytes(matches: PatternMatchResult[]): number;
56
+ static estimateWastedBytes(script: LH.Artifacts.Script, matches: PatternMatchResult[]): number;
57
57
  /**
58
58
  * @param {LH.Artifacts} artifacts
59
59
  * @param {Array<LH.Artifacts.NetworkRequest>} networkRecords
@@ -70,7 +70,8 @@ export namespace UIStrings {
70
70
  import { ByteEfficiencyAudit } from './byte-efficiency-audit.js';
71
71
  /**
72
72
  * Takes a list of patterns (consisting of a name identifier and a RegExp expression string)
73
- * and returns match results with line / column information for a given code input.
73
+ * and via `match` returns match results with line / column information for a given code input.
74
+ * Only returns the first match per pattern given.
74
75
  */
75
76
  declare class CodePatternMatcher {
76
77
  /**
@@ -11,8 +11,8 @@
11
11
  * ./core/scripts/legacy-javascript - verification tool.
12
12
  */
13
13
 
14
- /** @typedef {{name: string, expression: string, estimateBytes?: (result: PatternMatchResult) => number}} Pattern */
15
- /** @typedef {{name: string, line: number, column: number, count: number}} PatternMatchResult */
14
+ /** @typedef {{name: string, expression: string, estimateBytes?: (content: string) => number}} Pattern */
15
+ /** @typedef {{name: string, line: number, column: number}} PatternMatchResult */
16
16
  /** @typedef {import('./byte-efficiency-audit.js').ByteEfficiencyProduct} ByteEfficiencyProduct */
17
17
  /** @typedef {LH.Audit.ByteEfficiencyItem & {subItems: {type: 'subitems', items: SubItem[]}}} Item */
18
18
  /** @typedef {{signal: string, location: LH.Audit.Details.SourceLocationValue}} SubItem */
@@ -55,7 +55,8 @@ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
55
55
 
56
56
  /**
57
57
  * Takes a list of patterns (consisting of a name identifier and a RegExp expression string)
58
- * and returns match results with line / column information for a given code input.
58
+ * and via `match` returns match results with line / column information for a given code input.
59
+ * Only returns the first match per pattern given.
59
60
  */
60
61
  class CodePatternMatcher {
61
62
  /**
@@ -99,8 +100,6 @@ class CodePatternMatcher {
99
100
  const pattern = this.patterns[patternExpressionMatches.findIndex(Boolean)];
100
101
 
101
102
  if (seen.has(pattern)) {
102
- const existingMatch = matches.find(m => m.name === pattern.name);
103
- if (existingMatch) existingMatch.count += 1;
104
103
  continue;
105
104
  }
106
105
  seen.add(pattern);
@@ -109,7 +108,6 @@ class CodePatternMatcher {
109
108
  name: pattern.name,
110
109
  line,
111
110
  column: result.index - lineBeginsAtIndex,
112
- count: 1,
113
111
  });
114
112
  }
115
113
 
@@ -229,23 +227,74 @@ class LegacyJavascript extends ByteEfficiencyAudit {
229
227
  * @return {Pattern[]}
230
228
  */
231
229
  static getTransformPatterns() {
230
+ /**
231
+ * @param {string} content
232
+ * @param {RegExp|string} pattern
233
+ * @return {number}
234
+ */
235
+ const count = (content, pattern) => {
236
+ // Split is slightly faster than match.
237
+ if (typeof pattern === 'string') {
238
+ return content.split(pattern).length - 1;
239
+ }
240
+
241
+ return (content.match(pattern) ?? []).length;
242
+ };
243
+
244
+ // For expression: prefer a string that is found in the transform runtime support code (those won't ever be minified).
245
+
232
246
  return [
247
+ // @babel/plugin-transform-classes
248
+ //
249
+ // input:
250
+ //
251
+ // class MyTestClass {
252
+ // log() {
253
+ // console.log(1);
254
+ // }
255
+ // };
256
+ //
257
+ // output:
258
+ //
259
+ // function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
260
+ // function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
261
+ // function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
262
+ // function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
263
+ // function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
264
+ // let MyTestClass = function () {
265
+ // function MyTestClass() {
266
+ // _classCallCheck(this, MyTestClass);
267
+ // }
268
+ // return _createClass(MyTestClass, [{
269
+ // key: "log",
270
+ // value: function log() {
271
+ // console.log(1);
272
+ // }
273
+ // }]);
274
+ // }();
233
275
  {
234
276
  name: '@babel/plugin-transform-classes',
235
277
  expression: 'Cannot call a class as a function',
236
- estimateBytes: result => 150 + result.count * '_classCallCheck()'.length,
278
+ estimateBytes: content => {
279
+ return 1000 + (count(content, '_classCallCheck') - 1) * '_classCallCheck()'.length;
280
+ },
237
281
  },
238
282
  {
239
283
  name: '@babel/plugin-transform-regenerator',
240
- expression: /regeneratorRuntime\(?\)?\.a?wrap/.source,
284
+ expression: 'Generator is already running|regeneratorRuntime',
241
285
  // Example of this transform: https://gist.github.com/connorjclark/af8bccfff377ac44efc104a79bc75da2
242
286
  // `regeneratorRuntime.awrap` is generated for every usage of `await`, and adds ~80 bytes each.
243
- estimateBytes: result => result.count * 80,
287
+ estimateBytes: content => {
288
+ return count(content, /regeneratorRuntime\(?\)?\.a?wrap/g) * 80;
289
+ },
244
290
  },
245
291
  {
246
292
  name: '@babel/plugin-transform-spread',
247
- expression: /\.apply\(void 0,\s?_toConsumableArray/.source,
248
- estimateBytes: result => 1169 + result.count * '_toConsumableArray()'.length,
293
+ expression: 'Invalid attempt to spread non-iterable instance',
294
+ estimateBytes: content => {
295
+ const per = '_toConsumableArray()'.length;
296
+ return 1169 + count(content, /\.apply\(void 0,\s?_toConsumableArray/g) * per;
297
+ },
249
298
  },
250
299
  ];
251
300
  }
@@ -283,9 +332,9 @@ class LegacyJavascript extends ByteEfficiencyAudit {
283
332
 
284
333
  const mapping = bundle.map.mappings().find(m => m.sourceURL === source);
285
334
  if (mapping) {
286
- matches.push({name, line: mapping.lineNumber, column: mapping.columnNumber, count: 1});
335
+ matches.push({name, line: mapping.lineNumber, column: mapping.columnNumber});
287
336
  } else {
288
- matches.push({name, line: 0, column: 0, count: 1});
337
+ matches.push({name, line: 0, column: 0});
289
338
  }
290
339
  }
291
340
  }
@@ -298,10 +347,11 @@ class LegacyJavascript extends ByteEfficiencyAudit {
298
347
  }
299
348
 
300
349
  /**
350
+ * @param {LH.Artifacts.Script} script
301
351
  * @param {PatternMatchResult[]} matches
302
352
  * @return {number}
303
353
  */
304
- static estimateWastedBytes(matches) {
354
+ static estimateWastedBytes(script, matches) {
305
355
  // Split up results based on polyfill / transform. Only transforms start with @.
306
356
  const polyfillResults = matches.filter(m => !m.name.startsWith('@'));
307
357
  const transformResults = matches.filter(m => m.name.startsWith('@'));
@@ -325,8 +375,8 @@ class LegacyJavascript extends ByteEfficiencyAudit {
325
375
 
326
376
  for (const result of transformResults) {
327
377
  const pattern = this.getTransformPatterns().find(p => p.name === result.name);
328
- if (!pattern || !pattern.estimateBytes) continue;
329
- estimatedWastedBytesFromTransforms += pattern.estimateBytes(result);
378
+ if (!pattern || !pattern.estimateBytes || !script.content) continue;
379
+ estimatedWastedBytesFromTransforms += pattern.estimateBytes(script.content);
330
380
  }
331
381
 
332
382
  const estimatedWastedBytes =
@@ -363,7 +413,7 @@ class LegacyJavascript extends ByteEfficiencyAudit {
363
413
  for (const [script, matches] of scriptToMatchResults.entries()) {
364
414
  const compressionRatio = estimateCompressionRatioForContent(
365
415
  compressionRatioByUrl, script.url, artifacts, networkRecords);
366
- const wastedBytes = Math.round(this.estimateWastedBytes(matches) * compressionRatio);
416
+ const wastedBytes = Math.round(this.estimateWastedBytes(script, matches) * compressionRatio);
367
417
  /** @type {typeof items[number]} */
368
418
  const item = {
369
419
  url: script.url,
@@ -122,13 +122,14 @@ class RenderBlockingResources extends Audit {
122
122
  * @return {Promise<{fcpWastedMs: number, lcpWastedMs: number, results: Array<{url: string, totalBytes: number, wastedMs: number}>}>}
123
123
  */
124
124
  static async computeResults(artifacts, context) {
125
+ const settings = context.settings;
125
126
  const gatherContext = artifacts.GatherContext;
126
127
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
127
128
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
128
129
  const simulatorData = {devtoolsLog, settings: context.settings};
129
130
  const simulator = await LoadSimulator.request(simulatorData, context);
130
131
  const wastedCssBytes = await RenderBlockingResources.computeWastedCSSBytes(artifacts, context);
131
- const navInsights = await NavigationInsights.request(trace, context);
132
+ const navInsights = await NavigationInsights.request({trace, settings}, context);
132
133
 
133
134
  const renderBlocking = navInsights.model.RenderBlocking;
134
135
  if (renderBlocking instanceof Error) throw renderBlocking;
@@ -168,10 +168,11 @@ class CriticalRequestChains extends Audit {
168
168
  * @return {Promise<LH.Audit.Product>}
169
169
  */
170
170
  static async audit(artifacts, context) {
171
+ const settings = context.settings;
171
172
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
172
173
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
173
174
  const URL = artifacts.URL;
174
- const chains = await ComputedChains.request({devtoolsLog, trace, URL}, context);
175
+ const chains = await ComputedChains.request({settings, devtoolsLog, trace, URL}, context);
175
176
  let chainCount = 0;
176
177
  /**
177
178
  * @param {LH.Audit.Details.SimpleCriticalRequestNode} node
@@ -16,9 +16,10 @@ import {Audit} from '../audit.js';
16
16
  * @return {Promise<import('@paulirish/trace_engine/models/trace/insights/types.js').InsightSet|undefined>}
17
17
  */
18
18
  async function getInsightSet(artifacts, context) {
19
+ const settings = context.settings;
19
20
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
20
21
  const processedTrace = await ProcessedTrace.request(trace, context);
21
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
22
+ const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
22
23
 
23
24
  const navigationId = processedTrace.timeOriginEvt.args.data?.navigationId;
24
25
  const key = navigationId ?? NO_NAVIGATION;
@@ -57,8 +57,9 @@ class LayoutShifts extends Audit {
57
57
  * @return {Promise<LH.Audit.Product>}
58
58
  */
59
59
  static async audit(artifacts, context) {
60
+ const settings = context.settings;
60
61
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
61
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
62
+ const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
62
63
  const clusters = traceEngineResult.data.LayoutShifts.clusters ?? [];
63
64
  const {cumulativeLayoutShift: clsSavings, impactByNodeId} =
64
65
  await CumulativeLayoutShiftComputed.request(trace, context);
@@ -192,7 +192,8 @@ class LongTasks extends Audit {
192
192
  taskTimingsByEvent = new Map();
193
193
 
194
194
  const simulatorOptions = {devtoolsLog, settings: context.settings};
195
- const pageGraph = await PageDependencyGraph.request({trace, devtoolsLog, URL}, context);
195
+ const pageGraph =
196
+ await PageDependencyGraph.request({settings, trace, devtoolsLog, URL}, context);
196
197
  const simulator = await LoadSimulator.request(simulatorOptions, context);
197
198
  const simulation = await simulator.simulate(pageGraph, {label: 'long-tasks-diagnostic'});
198
199
  for (const [node, timing] of simulation.nodeTimings.entries()) {
@@ -114,8 +114,12 @@ class ScriptTreemapDataAudit extends Audit {
114
114
  */
115
115
  function collapseAll(node) {
116
116
  while (node.children && node.children.length === 1) {
117
- node.name += '/' + node.children[0].name;
118
- node.children = node.children[0].children;
117
+ const child = node.children[0];
118
+ node.name += '/' + child.name;
119
+ if (child.duplicatedNormalizedModuleName) {
120
+ node.duplicatedNormalizedModuleName = child.duplicatedNormalizedModuleName;
121
+ }
122
+ node.children = child.children;
119
123
  }
120
124
 
121
125
  if (node.children) {
@@ -137,7 +137,7 @@ class UsesRelPreconnectAudit extends Audit {
137
137
  MainResource.request({devtoolsLog, URL: artifacts.URL}, context),
138
138
  LoadSimulator.request({devtoolsLog, settings}, context),
139
139
  ProcessedNavigation.request(trace, context),
140
- PageDependencyGraph.request({trace, devtoolsLog, URL: artifacts.URL}, context),
140
+ PageDependencyGraph.request({settings, trace, devtoolsLog, URL: artifacts.URL}, context),
141
141
  ]);
142
142
 
143
143
  const {rtt, additionalRttByOrigin} = loadSimulator.getOptions();
@@ -212,6 +212,7 @@ class UsesRelPreloadAudit extends Audit {
212
212
  * @return {Promise<LH.Audit.Product>}
213
213
  */
214
214
  static async audit(artifacts, context) {
215
+ const settings = context.settings;
215
216
  const trace = artifacts.traces[UsesRelPreloadAudit.DEFAULT_PASS];
216
217
  const devtoolsLog = artifacts.devtoolsLogs[UsesRelPreloadAudit.DEFAULT_PASS];
217
218
  const URL = artifacts.URL;
@@ -219,7 +220,7 @@ class UsesRelPreloadAudit extends Audit {
219
220
 
220
221
  const [mainResource, graph, simulator] = await Promise.all([
221
222
  MainResource.request({devtoolsLog, URL}, context),
222
- PageDependencyGraph.request({trace, devtoolsLog, URL}, context),
223
+ PageDependencyGraph.request({settings, trace, devtoolsLog, URL}, context),
223
224
  LoadSimulator.request(simulatorOptions, context),
224
225
  ]);
225
226
 
@@ -4,6 +4,7 @@ declare const CriticalRequestChainsComputed: typeof CriticalRequestChains & {
4
4
  URL: LH.Artifacts["URL"];
5
5
  devtoolsLog: LH.DevtoolsLog;
6
6
  trace: LH.Trace;
7
+ settings: LH.Audit.Context["settings"];
7
8
  }, context: LH.Artifacts.ComputedContext) => ReturnType<typeof CriticalRequestChains.compute_>;
8
9
  };
9
10
  declare class CriticalRequestChains {
@@ -24,7 +25,7 @@ declare class CriticalRequestChains {
24
25
  */
25
26
  static extractChainsFromGraph(mainResource: LH.Artifacts.NetworkRequest, graph: LH.Gatherer.Simulation.GraphNode): LH.Artifacts.CriticalRequestNode;
26
27
  /**
27
- * @param {{URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace}} data
28
+ * @param {{URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
28
29
  * @param {LH.Artifacts.ComputedContext} context
29
30
  * @return {Promise<LH.Artifacts.CriticalRequestNode>}
30
31
  */
@@ -32,6 +33,7 @@ declare class CriticalRequestChains {
32
33
  URL: LH.Artifacts["URL"];
33
34
  devtoolsLog: LH.DevtoolsLog;
34
35
  trace: LH.Trace;
36
+ settings: LH.Audit.Context["settings"];
35
37
  }, context: LH.Artifacts.ComputedContext): Promise<LH.Artifacts.CriticalRequestNode>;
36
38
  }
37
39
  import * as Lantern from '../lib/lantern/lantern.js';
@@ -126,7 +126,7 @@ class CriticalRequestChains {
126
126
  }
127
127
 
128
128
  /**
129
- * @param {{URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace}} data
129
+ * @param {{URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
130
130
  * @param {LH.Artifacts.ComputedContext} context
131
131
  * @return {Promise<LH.Artifacts.CriticalRequestNode>}
132
132
  */
@@ -139,5 +139,5 @@ class CriticalRequestChains {
139
139
  }
140
140
 
141
141
  const CriticalRequestChainsComputed =
142
- makeComputedArtifact(CriticalRequestChains, ['URL', 'devtoolsLog', 'trace']);
142
+ makeComputedArtifact(CriticalRequestChains, ['URL', 'devtoolsLog', 'trace', 'settings']);
143
143
  export {CriticalRequestChainsComputed as CriticalRequestChains};
@@ -1,6 +1,9 @@
1
1
  export { NavigationInsightsComputed as NavigationInsights };
2
2
  declare const NavigationInsightsComputed: typeof NavigationInsights & {
3
- request: (dependencies: import("../index.js").Trace, context: LH.Artifacts.ComputedContext) => ReturnType<typeof NavigationInsights.compute_>;
3
+ request: (dependencies: {
4
+ trace: LH.Trace;
5
+ settings: LH.Audit.Context["settings"];
6
+ }, context: LH.Artifacts.ComputedContext) => ReturnType<typeof NavigationInsights.compute_>;
4
7
  };
5
8
  /**
6
9
  * @fileoverview Gets insights from the shared trace engine for the navigation audited by Lighthouse.
@@ -8,9 +11,12 @@ declare const NavigationInsightsComputed: typeof NavigationInsights & {
8
11
  */
9
12
  declare class NavigationInsights {
10
13
  /**
11
- * @param {LH.Trace} trace
14
+ * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
12
15
  * @param {LH.Artifacts.ComputedContext} context
13
16
  */
14
- static compute_(trace: LH.Trace, context: LH.Artifacts.ComputedContext): Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").InsightSet>;
17
+ static compute_(data: {
18
+ trace: LH.Trace;
19
+ settings: LH.Audit.Context["settings"];
20
+ }, context: LH.Artifacts.ComputedContext): Promise<import("@paulirish/trace_engine/models/trace/insights/types.js").InsightSet>;
15
21
  }
16
22
  //# sourceMappingURL=navigation-insights.d.ts.map
@@ -14,12 +14,13 @@ import {TraceEngineResult} from './trace-engine-result.js';
14
14
  */
15
15
  class NavigationInsights {
16
16
  /**
17
- * @param {LH.Trace} trace
17
+ * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
18
18
  * @param {LH.Artifacts.ComputedContext} context
19
19
  */
20
- static async compute_(trace, context) {
20
+ static async compute_(data, context) {
21
+ const {trace, settings} = data;
21
22
  const processedTrace = await ProcessedTrace.request(trace, context);
22
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
23
+ const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
23
24
 
24
25
  const navigationId = processedTrace.timeOriginEvt.args.data?.navigationId;
25
26
  if (!navigationId) throw new Error('No navigationId found');
@@ -31,5 +32,5 @@ class NavigationInsights {
31
32
  }
32
33
  }
33
34
 
34
- const NavigationInsightsComputed = makeComputedArtifact(NavigationInsights, null);
35
+ const NavigationInsightsComputed = makeComputedArtifact(NavigationInsights, ['trace', 'settings']);
35
36
  export {NavigationInsightsComputed as NavigationInsights};
@@ -3,19 +3,21 @@ declare const PageDependencyGraphComputed: typeof PageDependencyGraph & {
3
3
  request: (dependencies: {
4
4
  trace: LH.Trace;
5
5
  devtoolsLog: LH.DevtoolsLog;
6
+ settings: LH.Audit.Context["settings"];
6
7
  URL: LH.Artifacts["URL"];
7
8
  fromTrace?: boolean;
8
9
  }, context: LH.Artifacts.ComputedContext) => ReturnType<typeof PageDependencyGraph.compute_>;
9
10
  };
10
11
  declare class PageDependencyGraph {
11
12
  /**
12
- * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, URL: LH.Artifacts['URL'], fromTrace?: boolean}} data
13
+ * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, settings: LH.Audit.Context['settings'], URL: LH.Artifacts['URL'], fromTrace?: boolean}} data
13
14
  * @param {LH.Artifacts.ComputedContext} context
14
15
  * @return {Promise<LH.Gatherer.Simulation.GraphNode>}
15
16
  */
16
17
  static compute_(data: {
17
18
  trace: LH.Trace;
18
19
  devtoolsLog: LH.DevtoolsLog;
20
+ settings: LH.Audit.Context["settings"];
19
21
  URL: LH.Artifacts["URL"];
20
22
  fromTrace?: boolean;
21
23
  }, context: LH.Artifacts.ComputedContext): Promise<LH.Gatherer.Simulation.GraphNode>;
@@ -13,19 +13,19 @@ import {TraceEngineResult} from './trace-engine-result.js';
13
13
 
14
14
  class PageDependencyGraph {
15
15
  /**
16
- * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, URL: LH.Artifacts['URL'], fromTrace?: boolean}} data
16
+ * @param {{trace: LH.Trace, devtoolsLog: LH.DevtoolsLog, settings: LH.Audit.Context['settings'], URL: LH.Artifacts['URL'], fromTrace?: boolean}} data
17
17
  * @param {LH.Artifacts.ComputedContext} context
18
18
  * @return {Promise<LH.Gatherer.Simulation.GraphNode>}
19
19
  */
20
20
  static async compute_(data, context) {
21
- const {trace, devtoolsLog, URL} = data;
21
+ const {trace, settings, devtoolsLog, URL} = data;
22
22
  const [{mainThreadEvents}, networkRecords] = await Promise.all([
23
23
  ProcessedTrace.request(trace, context),
24
24
  NetworkRecords.request(devtoolsLog, context),
25
25
  ]);
26
26
 
27
27
  if (data.fromTrace) {
28
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
28
+ const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
29
29
  const traceEngineData = traceEngineResult.data;
30
30
  const requests =
31
31
  Lantern.TraceEngineComputationData.createNetworkRequests(trace, traceEngineData);
@@ -40,6 +40,6 @@ class PageDependencyGraph {
40
40
  }
41
41
  }
42
42
 
43
- const PageDependencyGraphComputed =
44
- makeComputedArtifact(PageDependencyGraph, ['devtoolsLog', 'trace', 'URL', 'fromTrace']);
43
+ const PageDependencyGraphComputed = makeComputedArtifact(PageDependencyGraph,
44
+ ['devtoolsLog', 'settings', 'trace', 'URL', 'fromTrace']);
45
45
  export {PageDependencyGraphComputed as PageDependencyGraph};
@@ -2,6 +2,7 @@ export { TraceEngineResultComputed as TraceEngineResult };
2
2
  declare const TraceEngineResultComputed: typeof TraceEngineResult & {
3
3
  request: (dependencies: {
4
4
  trace: LH.Trace;
5
+ settings: LH.Audit.Context["settings"];
5
6
  }, context: LH.Artifacts.ComputedContext) => ReturnType<typeof TraceEngineResult.compute_>;
6
7
  };
7
8
  /**
@@ -10,9 +11,10 @@ declare const TraceEngineResultComputed: typeof TraceEngineResult & {
10
11
  declare class TraceEngineResult {
11
12
  /**
12
13
  * @param {LH.TraceEvent[]} traceEvents
14
+ * @param {LH.Audit.Context['settings']} settings
13
15
  * @return {Promise<LH.Artifacts.TraceEngineResult>}
14
16
  */
15
- static runTraceEngine(traceEvents: LH.TraceEvent[]): Promise<LH.Artifacts.TraceEngineResult>;
17
+ static runTraceEngine(traceEvents: LH.TraceEvent[], settings: LH.Audit.Context["settings"]): Promise<LH.Artifacts.TraceEngineResult>;
16
18
  /**
17
19
  * Adapts the given DevTools function that returns a localized string to one
18
20
  * that returns a LH.IcuMessage.
@@ -45,12 +47,13 @@ declare class TraceEngineResult {
45
47
  */
46
48
  static localizeInsights(insightSets: import("@paulirish/trace_engine/models/trace/insights/types.js").TraceInsightSets): void;
47
49
  /**
48
- * @param {{trace: LH.Trace}} data
50
+ * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
49
51
  * @param {LH.Artifacts.ComputedContext} context
50
52
  * @return {Promise<LH.Artifacts.TraceEngineResult>}
51
53
  */
52
54
  static compute_(data: {
53
55
  trace: LH.Trace;
56
+ settings: LH.Audit.Context["settings"];
54
57
  }, context: LH.Artifacts.ComputedContext): Promise<LH.Artifacts.TraceEngineResult>;
55
58
  }
56
59
  import * as LH from '../../types/lh.js';
@@ -4,6 +4,8 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import log from 'lighthouse-logger';
8
+
7
9
  import * as i18n from '../lib/i18n/i18n.js';
8
10
  import * as TraceEngine from '../lib/trace-engine.js';
9
11
  import {makeComputedArtifact} from './computed-artifact.js';
@@ -17,15 +19,35 @@ import * as LH from '../../types/lh.js';
17
19
  class TraceEngineResult {
18
20
  /**
19
21
  * @param {LH.TraceEvent[]} traceEvents
22
+ * @param {LH.Audit.Context['settings']} settings
20
23
  * @return {Promise<LH.Artifacts.TraceEngineResult>}
21
24
  */
22
- static async runTraceEngine(traceEvents) {
25
+ static async runTraceEngine(traceEvents, settings) {
23
26
  const processor = new TraceEngine.TraceProcessor(TraceEngine.TraceHandlers);
24
27
 
28
+ const lanternSettings = {};
29
+ if (settings.throttlingMethod) lanternSettings.throttlingMethod = settings.throttlingMethod;
30
+ if (settings.throttling) lanternSettings.throttling = settings.throttling;
31
+ if (settings.precomputedLanternData) {
32
+ lanternSettings.precomputedLanternData = settings.precomputedLanternData;
33
+ }
34
+
25
35
  // eslint-disable-next-line max-len
26
36
  await processor.parse(/** @type {import('@paulirish/trace_engine').Types.Events.Event[]} */ (
27
37
  traceEvents
28
- ), {});
38
+ ), {
39
+ logger: {
40
+ start(id) {
41
+ const logId = `lh:computed:TraceEngineResult:${id}`;
42
+ log.time({msg: `Trace Engine ${id}`, id: logId});
43
+ },
44
+ end(id) {
45
+ const logId = `lh:computed:TraceEngineResult:${id}`;
46
+ log.timeEnd({msg: `Trace Engine ${id}`, id: logId});
47
+ },
48
+ },
49
+ lanternSettings,
50
+ });
29
51
  if (!processor.parsedTrace) throw new Error('No data');
30
52
  if (!processor.insights) throw new Error('No insights');
31
53
  this.localizeInsights(processor.insights);
@@ -177,7 +199,7 @@ class TraceEngineResult {
177
199
  }
178
200
 
179
201
  /**
180
- * @param {{trace: LH.Trace}} data
202
+ * @param {{trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
181
203
  * @param {LH.Artifacts.ComputedContext} context
182
204
  * @return {Promise<LH.Artifacts.TraceEngineResult>}
183
205
  */
@@ -207,10 +229,10 @@ class TraceEngineResult {
207
229
  }
208
230
  }
209
231
 
210
- const result = await TraceEngineResult.runTraceEngine(traceEvents);
232
+ const result = await TraceEngineResult.runTraceEngine(traceEvents, data.settings);
211
233
  return result;
212
234
  }
213
235
  }
214
236
 
215
- const TraceEngineResultComputed = makeComputedArtifact(TraceEngineResult, ['trace']);
237
+ const TraceEngineResultComputed = makeComputedArtifact(TraceEngineResult, ['trace', 'settings']);
216
238
  export {TraceEngineResultComputed as TraceEngineResult};
@@ -386,7 +386,8 @@ class TraceElements extends BaseGatherer {
386
386
  const session = context.driver.defaultSession;
387
387
 
388
388
  const trace = context.dependencies.Trace;
389
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
389
+ const settings = context.settings;
390
+ const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
390
391
  const rootCauses = context.dependencies.RootCauses;
391
392
 
392
393
  const processedTrace = await ProcessedTrace.request(trace, context);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "12.4.0-dev.20250312",
4
+ "version": "12.4.0-dev.20250313",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -184,7 +184,7 @@
184
184
  "webtreemap-cdt": "^3.2.1"
185
185
  },
186
186
  "dependencies": {
187
- "@paulirish/trace_engine": "0.0.47",
187
+ "@paulirish/trace_engine": "0.0.48",
188
188
  "@sentry/node": "^7.0.0",
189
189
  "axe-core": "^4.10.2",
190
190
  "chrome-launcher": "^1.1.2",