lighthouse 8.3.0-dev.20210907 → 8.3.0
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/changelog.md +1 -1
- package/dist/report/standalone.js +196 -0
- package/jest.config.js +0 -4
- package/lighthouse-cli/cli-flags.js +6 -14
- package/lighthouse-cli/run.js +1 -1
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +3 -9
- package/lighthouse-cli/test/smokehouse/report-assert.js +16 -36
- package/lighthouse-core/audits/large-javascript-libraries.js +166 -0
- package/lighthouse-core/audits/seo/http-status-code.js +6 -2
- package/lighthouse-core/audits/viewport.js +1 -2
- package/lighthouse-core/config/config-helpers.js +75 -9
- package/lighthouse-core/config/config.js +50 -6
- package/lighthouse-core/config/constants.js +0 -1
- package/lighthouse-core/config/default-config.js +0 -3
- package/lighthouse-core/config/experimental-config.js +8 -0
- package/lighthouse-core/config/metrics-to-audits.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +4 -3
- package/lighthouse-core/fraggle-rock/config/default-config.js +1 -3
- package/lighthouse-core/fraggle-rock/config/validation.js +0 -201
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +8 -16
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +0 -4
- package/lighthouse-core/fraggle-rock/gather/session.js +5 -30
- package/lighthouse-core/gather/driver/navigation.js +6 -7
- package/lighthouse-core/gather/driver/wait-for-condition.js +0 -27
- package/lighthouse-core/gather/fetcher.js +7 -17
- package/lighthouse-core/gather/gather-runner.js +0 -1
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +6 -2
- package/lighthouse-core/gather/gatherers/seo/tap-targets.js +2 -2
- package/lighthouse-core/gather/gatherers/stacks.js +1 -1
- package/lighthouse-core/lib/asset-saver.js +2 -2
- package/lighthouse-core/lib/cdt/SDK.js +0 -1
- package/lighthouse-core/lib/csp-evaluator.js +4 -17
- package/{report/generator → lighthouse-core/lib}/file-namer.js +0 -0
- package/lighthouse-core/lib/i18n/README.md +1 -1
- package/lighthouse-core/lib/i18n/i18n.js +7 -7
- package/lighthouse-core/lib/i18n/locales/ar-XB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ar.json +18 -0
- package/lighthouse-core/lib/i18n/locales/bg.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ca.json +18 -0
- package/lighthouse-core/lib/i18n/locales/cs.json +18 -0
- package/lighthouse-core/lib/i18n/locales/da.json +18 -0
- package/lighthouse-core/lib/i18n/locales/de.json +18 -0
- package/lighthouse-core/lib/i18n/locales/el.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-GB.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-US.json +18 -18
- package/lighthouse-core/lib/i18n/locales/en-XA.json +18 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +18 -18
- package/lighthouse-core/lib/i18n/locales/es-419.json +18 -0
- package/lighthouse-core/lib/i18n/locales/es.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fil.json +18 -0
- package/lighthouse-core/lib/i18n/locales/fr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/he.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/hu.json +18 -0
- package/lighthouse-core/lib/i18n/locales/id.json +18 -0
- package/lighthouse-core/lib/i18n/locales/it.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ja.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ko.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/lv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/nl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/no.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt-PT.json +18 -0
- package/lighthouse-core/lib/i18n/locales/pt.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ro.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ru.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sl.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr-Latn.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/sv.json +18 -0
- package/lighthouse-core/lib/i18n/locales/ta.json +18 -0
- package/lighthouse-core/lib/i18n/locales/te.json +18 -0
- package/lighthouse-core/lib/i18n/locales/th.json +18 -0
- package/lighthouse-core/lib/i18n/locales/tr.json +18 -0
- package/lighthouse-core/lib/i18n/locales/uk.json +18 -0
- package/lighthouse-core/lib/i18n/locales/vi.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-HK.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh-TW.json +18 -0
- package/lighthouse-core/lib/i18n/locales/zh.json +18 -0
- package/lighthouse-core/lib/large-javascript-libraries/bundlephobia-database.json +62 -0
- package/lighthouse-core/lib/large-javascript-libraries/library-suggestions.js +20 -0
- package/lighthouse-core/lib/network-request.js +1 -3
- package/lighthouse-core/lib/traces/pwmetrics-events.js +2 -2
- package/lighthouse-core/lib/url-shim.js +1 -7
- package/lighthouse-core/runner.js +1 -4
- package/lighthouse-core/util-commonjs.js +2 -2
- package/now.json +1 -1
- package/package.json +13 -20
- package/report/README.md +2 -2
- package/report/assets/standalone-template.html +1 -0
- package/report/assets/styles.css +27 -23
- package/report/assets/templates.html +40 -37
- package/report/clients/bundle.js +0 -1
- package/report/{package.json → clients/package.json} +0 -0
- package/report/clients/psi.js +3 -13
- package/report/clients/standalone.js +1 -1
- package/report/{types/buffer.d.ts → clients/treemap.js} +13 -11
- package/report/renderer/category-renderer.js +2 -2
- package/report/renderer/components.js +48 -46
- package/report/renderer/crc-details-renderer.js +16 -16
- package/report/renderer/details-renderer.js +1 -1
- package/report/renderer/dom.js +0 -17
- package/report/renderer/element-screenshot-renderer.js +9 -9
- package/{flow-report/test/setup/global-setup.ts → report/renderer/file-namer.js} +2 -5
- package/report/renderer/logger.js +4 -4
- package/report/renderer/package.json +4 -0
- package/report/renderer/report-renderer.js +11 -4
- package/report/renderer/report-ui-features.js +656 -43
- package/report/renderer/text-encoding.js +1 -1
- package/report/renderer/util.js +2 -2
- package/report/{generator/report-assets.js → report-assets.js} +3 -9
- package/report/{generator/report-generator.js → report-generator.js} +9 -37
- package/report/test/clients/package.json +4 -0
- package/report/test/clients/psi-test.js +1 -3
- package/report/test/renderer/category-renderer-test.js +3 -8
- package/report/test/renderer/components-test.js +0 -35
- package/report/test/renderer/crc-details-renderer-test.js +4 -5
- package/report/test/renderer/details-renderer-test.js +1 -3
- package/report/test/renderer/dom-test.js +6 -8
- package/report/test/renderer/i18n-test.js +0 -1
- package/report/test/renderer/package.json +4 -0
- package/report/test/renderer/performance-category-renderer-test.js +27 -30
- package/report/test/renderer/pwa-category-renderer-test.js +1 -2
- package/report/test/renderer/report-renderer-test.js +0 -1
- package/report/test/renderer/report-ui-features-test.js +28 -20
- package/report/test/renderer/snippet-renderer-test.js +0 -1
- package/report/test/renderer/text-encoding-test.js +0 -2
- package/report/test/renderer/util-test.js +0 -1
- package/report/test/{generator/report-generator-test.js → report-generator-test.js} +7 -9
- package/third-party/chromium-synchronization/installability-errors-test.js +27 -28
- package/third-party/snyk/snapshot.json +0 -2
- package/tsconfig.json +5 -24
- package/types/artifacts.d.ts +18 -5
- package/types/{lhr/audit-details.d.ts → audit-details.d.ts} +3 -18
- package/types/audit.d.ts +58 -7
- package/types/{lhr/budget.d.ts → budget.d.ts} +0 -0
- package/types/bundle-phobia-cli/index.d.ts +40 -0
- package/types/config.d.ts +8 -3
- package/types/externs.d.ts +119 -5
- package/types/gatherer.d.ts +2 -3
- package/types/global-lh.d.ts +14 -16
- package/{report/types/report-result.d.ts → types/html-renderer.d.ts} +17 -8
- package/types/{lhr/i18n.d.ts → i18n.d.ts} +25 -2
- package/types/{lhr/lhr.d.ts → lhr.d.ts} +9 -41
- package/types/smokehouse.d.ts +3 -3
- package/types/{lhr/treemap.d.ts → treemap.d.ts} +3 -3
- package/flow-report/assets/standalone-flow-template.html +0 -38
- package/flow-report/assets/styles.css +0 -310
- package/flow-report/jest.config.js +0 -24
- package/flow-report/src/app.tsx +0 -40
- package/flow-report/src/common.tsx +0 -72
- package/flow-report/src/icons.tsx +0 -96
- package/flow-report/src/sidebar/flow.tsx +0 -72
- package/flow-report/src/sidebar/sidebar.tsx +0 -89
- package/flow-report/src/summary/summary.tsx +0 -178
- package/flow-report/src/util.ts +0 -160
- package/flow-report/src/wrappers/gauge.tsx +0 -40
- package/flow-report/src/wrappers/report-renderer.tsx +0 -46
- package/flow-report/src/wrappers/report.tsx +0 -71
- package/flow-report/standalone-flow.tsx +0 -23
- package/flow-report/test/app-test.tsx +0 -48
- package/flow-report/test/common-test.tsx +0 -131
- package/flow-report/test/setup/env-setup.ts +0 -25
- package/flow-report/test/sidebar/flow-test.tsx +0 -71
- package/flow-report/test/sidebar/sidebar-test.tsx +0 -53
- package/flow-report/test/summary/summary-test.tsx +0 -132
- package/flow-report/test/util-test.tsx +0 -109
- package/flow-report/tsconfig.json +0 -39
- package/flow-report/types/flow-report.d.ts +0 -27
- package/lighthouse-core/audits/lcp-lazy-loaded.js +0 -83
- package/report/.eslintrc.cjs +0 -33
- package/report/generator/README.md +0 -9
- package/report/generator/flow-report-assets.js +0 -20
- package/report/generator/package.json +0 -4
- package/report/generator/tsconfig.json +0 -28
- package/report/renderer/drop-down-menu.js +0 -215
- package/report/renderer/features-util.js +0 -26
- package/report/renderer/open-tab.js +0 -137
- package/report/renderer/topbar-features.js +0 -309
- package/report/test/generator/file-namer-test.js +0 -28
- package/report/test/generator/package.json +0 -4
- package/report/test-assets/faux-psi-template.html +0 -126
- package/report/test-assets/faux-psi.js +0 -92
- package/report/tsconfig.json +0 -39
- package/report/types/augment-dom.d.ts +0 -24
- package/report/types/html-renderer.d.ts +0 -28
- package/types/lhr/audit-result.d.ts +0 -59
- package/types/lhr/flow.d.ts +0 -16
- package/types/lhr/settings.d.ts +0 -105
- package/types/lhr/tsconfig.json +0 -24
- package/types/query-selector.d.ts +0 -36
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const Audit = require('../../audits/audit.js');
|
|
9
|
-
const BaseFRGatherer = require('../gather/base-gatherer.js');
|
|
10
|
-
const i18n = require('../../lib/i18n/i18n.js');
|
|
11
|
-
|
|
12
8
|
/**
|
|
13
9
|
* @param {LH.Config.GathererDefn | LH.Config.AnyFRGathererDefn} gathererDefn
|
|
14
10
|
* @return {gathererDefn is LH.Config.AnyFRGathererDefn}
|
|
@@ -38,177 +34,6 @@ function isValidArtifactDependency(dependent, dependency) {
|
|
|
38
34
|
return true;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
/**
|
|
42
|
-
* Throws an error if the provided object does not implement the required Fraggle Rock gatherer interface.
|
|
43
|
-
* @param {LH.Config.AnyFRGathererDefn} gathererDefn
|
|
44
|
-
*/
|
|
45
|
-
function assertValidFRGatherer(gathererDefn) {
|
|
46
|
-
const gatherer = gathererDefn.instance;
|
|
47
|
-
const gathererName = gatherer.name;
|
|
48
|
-
|
|
49
|
-
if (typeof gatherer.meta !== 'object') {
|
|
50
|
-
throw new Error(`${gathererName} gatherer did not provide a meta object.`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (gatherer.meta.supportedModes.length === 0) {
|
|
54
|
-
throw new Error(`${gathererName} gatherer did not support any gather modes.`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
typeof gatherer.getArtifact !== 'function' ||
|
|
59
|
-
gatherer.getArtifact === BaseFRGatherer.prototype.getArtifact
|
|
60
|
-
) {
|
|
61
|
-
throw new Error(`${gathererName} gatherer did not define a "getArtifact" method.`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Throws an error if the provided object does not implement the required navigations interface.
|
|
67
|
-
* @param {LH.Config.FRConfig['navigations']} navigationsDefn
|
|
68
|
-
* @return {{warnings: string[]}}
|
|
69
|
-
*/
|
|
70
|
-
function assertValidFRNavigations(navigationsDefn) {
|
|
71
|
-
if (!navigationsDefn || !navigationsDefn.length) return {warnings: []};
|
|
72
|
-
|
|
73
|
-
/** @type {string[]} */
|
|
74
|
-
const warnings = [];
|
|
75
|
-
|
|
76
|
-
// Assert that the first navigation has loadFailureMode fatal.
|
|
77
|
-
const firstNavigation = navigationsDefn[0];
|
|
78
|
-
if (firstNavigation.loadFailureMode !== 'fatal') {
|
|
79
|
-
const currentMode = firstNavigation.loadFailureMode;
|
|
80
|
-
const warning = [
|
|
81
|
-
`"${firstNavigation.id}" is the first navigation but had a failure mode of ${currentMode}.`,
|
|
82
|
-
`The first navigation will always be treated as loadFailureMode=fatal.`,
|
|
83
|
-
].join(' ');
|
|
84
|
-
|
|
85
|
-
warnings.push(warning);
|
|
86
|
-
firstNavigation.loadFailureMode = 'fatal';
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Assert that navigations have unique IDs.
|
|
90
|
-
const navigationIds = navigationsDefn.map(navigation => navigation.id);
|
|
91
|
-
const duplicateId = navigationIds.find(
|
|
92
|
-
(id, i) => navigationIds.slice(i + 1).some(other => id === other)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
if (duplicateId) {
|
|
96
|
-
throw new Error(`Navigation must have unique identifiers, but "${duplicateId}" was repeated.`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return {warnings};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Throws an error if the provided object does not implement the required properties of an audit
|
|
104
|
-
* definition.
|
|
105
|
-
* @param {LH.Config.AuditDefn} auditDefinition
|
|
106
|
-
*/
|
|
107
|
-
function assertValidAudit(auditDefinition) {
|
|
108
|
-
const {implementation, path: auditPath} = auditDefinition;
|
|
109
|
-
const auditName = auditPath ||
|
|
110
|
-
(implementation && implementation.meta && implementation.meta.id) ||
|
|
111
|
-
'Unknown audit';
|
|
112
|
-
|
|
113
|
-
if (typeof implementation.audit !== 'function' || implementation.audit === Audit.audit) {
|
|
114
|
-
throw new Error(`${auditName} has no audit() method.`);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (typeof implementation.meta.id !== 'string') {
|
|
118
|
-
throw new Error(`${auditName} has no meta.id property, or the property is not a string.`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (!i18n.isStringOrIcuMessage(implementation.meta.title)) {
|
|
122
|
-
throw new Error(`${auditName} has no meta.title property, or the property is not a string.`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// If it'll have a ✔ or ✖ displayed alongside the result, it should have failureTitle
|
|
126
|
-
if (
|
|
127
|
-
!i18n.isStringOrIcuMessage(implementation.meta.failureTitle) &&
|
|
128
|
-
implementation.meta.scoreDisplayMode === Audit.SCORING_MODES.BINARY
|
|
129
|
-
) {
|
|
130
|
-
throw new Error(`${auditName} has no meta.failureTitle and should.`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!i18n.isStringOrIcuMessage(implementation.meta.description)) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`${auditName} has no meta.description property, or the property is not a string.`
|
|
136
|
-
);
|
|
137
|
-
} else if (implementation.meta.description === '') {
|
|
138
|
-
throw new Error(
|
|
139
|
-
`${auditName} has an empty meta.description string. Please add a description for the UI.`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (!Array.isArray(implementation.meta.requiredArtifacts)) {
|
|
144
|
-
throw new Error(
|
|
145
|
-
`${auditName} has no meta.requiredArtifacts property, or the property is not an array.`
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* @param {LH.Config.FRConfig['categories']} categories
|
|
152
|
-
* @param {LH.Config.FRConfig['audits']} audits
|
|
153
|
-
* @param {LH.Config.FRConfig['groups']} groups
|
|
154
|
-
*/
|
|
155
|
-
function assertValidCategories(categories, audits, groups) {
|
|
156
|
-
if (!categories) {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** @type {Map<string, LH.Config.AuditDefn>} */
|
|
161
|
-
const auditsKeyedById = new Map((audits || []).map(audit => {
|
|
162
|
-
return [audit.implementation.meta.id, audit];
|
|
163
|
-
}));
|
|
164
|
-
|
|
165
|
-
Object.keys(categories).forEach(categoryId => {
|
|
166
|
-
categories[categoryId].auditRefs.forEach((auditRef, index) => {
|
|
167
|
-
if (!auditRef.id) {
|
|
168
|
-
throw new Error(`missing an audit id at ${categoryId}[${index}]`);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const audit = auditsKeyedById.get(auditRef.id);
|
|
172
|
-
if (!audit) {
|
|
173
|
-
throw new Error(`could not find ${auditRef.id} audit for category ${categoryId}`);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const auditImpl = audit.implementation;
|
|
177
|
-
const isManual = auditImpl.meta.scoreDisplayMode === 'manual';
|
|
178
|
-
if (categoryId === 'accessibility' && !auditRef.group && !isManual) {
|
|
179
|
-
throw new Error(`${auditRef.id} accessibility audit does not have a group`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (auditRef.weight > 0 && isManual) {
|
|
183
|
-
throw new Error(`${auditRef.id} is manual but has a positive weight`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (auditRef.group && (!groups || !groups[auditRef.group])) {
|
|
187
|
-
throw new Error(`${auditRef.id} references unknown group ${auditRef.group}`);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Validate the settings after they've been built.
|
|
195
|
-
* @param {LH.Config.Settings} settings
|
|
196
|
-
*/
|
|
197
|
-
function assertValidSettings(settings) {
|
|
198
|
-
if (!settings.formFactor) {
|
|
199
|
-
throw new Error(`\`settings.formFactor\` must be defined as 'mobile' or 'desktop'. See https://github.com/GoogleChrome/lighthouse/blob/master/docs/emulation.md`);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (!settings.screenEmulation.disabled) {
|
|
203
|
-
// formFactor doesn't control emulation. So we don't want a mismatch:
|
|
204
|
-
// Bad mismatch A: user wants mobile emulation but scoring is configured for desktop
|
|
205
|
-
// Bad mismtach B: user wants everything desktop and set formFactor, but accidentally not screenEmulation
|
|
206
|
-
if (settings.screenEmulation.mobile !== (settings.formFactor === 'mobile')) {
|
|
207
|
-
throw new Error(`Screen emulation mobile setting (${settings.screenEmulation.mobile}) does not match formFactor setting (${settings.formFactor}). See https://github.com/GoogleChrome/lighthouse/blob/master/docs/emulation.md`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
37
|
/**
|
|
213
38
|
* Asserts that artifacts are in a valid dependency order that can be computed.
|
|
214
39
|
*
|
|
@@ -230,26 +55,6 @@ function assertArtifactTopologicalOrder(navigations) {
|
|
|
230
55
|
}
|
|
231
56
|
}
|
|
232
57
|
|
|
233
|
-
/**
|
|
234
|
-
* @param {LH.Config.FRConfig} config
|
|
235
|
-
* @return {{warnings: string[]}}
|
|
236
|
-
*/
|
|
237
|
-
function assertValidConfig(config) {
|
|
238
|
-
const {warnings} = assertValidFRNavigations(config.navigations);
|
|
239
|
-
|
|
240
|
-
for (const artifactDefn of config.artifacts || []) {
|
|
241
|
-
assertValidFRGatherer(artifactDefn.gatherer);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
for (const auditDefn of config.audits || []) {
|
|
245
|
-
assertValidAudit(auditDefn);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
assertValidCategories(config.categories, config.audits, config.groups);
|
|
249
|
-
assertValidSettings(config.settings);
|
|
250
|
-
return {warnings};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
58
|
/**
|
|
254
59
|
* @param {string} artifactId
|
|
255
60
|
* @param {string} dependencyKey
|
|
@@ -283,13 +88,7 @@ function throwInvalidArtifactDependency(artifactId, dependencyKey) {
|
|
|
283
88
|
module.exports = {
|
|
284
89
|
isFRGathererDefn,
|
|
285
90
|
isValidArtifactDependency,
|
|
286
|
-
assertValidFRGatherer,
|
|
287
|
-
assertValidFRNavigations,
|
|
288
|
-
assertValidAudit,
|
|
289
|
-
assertValidCategories,
|
|
290
|
-
assertValidSettings,
|
|
291
91
|
assertArtifactTopologicalOrder,
|
|
292
|
-
assertValidConfig,
|
|
293
92
|
throwInvalidDependencyOrder,
|
|
294
93
|
throwInvalidArtifactDependency,
|
|
295
94
|
};
|
|
@@ -77,10 +77,6 @@ function finalizeArtifacts(baseArtifacts, gathererArtifacts) {
|
|
|
77
77
|
artifacts.Timing = log.getTimeEntries();
|
|
78
78
|
artifacts.LighthouseRunWarnings = deduplicateWarnings(warnings);
|
|
79
79
|
|
|
80
|
-
if (artifacts.PageLoadError && !artifacts.URL.finalUrl) {
|
|
81
|
-
artifacts.URL.finalUrl = artifacts.URL.requestedUrl;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
80
|
// Check that the runner remembered to mutate the special-case URL artifact.
|
|
85
81
|
if (!artifacts.URL.requestedUrl) throw new Error('Runner did not set requestedUrl');
|
|
86
82
|
if (!artifacts.URL.finalUrl) throw new Error('Runner did not set finalUrl');
|
|
@@ -88,7 +88,6 @@ async function _navigate(navigationContext) {
|
|
|
88
88
|
try {
|
|
89
89
|
const {finalUrl, warnings} = await gotoURL(driver, requestedUrl, {
|
|
90
90
|
...navigationContext.navigation,
|
|
91
|
-
debugNavigation: config.settings.debugNavigation,
|
|
92
91
|
maxWaitForFcp: config.settings.maxWaitForFcp,
|
|
93
92
|
maxWaitForLoad: config.settings.maxWaitForLoad,
|
|
94
93
|
waitUntil: navigationContext.navigation.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'],
|
|
@@ -105,9 +104,9 @@ async function _navigate(navigationContext) {
|
|
|
105
104
|
/**
|
|
106
105
|
* @param {NavigationContext} navigationContext
|
|
107
106
|
* @param {PhaseState} phaseState
|
|
108
|
-
* @return {Promise<
|
|
107
|
+
* @return {Promise<Array<LH.Artifacts.NetworkRequest> | undefined>}
|
|
109
108
|
*/
|
|
110
|
-
async function
|
|
109
|
+
async function _collectNetworkRecords(navigationContext, phaseState) {
|
|
111
110
|
const devtoolsLogArtifactDefn = phaseState.artifactDefinitions.find(
|
|
112
111
|
definition => definition.gatherer.instance.meta.symbol === DevtoolsLog.symbol
|
|
113
112
|
);
|
|
@@ -119,7 +118,7 @@ async function _collectNetworkData(navigationContext, phaseState) {
|
|
|
119
118
|
|
|
120
119
|
const devtoolsLog = await phaseState.artifactState.getArtifact[devtoolsLogArtifactId];
|
|
121
120
|
const records = await NetworkRecords.request(devtoolsLog, navigationContext);
|
|
122
|
-
return
|
|
121
|
+
return records;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
/**
|
|
@@ -137,12 +136,12 @@ async function _computeNavigationResult(
|
|
|
137
136
|
) {
|
|
138
137
|
const {navigationError, finalUrl} = navigateResult;
|
|
139
138
|
const warnings = [...setupResult.warnings, ...navigateResult.warnings];
|
|
140
|
-
const
|
|
141
|
-
const pageLoadError =
|
|
139
|
+
const networkRecords = await _collectNetworkRecords(navigationContext, phaseState);
|
|
140
|
+
const pageLoadError = networkRecords
|
|
142
141
|
? getPageLoadError(navigationError, {
|
|
143
142
|
url: finalUrl,
|
|
144
143
|
loadFailureMode: navigationContext.navigation.loadFailureMode,
|
|
145
|
-
networkRecords
|
|
144
|
+
networkRecords,
|
|
146
145
|
})
|
|
147
146
|
: navigationError;
|
|
148
147
|
|
|
@@ -151,15 +150,10 @@ async function _computeNavigationResult(
|
|
|
151
150
|
const localizedMessage = i18n.getFormatted(pageLoadError.friendlyMessage, locale);
|
|
152
151
|
log.error('NavigationRunner', localizedMessage, navigationContext.requestedUrl);
|
|
153
152
|
|
|
154
|
-
/** @type {Partial<LH.GathererArtifacts>} */
|
|
155
|
-
const artifacts = {};
|
|
156
|
-
const pageLoadErrorId = `pageLoadError-${navigationContext.navigation.id}`;
|
|
157
|
-
if (networkData) artifacts.devtoolsLogs = {[pageLoadErrorId]: networkData.devtoolsLog};
|
|
158
|
-
|
|
159
153
|
return {
|
|
160
154
|
finalUrl,
|
|
161
155
|
pageLoadError,
|
|
162
|
-
artifacts,
|
|
156
|
+
artifacts: {},
|
|
163
157
|
warnings: [...warnings, pageLoadError.friendlyMessage],
|
|
164
158
|
};
|
|
165
159
|
} else {
|
|
@@ -217,12 +211,11 @@ async function _navigations({driver, config, requestedUrl, computedCache}) {
|
|
|
217
211
|
computedCache,
|
|
218
212
|
};
|
|
219
213
|
|
|
220
|
-
let shouldHaltNavigations = false;
|
|
221
214
|
const navigationResult = await _navigation(navigationContext);
|
|
222
215
|
if (navigation.loadFailureMode === 'fatal') {
|
|
223
216
|
if (navigationResult.pageLoadError) {
|
|
224
217
|
artifacts.PageLoadError = navigationResult.pageLoadError;
|
|
225
|
-
|
|
218
|
+
break;
|
|
226
219
|
}
|
|
227
220
|
|
|
228
221
|
artifacts.URL = {requestedUrl, finalUrl: navigationResult.finalUrl};
|
|
@@ -230,7 +223,6 @@ async function _navigations({driver, config, requestedUrl, computedCache}) {
|
|
|
230
223
|
|
|
231
224
|
LighthouseRunWarnings.push(...navigationResult.warnings);
|
|
232
225
|
Object.assign(artifacts, navigationResult.artifacts);
|
|
233
|
-
if (shouldHaltNavigations) break;
|
|
234
226
|
}
|
|
235
227
|
|
|
236
228
|
return {artifacts: {...artifacts, LighthouseRunWarnings}};
|
|
@@ -22,8 +22,6 @@
|
|
|
22
22
|
|
|
23
23
|
/** @typedef {LH.Gatherer.FRTransitionalContext<LH.Gatherer.DependencyKey>['dependencies']} Dependencies */
|
|
24
24
|
|
|
25
|
-
const log = require('lighthouse-logger');
|
|
26
|
-
|
|
27
25
|
/**
|
|
28
26
|
*
|
|
29
27
|
* @param {{id: string}} dependency
|
|
@@ -77,8 +75,6 @@ async function collectPhaseArtifacts(options) {
|
|
|
77
75
|
const priorPhaseArtifacts = (priorPhase && artifactState[priorPhase]) || {};
|
|
78
76
|
|
|
79
77
|
for (const artifactDefn of artifactDefinitions) {
|
|
80
|
-
const logLevel = phase === 'getArtifact' ? 'log' : 'verbose';
|
|
81
|
-
log[logLevel](`artifacts:${phase}`, artifactDefn.id);
|
|
82
78
|
const gatherer = artifactDefn.gatherer.instance;
|
|
83
79
|
|
|
84
80
|
const priorArtifactPromise = priorPhaseArtifacts[artifactDefn.id] || Promise.resolve();
|
|
@@ -5,12 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const LHError = require('../../lib/lh-error.js');
|
|
9
8
|
const SessionEmitMonkeypatch = Symbol('monkeypatch');
|
|
10
9
|
|
|
11
|
-
// Controls how long to wait for a response after sending a DevTools protocol command.
|
|
12
|
-
const DEFAULT_PROTOCOL_TIMEOUT = 30000;
|
|
13
|
-
|
|
14
10
|
/** @implements {LH.Gatherer.FRProtocolSession} */
|
|
15
11
|
class ProtocolSession {
|
|
16
12
|
/**
|
|
@@ -18,8 +14,6 @@ class ProtocolSession {
|
|
|
18
14
|
*/
|
|
19
15
|
constructor(session) {
|
|
20
16
|
this._session = session;
|
|
21
|
-
/** @type {number|undefined} */
|
|
22
|
-
this._nextProtocolTimeout = undefined;
|
|
23
17
|
|
|
24
18
|
// FIXME: Monkeypatch puppeteer to be able to listen to *all* protocol events.
|
|
25
19
|
// This patched method will now emit a copy of every event on `*`.
|
|
@@ -38,21 +32,21 @@ class ProtocolSession {
|
|
|
38
32
|
* @return {boolean}
|
|
39
33
|
*/
|
|
40
34
|
hasNextProtocolTimeout() {
|
|
41
|
-
return
|
|
35
|
+
return false;
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
/**
|
|
45
39
|
* @return {number}
|
|
46
40
|
*/
|
|
47
41
|
getNextProtocolTimeout() {
|
|
48
|
-
return
|
|
42
|
+
return Number.MAX_SAFE_INTEGER;
|
|
49
43
|
}
|
|
50
44
|
|
|
51
45
|
/**
|
|
52
46
|
* @param {number} ms
|
|
53
47
|
*/
|
|
54
|
-
setNextProtocolTimeout(ms) {
|
|
55
|
-
|
|
48
|
+
setNextProtocolTimeout(ms) { // eslint-disable-line no-unused-vars
|
|
49
|
+
// TODO(FR-COMPAT): support protocol timeout
|
|
56
50
|
}
|
|
57
51
|
|
|
58
52
|
/**
|
|
@@ -108,26 +102,7 @@ class ProtocolSession {
|
|
|
108
102
|
* @return {Promise<LH.CrdpCommands[C]['returnType']>}
|
|
109
103
|
*/
|
|
110
104
|
sendCommand(method, ...params) {
|
|
111
|
-
|
|
112
|
-
this._nextProtocolTimeout = undefined;
|
|
113
|
-
|
|
114
|
-
/** @type {NodeJS.Timer|undefined} */
|
|
115
|
-
let timeout;
|
|
116
|
-
const timeoutPromise = new Promise((resolve, reject) => {
|
|
117
|
-
if (timeoutMs === Infinity) return;
|
|
118
|
-
|
|
119
|
-
timeout = setTimeout((() => {
|
|
120
|
-
const err = new LHError(LHError.errors.PROTOCOL_TIMEOUT, {protocolMethod: method});
|
|
121
|
-
reject(err);
|
|
122
|
-
}), timeoutMs);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const resultPromise = this._session.send(method, ...params);
|
|
126
|
-
const resultWithTimeoutPromise = Promise.race([resultPromise, timeoutPromise]);
|
|
127
|
-
|
|
128
|
-
return resultWithTimeoutPromise.finally(() => {
|
|
129
|
-
if (timeout) clearTimeout(timeout);
|
|
130
|
-
});
|
|
105
|
+
return this._session.send(method, ...params);
|
|
131
106
|
}
|
|
132
107
|
}
|
|
133
108
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const NetworkMonitor = require('./network-monitor.js');
|
|
9
|
-
const {waitForFullyLoaded, waitForFrameNavigated
|
|
9
|
+
const {waitForFullyLoaded, waitForFrameNavigated} = require('./wait-for-condition.js');
|
|
10
10
|
const constants = require('../../config/constants.js');
|
|
11
11
|
const i18n = require('../../lib/i18n/i18n.js');
|
|
12
12
|
const URL = require('../../lib/url-shim.js');
|
|
@@ -39,7 +39,7 @@ const DEFAULT_NETWORK_QUIET_THRESHOLD = 5000;
|
|
|
39
39
|
// Controls how long to wait between longtasks before determining the CPU is idle, off by default
|
|
40
40
|
const DEFAULT_CPU_QUIET_THRESHOLD = 0;
|
|
41
41
|
|
|
42
|
-
/** @typedef {{waitUntil: Array<'fcp'|'load'|'navigated'>} & LH.Config.SharedPassNavigationJson & Partial<Pick<LH.Config.Settings, 'maxWaitForFcp'|'maxWaitForLoad'
|
|
42
|
+
/** @typedef {{waitUntil: Array<'fcp'|'load'|'navigated'>} & LH.Config.SharedPassNavigationJson & Partial<Pick<LH.Config.Settings, 'maxWaitForFcp'|'maxWaitForLoad'>>} NavigationOptions */
|
|
43
43
|
|
|
44
44
|
/** @param {NavigationOptions} options */
|
|
45
45
|
function resolveWaitForFullyLoadedOptions(options) {
|
|
@@ -121,10 +121,6 @@ async function gotoURL(driver, url, options) {
|
|
|
121
121
|
await waitforPageNavigateCmd;
|
|
122
122
|
await networkMonitor.disable();
|
|
123
123
|
|
|
124
|
-
if (options.debugNavigation) {
|
|
125
|
-
await waitForUserToContinue(driver);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
124
|
return {
|
|
129
125
|
finalUrl,
|
|
130
126
|
warnings: getNavigationWarnings({timedOut, finalUrl, requestedUrl: url}),
|
|
@@ -142,7 +138,10 @@ function getNavigationWarnings(navigation) {
|
|
|
142
138
|
|
|
143
139
|
if (navigation.timedOut) warnings.push(str_(UIStrings.warningTimeout));
|
|
144
140
|
|
|
145
|
-
if (
|
|
141
|
+
if (
|
|
142
|
+
!URL.equalWithExcludedFragments(requestedUrl, finalUrl) &&
|
|
143
|
+
!finalUrl.startsWith('chrome-error://')
|
|
144
|
+
) {
|
|
146
145
|
warnings.push(str_(UIStrings.warningRedirected, {
|
|
147
146
|
requested: requestedUrl,
|
|
148
147
|
final: finalUrl,
|
|
@@ -490,32 +490,6 @@ async function waitForFullyLoaded(session, networkMonitor, options) {
|
|
|
490
490
|
return cleanupFn();
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
-
/**
|
|
494
|
-
* @param {LH.Gatherer.FRTransitionalDriver} driver
|
|
495
|
-
*/
|
|
496
|
-
function waitForUserToContinue(driver) {
|
|
497
|
-
/* c8 ignore start */
|
|
498
|
-
function createInPagePromise() {
|
|
499
|
-
let resolve = () => {};
|
|
500
|
-
/** @type {Promise<void>} */
|
|
501
|
-
const promise = new Promise(r => resolve = r);
|
|
502
|
-
|
|
503
|
-
// eslint-disable-next-line no-console
|
|
504
|
-
console.log([
|
|
505
|
-
`You have enabled Lighthouse navigation debug mode.`,
|
|
506
|
-
`When you have finished inspecting the page, evaluate "continueLighthouseRun()"`,
|
|
507
|
-
`in the console to continue with the Lighthouse run.`,
|
|
508
|
-
].join(' '));
|
|
509
|
-
|
|
510
|
-
window.continueLighthouseRun = resolve;
|
|
511
|
-
return promise;
|
|
512
|
-
}
|
|
513
|
-
/* c8 ignore stop */
|
|
514
|
-
|
|
515
|
-
driver.defaultSession.setNextProtocolTimeout(2 ** 31 - 1);
|
|
516
|
-
return driver.executionContext.evaluate(createInPagePromise, {args: []});
|
|
517
|
-
}
|
|
518
|
-
|
|
519
493
|
module.exports = {
|
|
520
494
|
waitForNothing,
|
|
521
495
|
waitForFrameNavigated,
|
|
@@ -524,5 +498,4 @@ module.exports = {
|
|
|
524
498
|
waitForNetworkIdle,
|
|
525
499
|
waitForCPUIdle,
|
|
526
500
|
waitForFullyLoaded,
|
|
527
|
-
waitForUserToContinue,
|
|
528
501
|
};
|
|
@@ -92,19 +92,6 @@ class Fetcher {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
/**
|
|
96
|
-
* `Network.loadNetworkResource` was introduced in M88.
|
|
97
|
-
* The long timeout bug with `IO.read` was fixed in M92:
|
|
98
|
-
* https://bugs.chromium.org/p/chromium/issues/detail?id=1191757
|
|
99
|
-
* Lightrider has a bug forcing us to use the old version for now:
|
|
100
|
-
* https://docs.google.com/document/d/1V-DxgsOFMPxUuFrdGPQpyiCqSljvgNlOqXCtqDtd0b8/edit?usp=sharing&resourcekey=0-aIaIqcHFKG-0dX4MAudBEw
|
|
101
|
-
* @return {Promise<boolean>}
|
|
102
|
-
*/
|
|
103
|
-
async shouldUseLegacyFetcher() {
|
|
104
|
-
const {milestone} = await getBrowserVersion(this.session);
|
|
105
|
-
return milestone < 92 || Boolean(global.isLightrider);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
95
|
/**
|
|
109
96
|
* Requires that `fetcher.enable` has been called.
|
|
110
97
|
*
|
|
@@ -119,11 +106,14 @@ class Fetcher {
|
|
|
119
106
|
throw new Error('Must call `enable` before using fetchResource');
|
|
120
107
|
}
|
|
121
108
|
|
|
122
|
-
|
|
123
|
-
|
|
109
|
+
// `Network.loadNetworkResource` was introduced in M88.
|
|
110
|
+
// The long timeout bug with `IO.read` was fixed in M92:
|
|
111
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1191757
|
|
112
|
+
const {milestone} = await getBrowserVersion(this.session);
|
|
113
|
+
if (milestone >= 92) {
|
|
114
|
+
return await this._fetchResourceOverProtocol(url, options);
|
|
124
115
|
}
|
|
125
|
-
|
|
126
|
-
return this._fetchResourceOverProtocol(url, options);
|
|
116
|
+
return await this._fetchResourceIframe(url, options);
|
|
127
117
|
}
|
|
128
118
|
|
|
129
119
|
/**
|
|
@@ -74,7 +74,6 @@ class GatherRunner {
|
|
|
74
74
|
const {finalUrl, warnings} = await navigation.gotoURL(driver, requestedUrl, {
|
|
75
75
|
waitUntil: passContext.passConfig.recordTrace ?
|
|
76
76
|
['load', 'fcp'] : ['load'],
|
|
77
|
-
debugNavigation: passContext.settings.debugNavigation,
|
|
78
77
|
maxWaitForFcp: passContext.settings.maxWaitForFcp,
|
|
79
78
|
maxWaitForLoad: passContext.settings.maxWaitForLoad,
|
|
80
79
|
...passContext.passConfig,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const FRGatherer = require('../../../fraggle-rock/gather/base-gatherer.js');
|
|
9
|
+
const {getBrowserVersion} = require('../../driver/environment.js');
|
|
9
10
|
|
|
10
11
|
/* global fetch, location */
|
|
11
12
|
|
|
@@ -37,9 +38,12 @@ class RobotsTxt extends FRGatherer {
|
|
|
37
38
|
* @return {Promise<LH.Artifacts['RobotsTxt']>}
|
|
38
39
|
*/
|
|
39
40
|
async getArtifact(passContext) {
|
|
41
|
+
const {milestone} = await getBrowserVersion(passContext.driver.defaultSession);
|
|
42
|
+
|
|
43
|
+
// TODO: Remove when 92 hits stable.
|
|
40
44
|
// Iframe fetcher still has issues with CSPs.
|
|
41
|
-
// Only use the fetcher if we are fetching over the
|
|
42
|
-
if (
|
|
45
|
+
// Only use the fetcher if we are fetching over the CDP.
|
|
46
|
+
if (milestone < 92) {
|
|
43
47
|
return passContext.driver.executionContext.evaluate(getRobotsTxtContent, {
|
|
44
48
|
args: [],
|
|
45
49
|
useIsolation: true,
|
|
@@ -205,7 +205,7 @@ function gatherTapTargets(tapTargetsSelector, className) {
|
|
|
205
205
|
|
|
206
206
|
/** @type {{
|
|
207
207
|
tapTargetElement: Element,
|
|
208
|
-
clientRects:
|
|
208
|
+
clientRects: ClientRect[]
|
|
209
209
|
}[]} */
|
|
210
210
|
const tapTargetsWithClientRects = [];
|
|
211
211
|
tapTargetElements.forEach(tapTargetElement => {
|
|
@@ -238,7 +238,7 @@ function gatherTapTargets(tapTargetsSelector, className) {
|
|
|
238
238
|
|
|
239
239
|
/** @type {{
|
|
240
240
|
tapTargetElement: Element,
|
|
241
|
-
visibleClientRects:
|
|
241
|
+
visibleClientRects: ClientRect[]
|
|
242
242
|
}[]} */
|
|
243
243
|
const tapTargetsWithVisibleClientRects = [];
|
|
244
244
|
// We use separate loop here to get visible client rects because that involves
|
|
@@ -120,7 +120,7 @@ class Stacks extends FRGatherer {
|
|
|
120
120
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
121
121
|
* @return {Promise<LH.Artifacts['Stacks']>}
|
|
122
122
|
*/
|
|
123
|
-
async
|
|
123
|
+
async snapshot(context) {
|
|
124
124
|
return Stacks.collectStacks(context.driver.executionContext);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
@@ -142,7 +142,7 @@ function saveLhr(lhr, basePath) {
|
|
|
142
142
|
/**
|
|
143
143
|
* Filter traces and extract screenshots to prepare for saving.
|
|
144
144
|
* @param {LH.Artifacts} artifacts
|
|
145
|
-
* @param {LH.
|
|
145
|
+
* @param {LH.Audit.Results} [audits]
|
|
146
146
|
* @return {Promise<Array<PreparedAssets>>}
|
|
147
147
|
*/
|
|
148
148
|
async function prepareAssets(artifacts, audits) {
|
|
@@ -272,7 +272,7 @@ async function saveLanternDebugTraces(pathWithBasename) {
|
|
|
272
272
|
/**
|
|
273
273
|
* Writes trace(s) and associated asset(s) to disk.
|
|
274
274
|
* @param {LH.Artifacts} artifacts
|
|
275
|
-
* @param {LH.
|
|
275
|
+
* @param {LH.Audit.Results} audits
|
|
276
276
|
* @param {string} pathWithBasename
|
|
277
277
|
* @return {Promise<void>}
|
|
278
278
|
*/
|
|
@@ -46,7 +46,6 @@ SDK.TextSourceMap.prototype.mappings = function() {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const originalReversedMappings = SDK.TextSourceMap.prototype._reversedMappings;
|
|
49
|
-
/** @param {string} sourceURL */
|
|
50
49
|
SDK.TextSourceMap.prototype._reversedMappings = function(sourceURL) {
|
|
51
50
|
const mappings = originalReversedMappings.call(this, sourceURL);
|
|
52
51
|
extendArray(mappings);
|
|
@@ -28,11 +28,12 @@ const UIStrings = {
|
|
|
28
28
|
missingScriptSrc: 'script-src directive is missing. ' +
|
|
29
29
|
'This can allow the execution of unsafe scripts.',
|
|
30
30
|
/** Message shown when a CSP does not have a script-src directive. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy". "object-src" and "'none'" do not need to be translated. */
|
|
31
|
-
missingObjectSrc: '
|
|
32
|
-
'
|
|
31
|
+
missingObjectSrc: 'Elements controlled by object-src are considered legacy features. ' +
|
|
32
|
+
'Consider setting object-src to \'none\' to prevent the injection of ' +
|
|
33
|
+
'plugins that execute unsafe scripts.',
|
|
33
34
|
/** Message shown when a CSP uses a domain allowlist to filter out malicious scripts. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy". "CSP", "'strict-dynamic'", "nonces", and "hashes" do not need to be translated. "allowlists" can be interpreted as "whitelist". */
|
|
34
35
|
strictDynamic: 'Host allowlists can frequently be bypassed. Consider using ' +
|
|
35
|
-
'
|
|
36
|
+
'\'strict-dynamic\' in combination with CSP nonces or hashes.',
|
|
36
37
|
/** Message shown when a CSP allows inline scripts to be run in the page. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy". "CSP", "'unsafe-inline'", "nonces", and "hashes" do not need to be translated. */
|
|
37
38
|
unsafeInline: '\'unsafe-inline\' allows the execution of unsafe in-page scripts ' +
|
|
38
39
|
'and event handlers. Consider using CSP nonces or hashes to allow scripts individually.',
|
|
@@ -75,18 +76,6 @@ const UIStrings = {
|
|
|
75
76
|
/** Message shown when a CSP uses the deprecated disown-opener directive. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy". "disown-opener", "CSP3" and "Cross-Origin-Opener-Policy" do not need to be translated. */
|
|
76
77
|
deprecatedDisownOpener: 'disown-opener is deprecated since CSP3. ' +
|
|
77
78
|
'Please, use the Cross-Origin-Opener-Policy header instead.',
|
|
78
|
-
/**
|
|
79
|
-
* @description Message shown when a CSP wildcard allows unsafe scripts to be run in the page. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy".
|
|
80
|
-
* @example {*} keyword
|
|
81
|
-
*/
|
|
82
|
-
plainWildcards: 'Avoid using plain wildcards ({keyword}) in this directive. ' +
|
|
83
|
-
'Plain wildcards allow scripts to be sourced from an unsafe domain.',
|
|
84
|
-
/**
|
|
85
|
-
* @description Message shown when a CSP URL scheme allows unsafe scripts to be run in the page. Shown in a table with a list of other CSP vulnerabilities and suggestions. "CSP" stands for "Content Security Policy".
|
|
86
|
-
* @example {https:} keyword
|
|
87
|
-
*/
|
|
88
|
-
plainUrlScheme: 'Avoid using plain URL schemes ({keyword}) in this directive. ' +
|
|
89
|
-
'Plain URL schemes allow scripts to be sourced from an unsafe domain.',
|
|
90
79
|
};
|
|
91
80
|
|
|
92
81
|
const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings);
|
|
@@ -102,8 +91,6 @@ const FINDING_TO_UI_STRING = {
|
|
|
102
91
|
[Directive.OBJECT_SRC]: str_(UIStrings.missingObjectSrc),
|
|
103
92
|
},
|
|
104
93
|
[Type.SCRIPT_UNSAFE_INLINE]: str_(UIStrings.unsafeInline),
|
|
105
|
-
[Type.PLAIN_WILDCARD]: UIStrings.plainWildcards,
|
|
106
|
-
[Type.PLAIN_URL_SCHEMES]: UIStrings.plainUrlScheme,
|
|
107
94
|
[Type.NONCE_LENGTH]: str_(UIStrings.nonceLength),
|
|
108
95
|
[Type.NONCE_CHARSET]: str_(UIStrings.nonceCharset),
|
|
109
96
|
[Type.DEPRECATED_DIRECTIVE]: {
|
|
File without changes
|