lighthouse 13.4.0 → 13.4.1
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/.agents/skills/lighthouse-verification/SKILL.md +25 -0
- package/core/audits/agentic/agent-accessibility-tree.js +3 -2
- package/core/audits/agentic/llms-txt.d.ts +1 -0
- package/core/audits/agentic/llms-txt.js +15 -1
- package/core/audits/baseline.d.ts +788 -0
- package/core/audits/baseline.js +117 -49
- package/core/audits/seo/robots-txt.d.ts +1 -0
- package/core/audits/seo/robots-txt.js +22 -8
- package/core/audits/webmcp-form-coverage.js +3 -3
- package/core/audits/webmcp-registered-tools.js +2 -2
- package/core/audits/webmcp-schema-validity.js +4 -4
- package/core/gather/gatherers/agentic/llms-txt.js +5 -1
- package/core/gather/gatherers/seo/robots-txt.js +6 -1
- package/core/gather/gatherers/webmcp-schema.js +1 -1
- package/core/gather/gatherers/webmcp.js +3 -3
- package/core/lib/baseline/web-features-data.json +21 -16
- package/core/lib/baseline/web-features-metadata.json +1 -1
- package/core/lib/deprecations-strings.d.ts +104 -96
- package/core/lib/deprecations-strings.js +8 -0
- package/package.json +18 -15
- package/shared/localization/locales/en-US.json +12 -6
- package/shared/localization/locales/en-XL.json +12 -6
package/core/audits/baseline.js
CHANGED
|
@@ -31,6 +31,8 @@ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
|
31
31
|
/** @typedef {LH.TraceEvent & {args: {feature: string, url?: string, lineNumber?: number, columnNumber?: number}}} DXFeatureEvent */
|
|
32
32
|
|
|
33
33
|
class Baseline extends Audit {
|
|
34
|
+
static featureData = data;
|
|
35
|
+
|
|
34
36
|
/**
|
|
35
37
|
* @return {LH.Audit.Meta}
|
|
36
38
|
*/
|
|
@@ -44,6 +46,70 @@ class Baseline extends Audit {
|
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Determines the baseline status and display string for a given feature ID.
|
|
51
|
+
* @param {string} featureId
|
|
52
|
+
* @param {{high: Record<string, string>, low: Record<string, string>, limited: string[]}} featureData
|
|
53
|
+
* @param {Date} currentDate
|
|
54
|
+
* @return {{displayStatus: string, baselineTier: 'high' | 'low' | 'limited'} | null}
|
|
55
|
+
*/
|
|
56
|
+
static getFeatureStatus(featureId, featureData, currentDate) {
|
|
57
|
+
if (featureId in featureData.high) {
|
|
58
|
+
const highData = /** @type {Record<string, string>} */ (featureData.high);
|
|
59
|
+
return {
|
|
60
|
+
displayStatus: `Widely Available (${highData[featureId]})`,
|
|
61
|
+
baselineTier: 'high',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (featureId in featureData.low) {
|
|
66
|
+
const lowData = /** @type {Record<string, string>} */ (featureData.low);
|
|
67
|
+
const widelyAvailableDate = new Date(lowData[featureId]);
|
|
68
|
+
widelyAvailableDate.setUTCMonth(widelyAvailableDate.getUTCMonth() + 30);
|
|
69
|
+
const widelyAvailableDateStr = widelyAvailableDate.toISOString().slice(0, 10);
|
|
70
|
+
|
|
71
|
+
if (widelyAvailableDate <= currentDate) {
|
|
72
|
+
return {
|
|
73
|
+
displayStatus: `Widely Available (${widelyAvailableDateStr})`,
|
|
74
|
+
baselineTier: 'high',
|
|
75
|
+
};
|
|
76
|
+
} else {
|
|
77
|
+
return {
|
|
78
|
+
displayStatus: `Newly Available (${lowData[featureId]})`,
|
|
79
|
+
baselineTier: 'low',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (featureData.limited.includes(featureId)) {
|
|
85
|
+
return {
|
|
86
|
+
displayStatus: 'Limited Availability',
|
|
87
|
+
baselineTier: 'limited',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
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
|
+
|
|
47
113
|
/**
|
|
48
114
|
* @param {LH.Artifacts} artifacts
|
|
49
115
|
* @return {Promise<LH.Audit.Product>}
|
|
@@ -54,15 +120,14 @@ class Baseline extends Audit {
|
|
|
54
120
|
/** @type {Map<string, {featureId: string, source: LH.Audit.Details.SourceLocationValue | undefined}>} */
|
|
55
121
|
const featuresMap = new Map();
|
|
56
122
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (const event of dxEvents) {
|
|
63
|
-
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);
|
|
64
128
|
|
|
65
|
-
|
|
129
|
+
const feature = /** @type {string} */ (event.args.feature);
|
|
130
|
+
if (featuresMap.has(feature)) continue;
|
|
66
131
|
|
|
67
132
|
/** @type {LH.Audit.Details.SourceLocationValue | undefined} */
|
|
68
133
|
let source;
|
|
@@ -74,14 +139,15 @@ class Baseline extends Audit {
|
|
|
74
139
|
source = Audit.makeSourceLocation(event.args.url, line, column);
|
|
75
140
|
}
|
|
76
141
|
|
|
77
|
-
featuresMap.set(
|
|
78
|
-
featureId:
|
|
142
|
+
featuresMap.set(feature, {
|
|
143
|
+
featureId: feature,
|
|
79
144
|
source,
|
|
80
145
|
});
|
|
81
146
|
}
|
|
82
147
|
|
|
83
148
|
const baselineFeatures = Array.from(featuresMap.values());
|
|
84
149
|
const baselineStatus = [];
|
|
150
|
+
const currentDate = new Date;
|
|
85
151
|
|
|
86
152
|
for (const feature of baselineFeatures) {
|
|
87
153
|
if (!feature.featureId) {
|
|
@@ -90,20 +156,11 @@ class Baseline extends Audit {
|
|
|
90
156
|
|
|
91
157
|
const featureId = feature.featureId;
|
|
92
158
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
displayStatus = `Widely Available (${highData[featureId]})`;
|
|
99
|
-
baselineTier = 'high';
|
|
100
|
-
} else if (featureId in data.low) {
|
|
101
|
-
const lowData = /** @type {Record<string, string>} */ (data.low);
|
|
102
|
-
displayStatus = `Newly Available (${lowData[featureId]})`;
|
|
103
|
-
baselineTier = 'low';
|
|
104
|
-
} else if (!data.limited.includes(featureId)) {
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
159
|
+
const status = Baseline.getFeatureStatus(featureId, Baseline.featureData, currentDate);
|
|
160
|
+
if (!status) continue;
|
|
161
|
+
const {displayStatus, baselineTier} = status;
|
|
162
|
+
|
|
163
|
+
const lowDate = Baseline.getLowDate(featureId, Baseline.featureData) || '';
|
|
107
164
|
|
|
108
165
|
baselineStatus.push({
|
|
109
166
|
featureId: {
|
|
@@ -117,11 +174,12 @@ class Baseline extends Audit {
|
|
|
117
174
|
displayString: displayStatus,
|
|
118
175
|
},
|
|
119
176
|
source: feature.source,
|
|
177
|
+
lowDate,
|
|
120
178
|
});
|
|
121
179
|
}
|
|
122
180
|
|
|
123
181
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
124
|
-
const
|
|
182
|
+
const webFeatureHeadings = [
|
|
125
183
|
{
|
|
126
184
|
key: 'featureId',
|
|
127
185
|
valueType: 'link',
|
|
@@ -139,43 +197,53 @@ class Baseline extends Audit {
|
|
|
139
197
|
},
|
|
140
198
|
];
|
|
141
199
|
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const getStatusRank = (status) => {
|
|
148
|
-
if (status.startsWith('Limited')) {
|
|
149
|
-
return 1;
|
|
150
|
-
}
|
|
151
|
-
if (status.startsWith('Newly')) {
|
|
152
|
-
return 2;
|
|
153
|
-
}
|
|
154
|
-
if (status.startsWith('Widely')) {
|
|
155
|
-
return 3;
|
|
156
|
-
}
|
|
157
|
-
return 4;
|
|
200
|
+
/** @type {Record<string, number>} */
|
|
201
|
+
const TIER_RANKS = {
|
|
202
|
+
limited: 1,
|
|
203
|
+
low: 2,
|
|
204
|
+
high: 3,
|
|
158
205
|
};
|
|
159
206
|
|
|
160
207
|
const sortedStatuses = baselineStatus.sort((featureA, featureB) => {
|
|
161
|
-
const rankA =
|
|
162
|
-
const rankB =
|
|
208
|
+
const rankA = TIER_RANKS[featureA.displayStatus.status] || 4;
|
|
209
|
+
const rankB = TIER_RANKS[featureB.displayStatus.status] || 4;
|
|
163
210
|
|
|
164
211
|
if (rankA !== rankB) {
|
|
165
212
|
return rankA - rankB;
|
|
166
213
|
}
|
|
167
214
|
|
|
168
|
-
|
|
169
|
-
|
|
215
|
+
return featureB.lowDate.localeCompare(featureA.lowDate);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const hasLimited = baselineStatus.some(item => item.displayStatus.status === 'limited');
|
|
170
219
|
|
|
171
|
-
|
|
172
|
-
|
|
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
|
+
};
|
|
173
234
|
}
|
|
235
|
+
}
|
|
174
236
|
|
|
175
|
-
|
|
237
|
+
// Remove `lowDate` property from items before generating details table.
|
|
238
|
+
const tableItems = sortedStatuses.map(item => {
|
|
239
|
+
const {lowDate: _, ...rest} = item;
|
|
240
|
+
return rest;
|
|
176
241
|
});
|
|
177
242
|
|
|
178
|
-
const details = Audit.makeTableDetails(
|
|
243
|
+
const details = Audit.makeTableDetails(webFeatureHeadings, tableItems);
|
|
244
|
+
if (debugData) {
|
|
245
|
+
details.debugData = debugData;
|
|
246
|
+
}
|
|
179
247
|
|
|
180
248
|
return {
|
|
181
249
|
score: 1,
|
|
@@ -50,8 +50,13 @@ const UIStrings = {
|
|
|
50
50
|
=1 {1 error found}
|
|
51
51
|
other {# errors found}
|
|
52
52
|
}`,
|
|
53
|
+
/**
|
|
54
|
+
* @description Explanatory message stating that there was a failure in an audit caused by Lighthouse not being able to download the robots.txt file for the site. Note: "robots.txt" is a canonical filename and should not be translated.
|
|
55
|
+
* @example {Timed out fetching resource} error
|
|
56
|
+
* */
|
|
57
|
+
explanationWithError: 'Fetch of robots.txt failed: {error}',
|
|
53
58
|
/** Explanatory message stating that there was a failure in an audit caused by Lighthouse not being able to download the robots.txt file for the site. Note: "robots.txt" is a canonical filename and should not be translated. */
|
|
54
|
-
explanation: '
|
|
59
|
+
explanation: 'Fetch of robots.txt failed',
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
@@ -200,24 +205,33 @@ class RobotsTxt extends Audit {
|
|
|
200
205
|
const {
|
|
201
206
|
status,
|
|
202
207
|
content,
|
|
208
|
+
errorMessage,
|
|
203
209
|
} = artifacts.RobotsTxt;
|
|
204
210
|
|
|
205
|
-
|
|
211
|
+
// Do specific error messages first.
|
|
212
|
+
if (status && status >= HTTP_SERVER_ERROR_CODE_LOW) {
|
|
206
213
|
return {
|
|
207
214
|
score: 0,
|
|
208
|
-
|
|
215
|
+
displayValue: str_(UIStrings.displayValueHttpBadCode, {statusCode: status}),
|
|
216
|
+
};
|
|
217
|
+
} else if (status && status >= HTTP_CLIENT_ERROR_CODE_LOW || content === '') {
|
|
218
|
+
return {
|
|
219
|
+
score: 1,
|
|
220
|
+
notApplicable: true,
|
|
209
221
|
};
|
|
210
222
|
}
|
|
211
223
|
|
|
212
|
-
if (
|
|
224
|
+
if (errorMessage) {
|
|
213
225
|
return {
|
|
214
226
|
score: 0,
|
|
215
|
-
|
|
227
|
+
explanation: str_(UIStrings.explanationWithError, {error: errorMessage}),
|
|
216
228
|
};
|
|
217
|
-
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (!status) {
|
|
218
232
|
return {
|
|
219
|
-
score:
|
|
220
|
-
|
|
233
|
+
score: 0,
|
|
234
|
+
explanation: str_(UIStrings.explanation),
|
|
221
235
|
};
|
|
222
236
|
}
|
|
223
237
|
|
|
@@ -11,8 +11,8 @@ const UIStrings = {
|
|
|
11
11
|
/** Title of a Lighthouse audit that lists forms found in the page for WebMCP coverage. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
12
12
|
title: 'WebMCP form coverage',
|
|
13
13
|
/** Description of a Lighthouse audit that lists forms found in the page and indicates whether they have WebMCP declarative tool annotations. This is displayed after a user expands the section to see more. No character length limits. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
14
|
-
description: 'Consider adding [WebMCP](
|
|
15
|
-
'agents identify and interact with these forms more reliably.',
|
|
14
|
+
description: 'Consider adding [WebMCP](https://developer.chrome.com/docs/ai/webmcp) annotations to the forms listed below. ' +
|
|
15
|
+
'This helps AI agents identify and interact with these forms more reliably.',
|
|
16
16
|
/** [ICU Syntax] Label for the audit identifying the number of forms missing annotations. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
17
17
|
displayValue: `{itemCount, plural,
|
|
18
18
|
=1 {1 form missing annotations}
|
|
@@ -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'
|
|
38
|
+
supportedModes: ['navigation'],
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -15,7 +15,7 @@ const UIStrings = {
|
|
|
15
15
|
/** Title of a Lighthouse audit that lists registered WebMCP tools. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
16
16
|
title: 'WebMCP tools registered',
|
|
17
17
|
/** Description of a Lighthouse audit that lists registered WebMCP tools. This is displayed after a user expands the section to see more. No character length limits. "WebMCP" stands for "Web Model Context Protocol", neither should be translated. */
|
|
18
|
-
description: 'Lists the [WebMCP tools](
|
|
18
|
+
description: 'Lists the [WebMCP tools](https://developer.chrome.com/docs/ai/webmcp) registered at the time of analysis.',
|
|
19
19
|
/** Label for a column in a data table; entries will be the name of a WebMCP tool. */
|
|
20
20
|
columnTool: 'Tool name',
|
|
21
21
|
/** Label for a column in a data table; entries will be the description of a WebMCP tool. */
|
|
@@ -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'
|
|
48
|
+
supportedModes: ['navigation'],
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -13,9 +13,9 @@ const UIStrings = {
|
|
|
13
13
|
/** Title of a Lighthouse audit that provides detail on WebMCP schema validity. This descriptive title is shown to users when there are schema validity issues. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
14
14
|
failureTitle: 'WebMCP schemas are invalid',
|
|
15
15
|
/** Description of a Lighthouse audit that tells the user why they should ensure WebMCP schemas are valid. This is displayed after a user expands the section to see more. No character length limits. "WebMCP" stands for "Web Model Context Protocol" and should not be translated. */
|
|
16
|
-
description: 'Valid [WebMCP schemas](
|
|
17
|
-
'
|
|
18
|
-
|
|
16
|
+
description: 'Valid [WebMCP schemas](https://developer.chrome.com/docs/ai/webmcp) are required for AI agents to ' +
|
|
17
|
+
'understand and interact with tools correctly. ' +
|
|
18
|
+
'Please fix any errors or warnings reported by the browser.',
|
|
19
19
|
/** Header of the table column which displays the element. */
|
|
20
20
|
columnElement: 'Element',
|
|
21
21
|
/** Header of the table column which displays the issue. */
|
|
@@ -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'
|
|
51
|
+
supportedModes: ['navigation'],
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import log from 'lighthouse-logger';
|
|
7
8
|
|
|
8
9
|
import BaseGatherer from '../../base-gatherer.js';
|
|
9
10
|
|
|
@@ -21,7 +22,10 @@ class LlmsTxt extends BaseGatherer {
|
|
|
21
22
|
const {finalDisplayedUrl} = passContext.baseArtifacts.URL;
|
|
22
23
|
const llmUrl = new URL('/llms.txt', finalDisplayedUrl).href;
|
|
23
24
|
return passContext.driver.fetcher.fetchResource(llmUrl)
|
|
24
|
-
.catch(err =>
|
|
25
|
+
.catch(err => {
|
|
26
|
+
log.error('LlmsTxt', err);
|
|
27
|
+
return {status: null, content: null, errorMessage: err.message};
|
|
28
|
+
});
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
31
|
|
|
@@ -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 BaseGatherer from '../../base-gatherer.js';
|
|
8
10
|
|
|
9
11
|
class RobotsTxt extends BaseGatherer {
|
|
@@ -20,7 +22,10 @@ class RobotsTxt extends BaseGatherer {
|
|
|
20
22
|
const {finalDisplayedUrl} = passContext.baseArtifacts.URL;
|
|
21
23
|
const robotsUrl = new URL('/robots.txt', finalDisplayedUrl).href;
|
|
22
24
|
return passContext.driver.fetcher.fetchResource(robotsUrl)
|
|
23
|
-
.catch(err =>
|
|
25
|
+
.catch(err => {
|
|
26
|
+
log.error('RobotsTxt', err);
|
|
27
|
+
return {status: null, content: null, errorMessage: err.message};
|
|
28
|
+
});
|
|
24
29
|
}
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -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'
|
|
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'
|
|
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
|
-
|
|
139
|
-
|
|
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) {
|
|
@@ -77,7 +77,9 @@
|
|
|
77
77
|
"canvas": "2015-07-29",
|
|
78
78
|
"canvas-2d": "2015-07-29",
|
|
79
79
|
"canvas-createconicgradient": "2023-04-11",
|
|
80
|
+
"canvas-reset": "2023-12-11",
|
|
80
81
|
"canvas-roundrect": "2023-04-11",
|
|
82
|
+
"cap": "2023-12-11",
|
|
81
83
|
"capture-stream-canvas": "2020-01-15",
|
|
82
84
|
"caret-color": "2020-01-15",
|
|
83
85
|
"cascade-layers": "2022-03-14",
|
|
@@ -119,8 +121,10 @@
|
|
|
119
121
|
"contenteditable": "2015-07-29",
|
|
120
122
|
"cookies": "2015-07-29",
|
|
121
123
|
"cors": "2015-07-29",
|
|
124
|
+
"counter-set": "2023-12-11",
|
|
122
125
|
"counter-style": "2023-09-18",
|
|
123
126
|
"counters": "2015-07-29",
|
|
127
|
+
"createimagebitmap": "2023-12-11",
|
|
124
128
|
"credential-management": "2020-01-15",
|
|
125
129
|
"csp": "2016-08-02",
|
|
126
130
|
"css-escape": "2020-01-15",
|
|
@@ -142,6 +146,7 @@
|
|
|
142
146
|
"device-orientation-events": "2023-09-18",
|
|
143
147
|
"dfn": "2015-07-29",
|
|
144
148
|
"dialog": "2022-03-14",
|
|
149
|
+
"dir-pseudo": "2023-12-07",
|
|
145
150
|
"dirname": "2023-08-01",
|
|
146
151
|
"display": "2015-07-29",
|
|
147
152
|
"display-flow-root": "2020-01-15",
|
|
@@ -165,6 +170,7 @@
|
|
|
165
170
|
"error-cause": "2021-09-20",
|
|
166
171
|
"events": "2015-07-29",
|
|
167
172
|
"ex": "2015-07-29",
|
|
173
|
+
"exp-functions": "2023-12-07",
|
|
168
174
|
"exponentiation": "2017-03-27",
|
|
169
175
|
"ext-blend-minmax": "2018-04-30",
|
|
170
176
|
"ext-color-buffer-float": "2021-09-20",
|
|
@@ -227,6 +233,7 @@
|
|
|
227
233
|
"grid": "2017-10-17",
|
|
228
234
|
"grid-animation": "2022-10-27",
|
|
229
235
|
"hardware-concurrency": "2022-03-14",
|
|
236
|
+
"has": "2023-12-19",
|
|
230
237
|
"hashbang-comments": "2020-03-24",
|
|
231
238
|
"hashchange": "2015-07-29",
|
|
232
239
|
"head": "2015-07-29",
|
|
@@ -313,12 +320,14 @@
|
|
|
313
320
|
"lh": "2023-11-21",
|
|
314
321
|
"line-break": "2020-07-28",
|
|
315
322
|
"line-height": "2015-07-29",
|
|
323
|
+
"linear-easing": "2023-12-11",
|
|
316
324
|
"link": "2015-07-29",
|
|
317
325
|
"link-rel-preconnect": "2020-01-15",
|
|
318
326
|
"link-rel-preload": "2021-01-26",
|
|
319
327
|
"link-selectors": "2020-01-15",
|
|
320
328
|
"list-elements": "2015-07-29",
|
|
321
329
|
"list-style": "2015-07-29",
|
|
330
|
+
"loading-lazy": "2023-12-19",
|
|
322
331
|
"localstorage": "2015-07-29",
|
|
323
332
|
"location": "2015-07-29",
|
|
324
333
|
"logical-assignments": "2020-09-16",
|
|
@@ -328,6 +337,7 @@
|
|
|
328
337
|
"margin": "2015-07-29",
|
|
329
338
|
"mark": "2015-07-29",
|
|
330
339
|
"mask-type": "2020-01-15",
|
|
340
|
+
"masks": "2023-12-07",
|
|
331
341
|
"matchmedia": "2015-07-29",
|
|
332
342
|
"mathml": "2023-01-12",
|
|
333
343
|
"media-capabilities": "2022-04-28",
|
|
@@ -357,6 +367,7 @@
|
|
|
357
367
|
"nav": "2015-07-29",
|
|
358
368
|
"navigation-timing": "2021-10-25",
|
|
359
369
|
"navigator": "2015-07-29",
|
|
370
|
+
"nesting": "2023-12-11",
|
|
360
371
|
"not": "2021-01-21",
|
|
361
372
|
"notifications-apps": "2023-03-27",
|
|
362
373
|
"nth-child": "2015-07-29",
|
|
@@ -414,6 +425,8 @@
|
|
|
414
425
|
"prefers-color-scheme": "2020-01-15",
|
|
415
426
|
"prefers-contrast": "2022-05-31",
|
|
416
427
|
"prefers-reduced-motion": "2020-01-15",
|
|
428
|
+
"preloading-responsive-images": "2023-12-11",
|
|
429
|
+
"preserves-pitch": "2023-12-11",
|
|
417
430
|
"print": "2023-06-06",
|
|
418
431
|
"print-events": "2019-09-19",
|
|
419
432
|
"progress": "2015-07-29",
|
|
@@ -451,6 +464,7 @@
|
|
|
451
464
|
"screen": "2015-07-29",
|
|
452
465
|
"screen-orientation": "2023-03-27",
|
|
453
466
|
"script": "2015-07-29",
|
|
467
|
+
"scripting": "2023-12-07",
|
|
454
468
|
"scroll-behavior": "2022-03-14",
|
|
455
469
|
"scroll-elements": "2020-09-16",
|
|
456
470
|
"scroll-into-view": "2020-01-15",
|
|
@@ -558,6 +572,7 @@
|
|
|
558
572
|
"update": "2023-09-18",
|
|
559
573
|
"upgrade-insecure-requests": "2018-04-30",
|
|
560
574
|
"url": "2015-07-29",
|
|
575
|
+
"url-canparse": "2023-12-07",
|
|
561
576
|
"user-action-pseudos": "2015-07-29",
|
|
562
577
|
"user-activation": "2023-11-21",
|
|
563
578
|
"user-agent-sniffing": "2016-09-20",
|
|
@@ -638,8 +653,6 @@
|
|
|
638
653
|
"backdrop-filter": "2024-09-16",
|
|
639
654
|
"baseline-shift": "2026-03-24",
|
|
640
655
|
"canvas-2d-willreadfrequently": "2024-09-16",
|
|
641
|
-
"canvas-reset": "2023-12-11",
|
|
642
|
-
"cap": "2023-12-11",
|
|
643
656
|
"check-visibility": "2024-03-05",
|
|
644
657
|
"clipboard-supports": "2025-03-31",
|
|
645
658
|
"composed-ranges": "2025-08-19",
|
|
@@ -648,24 +661,20 @@
|
|
|
648
661
|
"contenteditable-plaintextonly": "2025-03-04",
|
|
649
662
|
"contrast-color": "2026-04-10",
|
|
650
663
|
"cookie-enabled": "2024-09-16",
|
|
651
|
-
"counter-set": "2023-12-11",
|
|
652
|
-
"createimagebitmap": "2023-12-11",
|
|
653
664
|
"crisp-edges": "2026-05-07",
|
|
654
665
|
"declarative-shadow-dom": "2024-02-20",
|
|
655
666
|
"details-content": "2025-09-16",
|
|
656
667
|
"details-name": "2024-09-03",
|
|
657
|
-
"dir-pseudo": "2023-12-07",
|
|
658
668
|
"document-caretpositionfrompoint": "2025-12-12",
|
|
659
669
|
"event-timing": "2025-12-12",
|
|
660
|
-
"exp-functions": "2023-12-07",
|
|
661
670
|
"fetch-priority": "2024-10-29",
|
|
671
|
+
"field-sizing": "2026-06-16",
|
|
662
672
|
"float16array": "2025-04-04",
|
|
663
673
|
"font-family-math": "2026-03-24",
|
|
664
674
|
"font-size-adjust": "2024-07-25",
|
|
665
675
|
"gethtml": "2024-09-16",
|
|
666
676
|
"getorinsert": "2026-02-14",
|
|
667
677
|
"gradient-interpolation": "2024-06-11",
|
|
668
|
-
"has": "2023-12-19",
|
|
669
678
|
"highlight": "2026-03-24",
|
|
670
679
|
"http3": "2024-09-16",
|
|
671
680
|
"input-file-webkitdirectory": "2025-08-19",
|
|
@@ -680,20 +689,14 @@
|
|
|
680
689
|
"json-raw": "2025-03-31",
|
|
681
690
|
"largest-contentful-paint": "2025-12-12",
|
|
682
691
|
"light-dark": "2024-05-13",
|
|
683
|
-
"linear-easing": "2023-12-11",
|
|
684
692
|
"link-rel-dns-prefetch": "2025-09-15",
|
|
685
|
-
"loading-lazy": "2023-12-19",
|
|
686
|
-
"masks": "2023-12-07",
|
|
687
693
|
"math-sum-precise": "2026-04-10",
|
|
688
694
|
"navigation": "2026-01-13",
|
|
689
|
-
"nesting": "2023-12-11",
|
|
690
695
|
"open-pseudo": "2026-05-11",
|
|
691
696
|
"page-setup": "2024-12-11",
|
|
692
697
|
"paint-order": "2024-03-22",
|
|
693
698
|
"parse-html-unsafe": "2025-09-15",
|
|
694
699
|
"popover": "2025-01-27",
|
|
695
|
-
"preloading-responsive-images": "2023-12-11",
|
|
696
|
-
"preserves-pitch": "2023-12-11",
|
|
697
700
|
"print-color-adjust": "2025-05-01",
|
|
698
701
|
"promise-try": "2025-01-07",
|
|
699
702
|
"promise-withresolvers": "2024-03-05",
|
|
@@ -716,7 +719,6 @@
|
|
|
716
719
|
"ruby-position": "2024-12-11",
|
|
717
720
|
"scope": "2025-12-12",
|
|
718
721
|
"screen-wake-lock": "2025-03-31",
|
|
719
|
-
"scripting": "2023-12-07",
|
|
720
722
|
"scroll-to-text-fragment": "2024-10-01",
|
|
721
723
|
"scrollbar-color": "2025-12-12",
|
|
722
724
|
"scrollbar-gutter": "2024-12-11",
|
|
@@ -740,7 +742,6 @@
|
|
|
740
742
|
"transition-behavior": "2024-08-06",
|
|
741
743
|
"trusted-types": "2026-02-24",
|
|
742
744
|
"uint8array-base64-hex": "2025-09-05",
|
|
743
|
-
"url-canparse": "2023-12-07",
|
|
744
745
|
"urlpattern": "2025-09-15",
|
|
745
746
|
"vertical-form-controls": "2024-04-18",
|
|
746
747
|
"view-transition-class": "2025-10-14",
|
|
@@ -767,6 +768,7 @@
|
|
|
767
768
|
"alternative-style-sheets",
|
|
768
769
|
"ambient-light",
|
|
769
770
|
"anchor-positioning",
|
|
771
|
+
"anchor-positioning-transforms",
|
|
770
772
|
"app-file-handlers",
|
|
771
773
|
"app-launch-handler",
|
|
772
774
|
"app-migration",
|
|
@@ -891,7 +893,6 @@
|
|
|
891
893
|
"fetch-metadata",
|
|
892
894
|
"fetch-request-streams",
|
|
893
895
|
"fetchlater",
|
|
894
|
-
"field-sizing",
|
|
895
896
|
"file-system-access",
|
|
896
897
|
"filter-function",
|
|
897
898
|
"fit-content-function",
|
|
@@ -919,6 +920,7 @@
|
|
|
919
920
|
"gyroscope",
|
|
920
921
|
"hanging-punctuation",
|
|
921
922
|
"has-slotted",
|
|
923
|
+
"heading-offset",
|
|
922
924
|
"heading-selectors",
|
|
923
925
|
"hidden-until-found",
|
|
924
926
|
"highlightsfrompoint",
|
|
@@ -980,6 +982,7 @@
|
|
|
980
982
|
"meta-application-title",
|
|
981
983
|
"meta-text-scale",
|
|
982
984
|
"meta-theme-color",
|
|
985
|
+
"mixin",
|
|
983
986
|
"move-before",
|
|
984
987
|
"mutation-events",
|
|
985
988
|
"navigation-precommit-handlers",
|
|
@@ -1069,6 +1072,7 @@
|
|
|
1069
1072
|
"selection",
|
|
1070
1073
|
"serial",
|
|
1071
1074
|
"serializable-errors",
|
|
1075
|
+
"service-workers-static-routes",
|
|
1072
1076
|
"share",
|
|
1073
1077
|
"shared-storage",
|
|
1074
1078
|
"shared-storage-locks",
|
|
@@ -1090,6 +1094,7 @@
|
|
|
1090
1094
|
"summarizer",
|
|
1091
1095
|
"supports-at-rule",
|
|
1092
1096
|
"svg-discouraged",
|
|
1097
|
+
"switch-control",
|
|
1093
1098
|
"table-discouraged",
|
|
1094
1099
|
"target-within",
|
|
1095
1100
|
"temporal",
|