lighthouse 13.4.0-dev.20260630 → 13.4.1-dev.20260720

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.
@@ -244,6 +244,7 @@ declare class Baseline extends Audit {
244
244
  grid: string;
245
245
  "grid-animation": string;
246
246
  "hardware-concurrency": string;
247
+ has: string;
247
248
  "hashbang-comments": string;
248
249
  hashchange: string;
249
250
  head: string;
@@ -337,6 +338,7 @@ declare class Baseline extends Audit {
337
338
  "link-selectors": string;
338
339
  "list-elements": string;
339
340
  "list-style": string;
341
+ "loading-lazy": string;
340
342
  localstorage: string;
341
343
  location: string;
342
344
  "logical-assignments": string;
@@ -677,13 +679,13 @@ declare class Baseline extends Audit {
677
679
  "document-caretpositionfrompoint": string;
678
680
  "event-timing": string;
679
681
  "fetch-priority": string;
682
+ "field-sizing": string;
680
683
  float16array: string;
681
684
  "font-family-math": string;
682
685
  "font-size-adjust": string;
683
686
  gethtml: string;
684
687
  getorinsert: string;
685
688
  "gradient-interpolation": string;
686
- has: string;
687
689
  highlight: string;
688
690
  http3: string;
689
691
  "input-file-webkitdirectory": string;
@@ -699,7 +701,6 @@ declare class Baseline extends Audit {
699
701
  "largest-contentful-paint": string;
700
702
  "light-dark": string;
701
703
  "link-rel-dns-prefetch": string;
702
- "loading-lazy": string;
703
704
  "math-sum-precise": string;
704
705
  navigation: string;
705
706
  "open-pseudo": string;
@@ -786,6 +787,16 @@ declare class Baseline extends Audit {
786
787
  displayStatus: string;
787
788
  baselineTier: "high" | "low" | "limited";
788
789
  } | null;
790
+ /**
791
+ * @param {string} featureId
792
+ * @param {{high: Record<string, string>, low: Record<string, string>, limited: string[]}} featureData
793
+ * @return {string|null}
794
+ */
795
+ static getLowDate(featureId: string, featureData: {
796
+ high: Record<string, string>;
797
+ low: Record<string, string>;
798
+ limited: string[];
799
+ }): string | null;
789
800
  /**
790
801
  * @param {LH.Artifacts} artifacts
791
802
  * @return {Promise<LH.Audit.Product>}
@@ -91,6 +91,25 @@ class Baseline extends Audit {
91
91
  return null;
92
92
  }
93
93
 
94
+ /**
95
+ * @param {string} featureId
96
+ * @param {{high: Record<string, string>, low: Record<string, string>, limited: string[]}} featureData
97
+ * @return {string|null}
98
+ */
99
+ static getLowDate(featureId, featureData) {
100
+ if (featureId in featureData.low) {
101
+ const lowData = /** @type {Record<string, string>} */ (featureData.low);
102
+ return lowData[featureId];
103
+ }
104
+ if (featureId in featureData.high) {
105
+ const highData = /** @type {Record<string, string>} */ (featureData.high);
106
+ const date = new Date(highData[featureId]);
107
+ date.setUTCMonth(date.getUTCMonth() - 30);
108
+ return date.toISOString().slice(0, 10);
109
+ }
110
+ return null;
111
+ }
112
+
94
113
  /**
95
114
  * @param {LH.Artifacts} artifacts
96
115
  * @return {Promise<LH.Audit.Product>}
@@ -101,15 +120,14 @@ class Baseline extends Audit {
101
120
  /** @type {Map<string, {featureId: string, source: LH.Audit.Details.SourceLocationValue | undefined}>} */
102
121
  const featuresMap = new Map();
103
122
 
104
- const dxEvents = /** @type {DXFeatureEvent[]} */ (
105
- (trace.traceEvents || []).filter(e => e.cat === 'blink.webdx_feature_usage' &&
106
- e.args?.feature)
107
- );
108
-
109
- for (const event of dxEvents) {
110
- const key = `${event.args.feature}`;
123
+ for (const e of trace.traceEvents || []) {
124
+ if (e.cat !== 'blink.webdx_feature_usage' || !e.args?.feature) {
125
+ continue;
126
+ }
127
+ const event = /** @type {DXFeatureEvent} */ (e);
111
128
 
112
- if (featuresMap.has(key)) continue;
129
+ const feature = /** @type {string} */ (event.args.feature);
130
+ if (featuresMap.has(feature)) continue;
113
131
 
114
132
  /** @type {LH.Audit.Details.SourceLocationValue | undefined} */
115
133
  let source;
@@ -121,8 +139,8 @@ class Baseline extends Audit {
121
139
  source = Audit.makeSourceLocation(event.args.url, line, column);
122
140
  }
123
141
 
124
- featuresMap.set(key, {
125
- featureId: event.args.feature,
142
+ featuresMap.set(feature, {
143
+ featureId: feature,
126
144
  source,
127
145
  });
128
146
  }
@@ -142,6 +160,8 @@ class Baseline extends Audit {
142
160
  if (!status) continue;
143
161
  const {displayStatus, baselineTier} = status;
144
162
 
163
+ const lowDate = Baseline.getLowDate(featureId, Baseline.featureData) || '';
164
+
145
165
  baselineStatus.push({
146
166
  featureId: {
147
167
  type: /** @type {const} */ ('link'),
@@ -154,11 +174,12 @@ class Baseline extends Audit {
154
174
  displayString: displayStatus,
155
175
  },
156
176
  source: feature.source,
177
+ lowDate,
157
178
  });
158
179
  }
159
180
 
160
181
  /** @type {LH.Audit.Details.Table['headings']} */
161
- const headings = [
182
+ const webFeatureHeadings = [
162
183
  {
163
184
  key: 'featureId',
164
185
  valueType: 'link',
@@ -176,43 +197,53 @@ class Baseline extends Audit {
176
197
  },
177
198
  ];
178
199
 
179
- /**
180
- * Determines the sorting rank of a baseline status.
181
- * @param {string} status The display status string.
182
- * @return {number} The numerical rank (1 is the highest priority).
183
- */
184
- const getStatusRank = (status) => {
185
- if (status.startsWith('Limited')) {
186
- return 1;
187
- }
188
- if (status.startsWith('Newly')) {
189
- return 2;
190
- }
191
- if (status.startsWith('Widely')) {
192
- return 3;
193
- }
194
- return 4;
200
+ /** @type {Record<string, number>} */
201
+ const TIER_RANKS = {
202
+ limited: 1,
203
+ low: 2,
204
+ high: 3,
195
205
  };
196
206
 
197
207
  const sortedStatuses = baselineStatus.sort((featureA, featureB) => {
198
- const rankA = getStatusRank(featureA.displayStatus.displayString);
199
- const rankB = getStatusRank(featureB.displayStatus.displayString);
208
+ const rankA = TIER_RANKS[featureA.displayStatus.status] || 4;
209
+ const rankB = TIER_RANKS[featureB.displayStatus.status] || 4;
200
210
 
201
211
  if (rankA !== rankB) {
202
212
  return rankA - rankB;
203
213
  }
204
214
 
205
- const hasSourceA = !!featureA.source;
206
- const hasSourceB = !!featureB.source;
215
+ return featureB.lowDate.localeCompare(featureA.lowDate);
216
+ });
207
217
 
208
- if (hasSourceA !== hasSourceB) {
209
- return hasSourceA ? -1 : 1;
218
+ const hasLimited = baselineStatus.some(item => item.displayStatus.status === 'limited');
219
+
220
+ /** @type {LH.Audit.Details.DebugData | undefined} */
221
+ let debugData;
222
+ if (!hasLimited && sortedStatuses.length > 0) {
223
+ const newestFeature = sortedStatuses[0];
224
+ const featureName = newestFeature.featureId.text;
225
+ const lowDate = newestFeature.lowDate;
226
+ if (lowDate) {
227
+ const year = lowDate.substring(0, 4);
228
+ debugData = {
229
+ type: 'debugdata',
230
+ newestFeatureId: featureName,
231
+ newestFeatureYear: year,
232
+ newestFeatureLowDate: lowDate,
233
+ };
210
234
  }
235
+ }
211
236
 
212
- return 0;
237
+ // Remove `lowDate` property from items before generating details table.
238
+ const tableItems = sortedStatuses.map(item => {
239
+ const {lowDate: _, ...rest} = item;
240
+ return rest;
213
241
  });
214
242
 
215
- const details = Audit.makeTableDetails(headings, sortedStatuses);
243
+ const details = Audit.makeTableDetails(webFeatureHeadings, tableItems);
244
+ if (debugData) {
245
+ details.debugData = debugData;
246
+ }
216
247
 
217
248
  return {
218
249
  score: 1,
@@ -35,7 +35,7 @@ class WebMcpFormCoverage extends Audit {
35
35
  title: str_(UIStrings.title),
36
36
  description: str_(UIStrings.description),
37
37
  requiredArtifacts: ['Inputs', 'WebMCP'],
38
- supportedModes: ['navigation', 'snapshot'],
38
+ supportedModes: ['navigation'],
39
39
  };
40
40
  }
41
41
 
@@ -45,7 +45,7 @@ class WebMCPRegisteredTools extends Audit {
45
45
  title: str_(UIStrings.title),
46
46
  description: str_(UIStrings.description),
47
47
  requiredArtifacts: ['WebMCP'],
48
- supportedModes: ['navigation', 'snapshot'],
48
+ supportedModes: ['navigation'],
49
49
  };
50
50
  }
51
51
 
@@ -48,7 +48,7 @@ class WebMcpSchemaValidity extends Audit {
48
48
  failureTitle: str_(UIStrings.failureTitle),
49
49
  description: str_(UIStrings.description),
50
50
  requiredArtifacts: ['WebMCP', 'WebMcpSchemaIssues'],
51
- supportedModes: ['navigation', 'snapshot'],
51
+ supportedModes: ['navigation'],
52
52
  };
53
53
  }
54
54
 
@@ -11,7 +11,7 @@ import {pageFunctions} from '../../lib/page-functions.js';
11
11
  class WebMcpSchemaIssues extends BaseGatherer {
12
12
  /** @type {LH.Gatherer.GathererMeta} */
13
13
  meta = {
14
- supportedModes: ['navigation', 'snapshot'],
14
+ supportedModes: ['navigation'],
15
15
  };
16
16
 
17
17
  constructor() {
@@ -25,7 +25,7 @@ import {pageFunctions} from '../../lib/page-functions.js';
25
25
  class WebMCP extends BaseGatherer {
26
26
  /** @type {LH.Gatherer.GathererMeta} */
27
27
  meta = {
28
- supportedModes: ['navigation', 'snapshot'],
28
+ supportedModes: ['navigation'],
29
29
  };
30
30
 
31
31
  constructor() {
@@ -135,8 +135,8 @@ class WebMCP extends BaseGatherer {
135
135
  */
136
136
  async getArtifact(context) {
137
137
  const isSupported = await context.driver.executionContext.evaluate(
138
- // @ts-expect-error - modelContext is not in types
139
- () => typeof navigator.modelContext !== 'undefined',
138
+ () => typeof (/** @type {any} */ (navigator)).modelContext !== 'undefined' ||
139
+ typeof (/** @type {any} */ (document)).modelContext !== 'undefined',
140
140
  {args: [], useIsolation: true}
141
141
  );
142
142
  if (!isSupported || !this._isSupported) {
@@ -233,6 +233,7 @@
233
233
  "grid": "2017-10-17",
234
234
  "grid-animation": "2022-10-27",
235
235
  "hardware-concurrency": "2022-03-14",
236
+ "has": "2023-12-19",
236
237
  "hashbang-comments": "2020-03-24",
237
238
  "hashchange": "2015-07-29",
238
239
  "head": "2015-07-29",
@@ -326,6 +327,7 @@
326
327
  "link-selectors": "2020-01-15",
327
328
  "list-elements": "2015-07-29",
328
329
  "list-style": "2015-07-29",
330
+ "loading-lazy": "2023-12-19",
329
331
  "localstorage": "2015-07-29",
330
332
  "location": "2015-07-29",
331
333
  "logical-assignments": "2020-09-16",
@@ -666,13 +668,13 @@
666
668
  "document-caretpositionfrompoint": "2025-12-12",
667
669
  "event-timing": "2025-12-12",
668
670
  "fetch-priority": "2024-10-29",
671
+ "field-sizing": "2026-06-16",
669
672
  "float16array": "2025-04-04",
670
673
  "font-family-math": "2026-03-24",
671
674
  "font-size-adjust": "2024-07-25",
672
675
  "gethtml": "2024-09-16",
673
676
  "getorinsert": "2026-02-14",
674
677
  "gradient-interpolation": "2024-06-11",
675
- "has": "2023-12-19",
676
678
  "highlight": "2026-03-24",
677
679
  "http3": "2024-09-16",
678
680
  "input-file-webkitdirectory": "2025-08-19",
@@ -688,7 +690,6 @@
688
690
  "largest-contentful-paint": "2025-12-12",
689
691
  "light-dark": "2024-05-13",
690
692
  "link-rel-dns-prefetch": "2025-09-15",
691
- "loading-lazy": "2023-12-19",
692
693
  "math-sum-precise": "2026-04-10",
693
694
  "navigation": "2026-01-13",
694
695
  "open-pseudo": "2026-05-11",
@@ -892,7 +893,6 @@
892
893
  "fetch-metadata",
893
894
  "fetch-request-streams",
894
895
  "fetchlater",
895
- "field-sizing",
896
896
  "file-system-access",
897
897
  "filter-function",
898
898
  "fit-content-function",
@@ -920,6 +920,7 @@
920
920
  "gyroscope",
921
921
  "hanging-punctuation",
922
922
  "has-slotted",
923
+ "heading-offset",
923
924
  "heading-selectors",
924
925
  "hidden-until-found",
925
926
  "highlightsfrompoint",
@@ -981,6 +982,7 @@
981
982
  "meta-application-title",
982
983
  "meta-text-scale",
983
984
  "meta-theme-color",
985
+ "mixin",
984
986
  "move-before",
985
987
  "mutation-events",
986
988
  "navigation-precommit-handlers",
@@ -1092,6 +1094,7 @@
1092
1094
  "summarizer",
1093
1095
  "supports-at-rule",
1094
1096
  "svg-discouraged",
1097
+ "switch-control",
1095
1098
  "table-discouraged",
1096
1099
  "target-within",
1097
1100
  "temporal",
@@ -1,3 +1,3 @@
1
1
  {
2
- "date": "2026-06-19"
2
+ "date": "2026-07-15"
3
3
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "13.4.0-dev.20260630",
4
+ "version": "13.4.1-dev.20260720",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -138,7 +138,7 @@
138
138
  "archiver": "^7.0.1",
139
139
  "builtin-modules": "^3.3.0",
140
140
  "chalk": "^2.4.1",
141
- "chrome-devtools-frontend": "1.0.1650100",
141
+ "chrome-devtools-frontend": "1.0.1662965",
142
142
  "colors": "^1.4.0",
143
143
  "concurrently": "^9.2.1",
144
144
  "conventional-changelog-cli": "^2.1.1",
@@ -167,7 +167,7 @@
167
167
  "pako": "^2.1.0",
168
168
  "preact": "^10.7.2",
169
169
  "pretty-json-stringify": "^0.0.2",
170
- "puppeteer": "^25.2.0",
170
+ "puppeteer": "^25.3.0",
171
171
  "resolve": "^1.22.10",
172
172
  "rollup-plugin-polyfill-node": "^0.12.0",
173
173
  "source-map-support": "^0.5.21",
@@ -185,7 +185,7 @@
185
185
  "chrome-launcher": "^1.2.1",
186
186
  "configstore": "^7.0.0",
187
187
  "csp_evaluator": "1.1.8",
188
- "devtools-protocol": "0.0.1625959",
188
+ "devtools-protocol": "0.0.1663043",
189
189
  "enquirer": "^2.3.6",
190
190
  "http-link-header": "^1.1.1",
191
191
  "intl-messageformat": "^10.5.3",
@@ -196,19 +196,19 @@
196
196
  "lodash-es": "^4.17.21",
197
197
  "lookup-closest-locale": "6.2.0",
198
198
  "open": "^8.4.0",
199
- "puppeteer-core": "^25.2.0",
199
+ "puppeteer-core": "^25.3.0",
200
200
  "robots-parser": "^3.0.1",
201
201
  "speedline-core": "^1.4.3",
202
202
  "third-party-web": "^0.29.2",
203
- "tldts-icann": "^7.4.4",
204
- "web-features": "^3.31.0",
203
+ "tldts-icann": "^7.4.9",
204
+ "web-features": "^3.34.0",
205
205
  "ws": "^7.0.0",
206
206
  "yargs": "^17.3.1",
207
207
  "yargs-parser": "^21.0.0"
208
208
  },
209
209
  "resolutions": {
210
- "puppeteer/**/devtools-protocol": "0.0.1625959",
211
- "puppeteer-core/**/devtools-protocol": "0.0.1625959"
210
+ "puppeteer/**/devtools-protocol": "0.0.1663043",
211
+ "puppeteer-core/**/devtools-protocol": "0.0.1663043"
212
212
  },
213
213
  "repository": {
214
214
  "type": "git",