lighthouse 9.5.0-dev.20220509 → 9.6.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/changelog.md +70 -0
- package/dist/report/bundle.esm.js +400 -808
- package/dist/report/flow.js +22 -27
- package/dist/report/standalone.js +18 -23
- package/flow-report/src/summary/category.tsx +1 -1
- package/jest.config.js +1 -1
- package/lighthouse-cli/.eslintrc.cjs +4 -3
- package/lighthouse-cli/bin.js +1 -0
- package/lighthouse-cli/cli-flags.js +4 -3
- package/lighthouse-cli/commands/commands.js +1 -0
- package/lighthouse-cli/commands/list-audits.js +1 -0
- package/lighthouse-cli/commands/list-locales.js +1 -0
- package/lighthouse-cli/commands/list-trace-categories.js +1 -0
- package/lighthouse-cli/index.js +1 -0
- package/lighthouse-cli/printer.js +1 -0
- package/lighthouse-cli/run.js +24 -9
- package/lighthouse-cli/sentry-prompt.js +1 -0
- package/lighthouse-cli/test/smokehouse/core-tests.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/lib.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -0
- package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -0
- package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -0
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +23 -109
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +3 -2
- package/lighthouse-cli/test/smokehouse/lighthouse-runners/devtools.js +19 -28
- package/lighthouse-cli/test/smokehouse/report-assert.js +4 -3
- package/lighthouse-cli/test/smokehouse/smokehouse.js +1 -1
- package/lighthouse-cli/test/smokehouse/version-check-test.js +3 -0
- package/lighthouse-cli/test/smokehouse/version-check.js +1 -0
- package/lighthouse-core/audits/accessibility/accesskeys.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-allowed-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-body.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-hidden-focus.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-input-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-children.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-required-parent.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-roles.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-toggle-field-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr-value.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-valid-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/button-name.js +1 -1
- package/lighthouse-core/audits/accessibility/bypass.js +1 -1
- package/lighthouse-core/audits/accessibility/color-contrast.js +1 -1
- package/lighthouse-core/audits/accessibility/definition-list.js +1 -1
- package/lighthouse-core/audits/accessibility/dlitem.js +1 -1
- package/lighthouse-core/audits/accessibility/document-title.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-active.js +1 -1
- package/lighthouse-core/audits/accessibility/duplicate-id-aria.js +1 -1
- package/lighthouse-core/audits/accessibility/form-field-multiple-labels.js +1 -1
- package/lighthouse-core/audits/accessibility/frame-title.js +1 -1
- package/lighthouse-core/audits/accessibility/heading-order.js +1 -1
- package/lighthouse-core/audits/accessibility/html-has-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/html-lang-valid.js +1 -1
- package/lighthouse-core/audits/accessibility/image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/input-image-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/label.js +1 -1
- package/lighthouse-core/audits/accessibility/link-name.js +1 -1
- package/lighthouse-core/audits/accessibility/list.js +1 -1
- package/lighthouse-core/audits/accessibility/listitem.js +5 -5
- package/lighthouse-core/audits/accessibility/meta-refresh.js +1 -1
- package/lighthouse-core/audits/accessibility/meta-viewport.js +1 -1
- package/lighthouse-core/audits/accessibility/object-alt.js +1 -1
- package/lighthouse-core/audits/accessibility/tabindex.js +1 -1
- package/lighthouse-core/audits/accessibility/td-headers-attr.js +1 -1
- package/lighthouse-core/audits/accessibility/th-has-data-cells.js +1 -1
- package/lighthouse-core/audits/accessibility/valid-lang.js +1 -1
- package/lighthouse-core/audits/accessibility/video-caption.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +12 -11
- package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +24 -22
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +3 -2
- package/lighthouse-core/audits/byte-efficiency/unminified-css.js +5 -3
- package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +11 -10
- package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -0
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +8 -11
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/lighthouse-core/audits/deprecations.js +598 -8
- package/lighthouse-core/audits/diagnostics.js +3 -4
- package/lighthouse-core/audits/dobetterweb/doctype.js +9 -20
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/no-document-write.js +1 -1
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +1 -1
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -2
- package/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
- package/lighthouse-core/audits/errors-in-console.js +2 -2
- package/lighthouse-core/audits/long-tasks.js +2 -3
- package/lighthouse-core/audits/metrics/experimental-interaction-to-next-paint.js +3 -1
- package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -2
- package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/interactive.js +2 -3
- package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -3
- package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -3
- package/lighthouse-core/audits/metrics/speed-index.js +2 -3
- package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -3
- package/lighthouse-core/audits/metrics.js +2 -3
- package/lighthouse-core/audits/no-unload-listeners.js +15 -7
- package/lighthouse-core/audits/predictive-perf.js +1 -2
- package/lighthouse-core/audits/preload-lcp-image.js +3 -3
- package/lighthouse-core/audits/redirects.js +1 -1
- package/lighthouse-core/audits/script-treemap-data.js +45 -45
- package/lighthouse-core/audits/seo/http-status-code.js +4 -2
- package/lighthouse-core/audits/seo/link-text.js +0 -2
- package/lighthouse-core/audits/server-response-time.js +17 -2
- package/lighthouse-core/audits/service-worker.js +2 -7
- package/lighthouse-core/audits/timing-budget.js +2 -3
- package/lighthouse-core/audits/uses-rel-preconnect.js +1 -1
- package/lighthouse-core/audits/uses-rel-preload.js +1 -1
- package/lighthouse-core/audits/valid-source-maps.js +14 -12
- package/lighthouse-core/audits/violation-audit.js +1 -1
- package/lighthouse-core/audits/work-during-interaction.js +280 -0
- package/lighthouse-core/computed/critical-request-chains.js +9 -5
- package/lighthouse-core/computed/js-bundles.js +11 -11
- package/lighthouse-core/computed/main-resource.js +2 -3
- package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-interactive.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-metric.js +5 -3
- package/lighthouse-core/computed/metrics/lantern-speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/lantern-total-blocking-time.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
- package/lighthouse-core/computed/metrics/largest-contentful-paint.js +1 -1
- package/lighthouse-core/computed/metrics/max-potential-fid.js +1 -1
- package/lighthouse-core/computed/metrics/metric.js +0 -1
- package/lighthouse-core/computed/metrics/responsiveness.js +12 -9
- package/lighthouse-core/computed/metrics/speed-index.js +1 -1
- package/lighthouse-core/computed/metrics/timing-summary.js +6 -13
- package/lighthouse-core/computed/metrics/total-blocking-time.js +1 -1
- package/lighthouse-core/computed/module-duplication.js +5 -6
- package/lighthouse-core/computed/page-dependency-graph.js +28 -55
- package/lighthouse-core/computed/resource-summary.js +5 -5
- package/lighthouse-core/computed/unused-css.js +7 -6
- package/lighthouse-core/computed/unused-javascript-summary.js +36 -16
- package/lighthouse-core/config/budget.js +2 -2
- package/lighthouse-core/config/default-config.js +1 -2
- package/lighthouse-core/config/metrics-to-audits.js +5 -0
- package/lighthouse-core/fraggle-rock/api.js +1 -1
- package/lighthouse-core/fraggle-rock/config/default-config.js +8 -5
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +3 -6
- package/lighthouse-core/fraggle-rock/gather/driver.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +26 -51
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
- package/lighthouse-core/fraggle-rock/gather/session.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -5
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +6 -6
- package/lighthouse-core/gather/connections/cri.js +0 -1
- package/lighthouse-core/gather/driver/execution-context.js +2 -4
- package/lighthouse-core/gather/driver/navigation.js +9 -9
- package/lighthouse-core/gather/driver/network-monitor.js +3 -16
- package/lighthouse-core/gather/driver.js +1 -6
- package/lighthouse-core/gather/fetcher.js +210 -34
- package/lighthouse-core/gather/gather-runner.js +17 -13
- package/lighthouse-core/gather/gatherers/accessibility.js +4 -16
- package/lighthouse-core/gather/gatherers/console-messages.js +2 -4
- package/lighthouse-core/gather/gatherers/dobetterweb/doctype.js +2 -4
- package/lighthouse-core/gather/gatherers/full-page-screenshot.js +2 -3
- package/lighthouse-core/gather/gatherers/js-usage.js +87 -12
- package/lighthouse-core/gather/gatherers/link-elements.js +14 -12
- package/lighthouse-core/gather/gatherers/main-document-content.js +8 -8
- package/lighthouse-core/gather/gatherers/script-elements.js +56 -7
- package/lighthouse-core/gather/gatherers/seo/robots-txt.js +30 -2
- package/lighthouse-core/gather/gatherers/source-maps.js +1 -3
- package/lighthouse-core/gather/gatherers/trace-elements.js +21 -2
- package/lighthouse-core/gather/gatherers/web-app-manifest.js +2 -2
- package/lighthouse-core/index.js +2 -26
- package/lighthouse-core/lib/cdt/generated/SourceMap.js +1 -1
- package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +29 -8
- package/lighthouse-core/lib/navigation-error.js +4 -13
- package/lighthouse-core/lib/script-helpers.js +6 -11
- package/lighthouse-core/lib/url-shim.js +2 -2
- package/lighthouse-core/runner.js +5 -0
- package/lighthouse-core/scripts/manual-chrome-launcher.js +1 -0
- package/lighthouse-core/util-commonjs.js +24 -28
- package/package.json +12 -12
- package/readme.md +1 -1
- package/report/.eslintrc.cjs +1 -3
- package/report/assets/styles.css +10 -12
- package/report/assets/templates.html +9 -10
- package/report/clients/bundle.js +1 -0
- package/report/clients/standalone.js +1 -0
- package/report/generator/report-generator.js +21 -46
- package/report/renderer/api.js +1 -0
- package/report/renderer/category-renderer.js +1 -0
- package/report/renderer/components.js +304 -303
- package/report/renderer/crc-details-renderer.js +1 -0
- package/report/renderer/details-renderer.js +10 -10
- package/report/renderer/dom.js +1 -0
- package/report/renderer/drop-down-menu.js +1 -0
- package/report/renderer/element-screenshot-renderer.js +4 -0
- package/report/renderer/features-util.js +1 -0
- package/report/renderer/i18n.js +62 -118
- package/report/renderer/logger.js +1 -0
- package/report/renderer/open-tab.js +3 -1
- package/report/renderer/performance-category-renderer.js +1 -0
- package/report/renderer/pwa-category-renderer.js +1 -0
- package/report/renderer/report-renderer.js +1 -0
- package/report/renderer/report-ui-features.js +1 -0
- package/report/renderer/snippet-renderer.js +1 -0
- package/report/renderer/swap-locale-feature.js +1 -0
- package/report/renderer/text-encoding.js +1 -0
- package/report/renderer/topbar-features.js +1 -0
- package/report/renderer/util.js +24 -27
- package/report/test/clients/bundle-test.js +4 -0
- package/report/test/generator/file-namer-test.js +1 -0
- package/report/test/generator/report-generator-test.js +20 -25
- package/report/test/renderer/category-renderer-test.js +3 -0
- package/report/test/renderer/components-test.js +3 -0
- package/report/test/renderer/crc-details-renderer-test.js +3 -0
- package/report/test/renderer/details-renderer-test.js +12 -58
- package/report/test/renderer/dom-test.js +3 -0
- package/report/test/renderer/element-screenshot-renderer-test.js +6 -3
- package/report/test/renderer/i18n-test.js +25 -70
- package/report/test/renderer/performance-category-renderer-test.js +4 -11
- package/report/test/renderer/pwa-category-renderer-test.js +3 -0
- package/report/test/renderer/report-renderer-axe-test.js +3 -0
- package/report/test/renderer/report-renderer-test.js +3 -0
- package/report/test/renderer/report-ui-features-test.js +3 -0
- package/report/test/renderer/snippet-renderer-test.js +3 -0
- package/report/test/renderer/text-encoding-test.js +3 -0
- package/report/test/renderer/util-test.js +5 -2
- package/report/test-assets/faux-psi.js +1 -2
- package/shared/localization/locales/en-US.json +260 -53
- package/shared/localization/locales/en-XL.json +260 -53
- package/shared/test/localization/format-test.js +2 -0
- package/shared/test/localization/locales-test.js +2 -0
- package/shared/test/localization/swap-locale-test.js +2 -0
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -0
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -0
- package/tsconfig.json +0 -1
- package/types/artifacts.d.ts +9 -48
- package/types/config.d.ts +0 -2
- package/types/externs.d.ts +2 -2
- package/types/gatherer.d.ts +2 -1
- package/types/global-lh.d.ts +0 -3
- package/types/lhr/audit-details.d.ts +3 -1
- package/types/lhr/lhr.d.ts +2 -2
- package/types/lhr/treemap.d.ts +1 -0
- package/lighthouse-core/audits/script-elements-test-audit.js +0 -30
- package/lighthouse-core/gather/gatherers/scripts.js +0 -154
- package/report/test/.eslintrc.cjs +0 -11
- package/shared/test/localization/.eslintrc.cjs +0 -11
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
const LinkHeader = require('http-link-header');
|
|
9
9
|
const FRGatherer = require('../../fraggle-rock/gather/base-gatherer.js');
|
|
10
10
|
const {URL} = require('../../lib/url-shim.js');
|
|
11
|
+
const NetworkRecords = require('../../computed/network-records.js');
|
|
12
|
+
const NetworkAnalyzer = require('../../lib/dependency-graph/simulator/network-analyzer.js');
|
|
11
13
|
const pageFunctions = require('../../lib/page-functions.js');
|
|
12
14
|
const DevtoolsLog = require('./devtools-log.js');
|
|
13
|
-
const MainResource = require('../../computed/main-resource.js');
|
|
14
15
|
|
|
15
16
|
/* globals HTMLLinkElement getNodeDetails */
|
|
16
17
|
|
|
@@ -113,12 +114,12 @@ class LinkElements extends FRGatherer {
|
|
|
113
114
|
|
|
114
115
|
/**
|
|
115
116
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
116
|
-
* @param {LH.Artifacts[
|
|
117
|
-
* @return {
|
|
117
|
+
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
118
|
+
* @return {LH.Artifacts['LinkElements']}
|
|
118
119
|
*/
|
|
119
|
-
static
|
|
120
|
-
const
|
|
121
|
-
|
|
120
|
+
static getLinkElementsInHeaders(context, networkRecords) {
|
|
121
|
+
const finalUrl = context.url;
|
|
122
|
+
const mainDocument = NetworkAnalyzer.findMainDocument(networkRecords, finalUrl);
|
|
122
123
|
|
|
123
124
|
/** @type {LH.Artifacts['LinkElements']} */
|
|
124
125
|
const linkElements = [];
|
|
@@ -129,7 +130,7 @@ class LinkElements extends FRGatherer {
|
|
|
129
130
|
for (const link of LinkHeader.parse(header.value).refs) {
|
|
130
131
|
linkElements.push({
|
|
131
132
|
rel: link.rel || '',
|
|
132
|
-
href: normalizeUrlOrNull(link.uri,
|
|
133
|
+
href: normalizeUrlOrNull(link.uri, finalUrl),
|
|
133
134
|
hrefRaw: link.uri || '',
|
|
134
135
|
hreflang: link.hreflang || '',
|
|
135
136
|
as: link.as || '',
|
|
@@ -145,12 +146,12 @@ class LinkElements extends FRGatherer {
|
|
|
145
146
|
|
|
146
147
|
/**
|
|
147
148
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
148
|
-
* @param {LH.Artifacts[
|
|
149
|
+
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
149
150
|
* @return {Promise<LH.Artifacts['LinkElements']>}
|
|
150
151
|
*/
|
|
151
|
-
async _getArtifact(context,
|
|
152
|
+
async _getArtifact(context, networkRecords) {
|
|
152
153
|
const fromDOM = await LinkElements.getLinkElementsInDOM(context);
|
|
153
|
-
const fromHeaders =
|
|
154
|
+
const fromHeaders = LinkElements.getLinkElementsInHeaders(context, networkRecords);
|
|
154
155
|
const linkElements = fromDOM.concat(fromHeaders);
|
|
155
156
|
|
|
156
157
|
for (const link of linkElements) {
|
|
@@ -167,7 +168,7 @@ class LinkElements extends FRGatherer {
|
|
|
167
168
|
* @return {Promise<LH.Artifacts['LinkElements']>}
|
|
168
169
|
*/
|
|
169
170
|
async afterPass(context, loadData) {
|
|
170
|
-
return this._getArtifact({...context, dependencies: {}}, loadData.
|
|
171
|
+
return this._getArtifact({...context, dependencies: {}}, loadData.networkRecords);
|
|
171
172
|
}
|
|
172
173
|
|
|
173
174
|
/**
|
|
@@ -175,7 +176,8 @@ class LinkElements extends FRGatherer {
|
|
|
175
176
|
* @return {Promise<LH.Artifacts['LinkElements']>}
|
|
176
177
|
*/
|
|
177
178
|
async getArtifact(context) {
|
|
178
|
-
|
|
179
|
+
const records = await NetworkRecords.request(context.dependencies.DevtoolsLog, context);
|
|
180
|
+
return this._getArtifact(context, records);
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const FRGatherer = require('../../fraggle-rock/gather/base-gatherer.js');
|
|
9
|
+
const NetworkAnalyzer = require('../../lib/dependency-graph/simulator/network-analyzer.js');
|
|
10
|
+
const NetworkRecords = require('../../computed/network-records.js');
|
|
9
11
|
const DevtoolsLog = require('./devtools-log.js');
|
|
10
12
|
const {fetchResponseBodyFromCache} = require('../driver/network.js');
|
|
11
|
-
const MainResource = require('../../computed/main-resource.js');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Collects the content of the main html document.
|
|
@@ -23,16 +24,14 @@ class MainDocumentContent extends FRGatherer {
|
|
|
23
24
|
/**
|
|
24
25
|
*
|
|
25
26
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
26
|
-
* @param {LH.Artifacts[
|
|
27
|
+
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
27
28
|
* @return {Promise<LH.Artifacts['MainDocumentContent']>}
|
|
28
29
|
*/
|
|
29
|
-
async _getArtifact(context,
|
|
30
|
-
const mainResource =
|
|
31
|
-
await MainResource.request({devtoolsLog, URL: context.baseArtifacts.URL}, context);
|
|
30
|
+
async _getArtifact(context, networkRecords) {
|
|
31
|
+
const mainResource = NetworkAnalyzer.findMainDocument(networkRecords, context.url);
|
|
32
32
|
const session = context.driver.defaultSession;
|
|
33
33
|
return fetchResponseBodyFromCache(session, mainResource.requestId);
|
|
34
34
|
}
|
|
35
|
-
|
|
36
35
|
/**
|
|
37
36
|
*
|
|
38
37
|
* @param {LH.Gatherer.FRTransitionalContext<'DevtoolsLog'>} context
|
|
@@ -40,7 +39,8 @@ class MainDocumentContent extends FRGatherer {
|
|
|
40
39
|
*/
|
|
41
40
|
async getArtifact(context) {
|
|
42
41
|
const devtoolsLog = context.dependencies.DevtoolsLog;
|
|
43
|
-
|
|
42
|
+
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
|
|
43
|
+
return this._getArtifact(context, networkRecords);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -49,7 +49,7 @@ class MainDocumentContent extends FRGatherer {
|
|
|
49
49
|
* @return {Promise<LH.Artifacts['MainDocumentContent']>}
|
|
50
50
|
*/
|
|
51
51
|
async afterPass(passContext, loadData) {
|
|
52
|
-
return this._getArtifact({...passContext, dependencies: {}}, loadData.
|
|
52
|
+
return this._getArtifact({...passContext, dependencies: {}}, loadData.networkRecords);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
const FRGatherer = require('../../fraggle-rock/gather/base-gatherer.js');
|
|
9
9
|
const NetworkRecords = require('../../computed/network-records.js');
|
|
10
|
+
const NetworkAnalyzer = require('../../lib/dependency-graph/simulator/network-analyzer.js');
|
|
10
11
|
const NetworkRequest = require('../../lib/network-request.js');
|
|
11
12
|
const pageFunctions = require('../../lib/page-functions.js');
|
|
13
|
+
const {fetchResponseBodyFromCache} = require('../driver/network.js');
|
|
12
14
|
const DevtoolsLog = require('./devtools-log.js');
|
|
13
15
|
|
|
14
16
|
/* global getNodeDetails */
|
|
@@ -30,6 +32,8 @@ function collectAllScriptElements() {
|
|
|
30
32
|
async: script.async,
|
|
31
33
|
defer: script.defer,
|
|
32
34
|
source: script.closest('head') ? 'head' : 'body',
|
|
35
|
+
content: script.src ? null : script.text,
|
|
36
|
+
requestId: null,
|
|
33
37
|
// @ts-expect-error - getNodeDetails put into scope via stringification
|
|
34
38
|
node: getNodeDetails(script),
|
|
35
39
|
};
|
|
@@ -37,6 +41,27 @@ function collectAllScriptElements() {
|
|
|
37
41
|
}
|
|
38
42
|
/* c8 ignore stop */
|
|
39
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @template T, U
|
|
46
|
+
* @param {Array<T>} values
|
|
47
|
+
* @param {(value: T) => Promise<U>} promiseMapper
|
|
48
|
+
* @param {boolean} runInSeries
|
|
49
|
+
* @return {Promise<Array<U>>}
|
|
50
|
+
*/
|
|
51
|
+
async function runInSeriesOrParallel(values, promiseMapper, runInSeries) {
|
|
52
|
+
if (runInSeries) {
|
|
53
|
+
const results = [];
|
|
54
|
+
for (const value of values) {
|
|
55
|
+
const result = await promiseMapper(value);
|
|
56
|
+
results.push(result);
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
} else {
|
|
60
|
+
const promises = values.map(promiseMapper);
|
|
61
|
+
return await Promise.all(promises);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
40
65
|
/**
|
|
41
66
|
* @fileoverview Gets JavaScript file contents.
|
|
42
67
|
*/
|
|
@@ -50,10 +75,13 @@ class ScriptElements extends FRGatherer {
|
|
|
50
75
|
/**
|
|
51
76
|
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
52
77
|
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
78
|
+
* @param {LH.Artifacts['HostFormFactor']} formFactor
|
|
53
79
|
* @return {Promise<LH.Artifacts['ScriptElements']>}
|
|
54
80
|
*/
|
|
55
|
-
async _getArtifact(context, networkRecords) {
|
|
81
|
+
async _getArtifact(context, networkRecords, formFactor) {
|
|
82
|
+
const session = context.driver.defaultSession;
|
|
56
83
|
const executionContext = context.driver.executionContext;
|
|
84
|
+
const mainResource = NetworkAnalyzer.findOptionalMainDocument(networkRecords, context.url);
|
|
57
85
|
|
|
58
86
|
const scripts = await executionContext.evaluate(collectAllScriptElements, {
|
|
59
87
|
args: [],
|
|
@@ -64,16 +92,34 @@ class ScriptElements extends FRGatherer {
|
|
|
64
92
|
],
|
|
65
93
|
});
|
|
66
94
|
|
|
95
|
+
for (const script of scripts) {
|
|
96
|
+
if (mainResource && script.content) script.requestId = mainResource.requestId;
|
|
97
|
+
}
|
|
98
|
+
|
|
67
99
|
const scriptRecords = networkRecords
|
|
68
|
-
.filter(record => record.resourceType === NetworkRequest.TYPES.Script)
|
|
69
100
|
// Ignore records from OOPIFs
|
|
70
|
-
.filter(record => !record.sessionId)
|
|
101
|
+
.filter(record => !record.sessionId)
|
|
102
|
+
// Only get the content of script requests
|
|
103
|
+
.filter(record => record.resourceType === NetworkRequest.TYPES.Script);
|
|
104
|
+
|
|
105
|
+
// If run on a mobile device, be sensitive to memory limitations and only request one
|
|
106
|
+
// record at a time.
|
|
107
|
+
const scriptRecordContents = await runInSeriesOrParallel(
|
|
108
|
+
scriptRecords,
|
|
109
|
+
record => fetchResponseBodyFromCache(session, record.requestId).catch(() => ''),
|
|
110
|
+
formFactor === 'mobile' /* runInSeries */
|
|
111
|
+
);
|
|
71
112
|
|
|
72
113
|
for (let i = 0; i < scriptRecords.length; i++) {
|
|
73
114
|
const record = scriptRecords[i];
|
|
115
|
+
const content = scriptRecordContents[i];
|
|
116
|
+
if (!content) continue;
|
|
74
117
|
|
|
75
118
|
const matchedScriptElement = scripts.find(script => script.src === record.url);
|
|
76
|
-
if (
|
|
119
|
+
if (matchedScriptElement) {
|
|
120
|
+
matchedScriptElement.requestId = record.requestId;
|
|
121
|
+
matchedScriptElement.content = content;
|
|
122
|
+
} else {
|
|
77
123
|
scripts.push({
|
|
78
124
|
type: null,
|
|
79
125
|
src: record.url,
|
|
@@ -81,11 +127,12 @@ class ScriptElements extends FRGatherer {
|
|
|
81
127
|
async: false,
|
|
82
128
|
defer: false,
|
|
83
129
|
source: 'network',
|
|
130
|
+
requestId: record.requestId,
|
|
131
|
+
content,
|
|
84
132
|
node: null,
|
|
85
133
|
});
|
|
86
134
|
}
|
|
87
135
|
}
|
|
88
|
-
|
|
89
136
|
return scripts;
|
|
90
137
|
}
|
|
91
138
|
|
|
@@ -94,8 +141,9 @@ class ScriptElements extends FRGatherer {
|
|
|
94
141
|
*/
|
|
95
142
|
async getArtifact(context) {
|
|
96
143
|
const devtoolsLog = context.dependencies.DevtoolsLog;
|
|
144
|
+
const formFactor = context.baseArtifacts.HostFormFactor;
|
|
97
145
|
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
|
|
98
|
-
return this._getArtifact(context, networkRecords);
|
|
146
|
+
return this._getArtifact(context, networkRecords, formFactor);
|
|
99
147
|
}
|
|
100
148
|
|
|
101
149
|
/**
|
|
@@ -104,7 +152,8 @@ class ScriptElements extends FRGatherer {
|
|
|
104
152
|
*/
|
|
105
153
|
async afterPass(passContext, loadData) {
|
|
106
154
|
const networkRecords = loadData.networkRecords;
|
|
107
|
-
|
|
155
|
+
const formFactor = passContext.baseArtifacts.HostFormFactor;
|
|
156
|
+
return this._getArtifact({...passContext, dependencies: {}}, networkRecords, formFactor);
|
|
108
157
|
}
|
|
109
158
|
}
|
|
110
159
|
|
|
@@ -7,6 +7,25 @@
|
|
|
7
7
|
|
|
8
8
|
const FRGatherer = require('../../../fraggle-rock/gather/base-gatherer.js');
|
|
9
9
|
|
|
10
|
+
/* global fetch, location */
|
|
11
|
+
|
|
12
|
+
/** @return {Promise<LH.Artifacts['RobotsTxt']>} */
|
|
13
|
+
/* c8 ignore start */
|
|
14
|
+
async function getRobotsTxtContent() {
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(new URL('/robots.txt', location.href).href);
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
return {status: response.status, content: null};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const content = await response.text();
|
|
22
|
+
return {status: response.status, content};
|
|
23
|
+
} catch (err) {
|
|
24
|
+
return {status: null, content: null, errorMessage: err.message};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/* c8 ignore stop */
|
|
28
|
+
|
|
10
29
|
class RobotsTxt extends FRGatherer {
|
|
11
30
|
/** @type {LH.Gatherer.GathererMeta} */
|
|
12
31
|
meta = {
|
|
@@ -18,8 +37,17 @@ class RobotsTxt extends FRGatherer {
|
|
|
18
37
|
* @return {Promise<LH.Artifacts['RobotsTxt']>}
|
|
19
38
|
*/
|
|
20
39
|
async getArtifact(passContext) {
|
|
21
|
-
|
|
22
|
-
|
|
40
|
+
// Iframe fetcher still has issues with CSPs.
|
|
41
|
+
// Only use the fetcher if we are fetching over the protocol.
|
|
42
|
+
if (await passContext.driver.fetcher.shouldUseLegacyFetcher()) {
|
|
43
|
+
return passContext.driver.executionContext.evaluate(getRobotsTxtContent, {
|
|
44
|
+
args: [],
|
|
45
|
+
useIsolation: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const robotsUrl = new URL('/robots.txt', passContext.url).href;
|
|
50
|
+
await passContext.driver.fetcher.enable();
|
|
23
51
|
return passContext.driver.fetcher.fetchResource(robotsUrl)
|
|
24
52
|
.catch(err => ({status: null, content: null, errorMessage: err.message}));
|
|
25
53
|
}
|
|
@@ -88,7 +88,6 @@ class SourceMaps extends FRGatherer {
|
|
|
88
88
|
|
|
89
89
|
if (!rawSourceMapUrl) {
|
|
90
90
|
return {
|
|
91
|
-
scriptId: event.scriptId,
|
|
92
91
|
scriptUrl,
|
|
93
92
|
errorMessage: `Could not resolve map url: ${event.sourceMapURL}`,
|
|
94
93
|
};
|
|
@@ -105,14 +104,12 @@ class SourceMaps extends FRGatherer {
|
|
|
105
104
|
map.sections = map.sections.filter(section => section.map);
|
|
106
105
|
}
|
|
107
106
|
return {
|
|
108
|
-
scriptId: event.scriptId,
|
|
109
107
|
scriptUrl,
|
|
110
108
|
sourceMapUrl,
|
|
111
109
|
map,
|
|
112
110
|
};
|
|
113
111
|
} catch (err) {
|
|
114
112
|
return {
|
|
115
|
-
scriptId: event.scriptId,
|
|
116
113
|
scriptUrl,
|
|
117
114
|
sourceMapUrl,
|
|
118
115
|
errorMessage: err.toString(),
|
|
@@ -143,6 +140,7 @@ class SourceMaps extends FRGatherer {
|
|
|
143
140
|
* @return {Promise<LH.Artifacts['SourceMaps']>}
|
|
144
141
|
*/
|
|
145
142
|
async getArtifact(context) {
|
|
143
|
+
await context.driver.fetcher.enable();
|
|
146
144
|
const eventProcessPromises = this._scriptParsedEvents
|
|
147
145
|
.map((event) => this._retrieveMapFromScriptParsedEvent(context.driver, event));
|
|
148
146
|
return Promise.all(eventProcessPromises);
|
|
@@ -22,6 +22,7 @@ const Trace = require('./trace.js');
|
|
|
22
22
|
const ProcessedTrace = require('../../computed/processed-trace.js');
|
|
23
23
|
const ProcessedNavigation = require('../../computed/processed-navigation.js');
|
|
24
24
|
const LighthouseError = require('../../lib/lh-error.js');
|
|
25
|
+
const ComputedResponsivenes = require('../../computed/metrics/responsiveness.js');
|
|
25
26
|
|
|
26
27
|
/** @typedef {{nodeId: number, score?: number, animations?: {name?: string, failureReasonsMask?: number, unsupportedProperties?: string[]}[]}} TraceElementData */
|
|
27
28
|
|
|
@@ -142,6 +143,23 @@ class TraceElements extends FRGatherer {
|
|
|
142
143
|
return topFive;
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
/**
|
|
147
|
+
* @param {LH.Trace} trace
|
|
148
|
+
* @param {LH.Gatherer.FRTransitionalContext} context
|
|
149
|
+
* @return {Promise<TraceElementData|undefined>}
|
|
150
|
+
*/
|
|
151
|
+
static async getResponsivenessElement(trace, context) {
|
|
152
|
+
const {settings} = context;
|
|
153
|
+
try {
|
|
154
|
+
const responsivenessEvent = await ComputedResponsivenes.request({trace, settings}, context);
|
|
155
|
+
if (!responsivenessEvent || responsivenessEvent.name === 'FallbackTiming') return;
|
|
156
|
+
return {nodeId: responsivenessEvent.args.data.nodeId};
|
|
157
|
+
} catch {
|
|
158
|
+
// Don't let responsiveness errors sink the rest of the gatherer.
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
145
163
|
/**
|
|
146
164
|
* Find the node ids of elements which are animated using the Animation trace events.
|
|
147
165
|
* @param {Array<LH.TraceEvent>} mainThreadEvents
|
|
@@ -237,14 +255,15 @@ class TraceElements extends FRGatherer {
|
|
|
237
255
|
|
|
238
256
|
const lcpNodeId = largestContentfulPaintEvt?.args?.data?.nodeId;
|
|
239
257
|
const clsNodeData = TraceElements.getTopLayoutShiftElements(mainThreadEvents);
|
|
240
|
-
const animatedElementData =
|
|
241
|
-
|
|
258
|
+
const animatedElementData = await this.getAnimatedElements(mainThreadEvents);
|
|
259
|
+
const responsivenessElementData = await TraceElements.getResponsivenessElement(trace, context);
|
|
242
260
|
|
|
243
261
|
/** @type {Map<string, TraceElementData[]>} */
|
|
244
262
|
const backendNodeDataMap = new Map([
|
|
245
263
|
['largest-contentful-paint', lcpNodeId ? [{nodeId: lcpNodeId}] : []],
|
|
246
264
|
['layout-shift', clsNodeData],
|
|
247
265
|
['animation', animatedElementData],
|
|
266
|
+
['responsiveness', responsivenessElementData ? [responsivenessElementData] : []],
|
|
248
267
|
]);
|
|
249
268
|
|
|
250
269
|
const traceElements = [];
|
|
@@ -94,8 +94,8 @@ class WebAppManifest extends FRGatherer {
|
|
|
94
94
|
*/
|
|
95
95
|
getArtifact(context) {
|
|
96
96
|
const driver = context.driver;
|
|
97
|
-
|
|
98
|
-
return WebAppManifest.getWebAppManifest(driver.defaultSession,
|
|
97
|
+
|
|
98
|
+
return WebAppManifest.getWebAppManifest(driver.defaultSession, context.url);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
package/lighthouse-core/index.js
CHANGED
|
@@ -10,7 +10,6 @@ const log = require('lighthouse-logger');
|
|
|
10
10
|
const ChromeProtocol = require('./gather/connections/cri.js');
|
|
11
11
|
const Config = require('./config/config.js');
|
|
12
12
|
const URL = require('./lib/url-shim.js');
|
|
13
|
-
const fraggleRock = require('./fraggle-rock/api.js');
|
|
14
13
|
|
|
15
14
|
/** @typedef {import('./gather/connections/connection.js')} Connection */
|
|
16
15
|
|
|
@@ -34,32 +33,10 @@ const fraggleRock = require('./fraggle-rock/api.js');
|
|
|
34
33
|
* they will override any settings in the config.
|
|
35
34
|
* @param {LH.Config.Json=} configJSON Configuration for the Lighthouse run. If
|
|
36
35
|
* not present, the default config is used.
|
|
37
|
-
* @param {LH.Puppeteer.Page=} page
|
|
38
|
-
* @return {Promise<LH.RunnerResult|undefined>}
|
|
39
|
-
*/
|
|
40
|
-
async function lighthouse(url, flags = {}, configJSON, page) {
|
|
41
|
-
const configContext = {
|
|
42
|
-
configPath: flags.configPath,
|
|
43
|
-
settingsOverrides: flags,
|
|
44
|
-
logLevel: flags.logLevel,
|
|
45
|
-
hostname: flags.hostname,
|
|
46
|
-
port: flags.port,
|
|
47
|
-
};
|
|
48
|
-
return fraggleRock.navigation(url, {page, config: configJSON, configContext});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Run Lighthouse using the legacy navigation runner.
|
|
53
|
-
* This is left in place for any clients that don't support FR navigations yet (e.g. Lightrider)
|
|
54
|
-
* @param {string=} url The URL to test. Optional if running in auditMode.
|
|
55
|
-
* @param {LH.Flags=} flags Optional settings for the Lighthouse run. If present,
|
|
56
|
-
* they will override any settings in the config.
|
|
57
|
-
* @param {LH.Config.Json=} configJSON Configuration for the Lighthouse run. If
|
|
58
|
-
* not present, the default config is used.
|
|
59
36
|
* @param {Connection=} userConnection
|
|
60
37
|
* @return {Promise<LH.RunnerResult|undefined>}
|
|
61
38
|
*/
|
|
62
|
-
async function
|
|
39
|
+
async function lighthouse(url, flags = {}, configJSON, userConnection) {
|
|
63
40
|
// set logging preferences, assume quiet
|
|
64
41
|
flags.logLevel = flags.logLevel || 'error';
|
|
65
42
|
log.setLevel(flags.logLevel);
|
|
@@ -89,12 +66,11 @@ function generateConfig(configJson, flags) {
|
|
|
89
66
|
return new Config(configJson, flags);
|
|
90
67
|
}
|
|
91
68
|
|
|
92
|
-
lighthouse.legacyNavigation = legacyNavigation;
|
|
93
69
|
lighthouse.generateConfig = generateConfig;
|
|
94
70
|
lighthouse.getAuditList = Runner.getAuditList;
|
|
95
71
|
lighthouse.traceCategories = require('./gather/driver.js').traceCategories;
|
|
96
72
|
lighthouse.Audit = require('./audits/audit.js');
|
|
97
|
-
lighthouse.Gatherer = require('./
|
|
73
|
+
lighthouse.Gatherer = require('./gather/gatherers/gatherer.js');
|
|
98
74
|
|
|
99
75
|
// Explicit type reference (hidden by makeComputedArtifact) for d.ts export.
|
|
100
76
|
// TODO(esmodules): should be a workaround for module.export and can be removed when in esm.
|
|
@@ -149,7 +149,7 @@ class TextSourceMap {
|
|
|
149
149
|
}
|
|
150
150
|
return mappings.slice(startIndex, endIndex);
|
|
151
151
|
}
|
|
152
|
-
/** @return {Array<{lineNumber: number, columnNumber: number, sourceURL?: string, sourceLineNumber
|
|
152
|
+
/** @return {Array<{lineNumber: number, columnNumber: number, sourceURL?: string, sourceLineNumber, sourceColumnNumber: number, name?: string, lastColumnNumber?: number}>} */
|
|
153
153
|
mappings() {
|
|
154
154
|
if (this.mappingsInternal === null) {
|
|
155
155
|
this.mappingsInternal = [];
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
8
|
const INITIAL_CWD = 14 * 1024;
|
|
9
|
+
const NetworkRequest = require('../../network-request.js');
|
|
9
10
|
const URL = require('../../url-shim.js');
|
|
10
11
|
|
|
11
12
|
// Assume that 40% of TTFB was server response time by default for static assets
|
|
@@ -433,20 +434,40 @@ class NetworkAnalyzer {
|
|
|
433
434
|
|
|
434
435
|
/**
|
|
435
436
|
* @param {Array<LH.Artifacts.NetworkRequest>} records
|
|
436
|
-
* @param {string}
|
|
437
|
+
* @param {string} [finalURL]
|
|
438
|
+
* @return {LH.Artifacts.NetworkRequest}
|
|
439
|
+
*/
|
|
440
|
+
static findMainDocument(records, finalURL) {
|
|
441
|
+
const mainDocument = NetworkAnalyzer.findOptionalMainDocument(records, finalURL);
|
|
442
|
+
if (!mainDocument) throw new Error('Unable to identify the main resource');
|
|
443
|
+
return mainDocument;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* @param {Array<LH.Artifacts.NetworkRequest>} records
|
|
448
|
+
* @param {string} [finalURL]
|
|
437
449
|
* @return {LH.Artifacts.NetworkRequest|undefined}
|
|
438
450
|
*/
|
|
439
|
-
static
|
|
440
|
-
//
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
451
|
+
static findOptionalMainDocument(records, finalURL) {
|
|
452
|
+
// Try to find an exact match with the final URL first if we have one
|
|
453
|
+
if (finalURL) {
|
|
454
|
+
// equalWithExcludedFragments is expensive, so check that the finalUrl starts with the request first
|
|
455
|
+
const mainResource = records.find(request => finalURL.startsWith(request.url) &&
|
|
456
|
+
URL.equalWithExcludedFragments(request.url, finalURL));
|
|
457
|
+
if (mainResource) return mainResource;
|
|
458
|
+
// TODO: beacon !mainResource to Sentry, https://github.com/GoogleChrome/lighthouse/issues/7041
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const documentRequests = records.filter(record => record.resourceType ===
|
|
462
|
+
NetworkRequest.TYPES.Document);
|
|
463
|
+
if (!documentRequests.length) return undefined;
|
|
464
|
+
// The main document is the earliest document request, using position in networkRecords array to break ties.
|
|
465
|
+
return documentRequests.reduce((min, r) => (r.startTime < min.startTime ? r : min));
|
|
445
466
|
}
|
|
446
467
|
|
|
447
468
|
/**
|
|
448
469
|
* Resolves redirect chain given a main document.
|
|
449
|
-
* See: {@link NetworkAnalyzer.
|
|
470
|
+
* See: {@link NetworkAnalyzer.findMainDocument}) for how to retrieve main document.
|
|
450
471
|
*
|
|
451
472
|
* @param {LH.Artifacts.NetworkRequest} request
|
|
452
473
|
* @return {LH.Artifacts.NetworkRequest}
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
const LHError = require('./lh-error.js');
|
|
9
9
|
const NetworkAnalyzer = require('./dependency-graph/simulator/network-analyzer.js');
|
|
10
|
-
const NetworkRequest = require('./network-request.js');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Returns an error if the original network request failed or wasn't found.
|
|
@@ -101,18 +100,10 @@ function getNonHtmlError(finalRecord) {
|
|
|
101
100
|
function getPageLoadError(navigationError, context) {
|
|
102
101
|
const {url, loadFailureMode, networkRecords} = context;
|
|
103
102
|
/** @type {LH.Artifacts.NetworkRequest|undefined} */
|
|
104
|
-
let mainRecord
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (!mainRecord) {
|
|
109
|
-
const documentRequests = networkRecords.filter(record =>
|
|
110
|
-
record.resourceType === NetworkRequest.TYPES.Document
|
|
111
|
-
);
|
|
112
|
-
if (documentRequests.length) {
|
|
113
|
-
mainRecord = documentRequests.reduce((min, r) => (r.startTime < min.startTime ? r : min));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
103
|
+
let mainRecord;
|
|
104
|
+
try {
|
|
105
|
+
mainRecord = NetworkAnalyzer.findMainDocument(networkRecords, url);
|
|
106
|
+
} catch (_) {}
|
|
116
107
|
|
|
117
108
|
// MIME Type is only set on the final redirected document request. Use this for the HTML check instead of root.
|
|
118
109
|
let finalRecord;
|
|
@@ -5,25 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* @param {LH.Artifacts.Script} script
|
|
10
|
-
* @return {boolean}
|
|
11
|
-
*/
|
|
12
|
-
function isInline(script) {
|
|
13
|
-
return Boolean(script.startLine || script.startColumn);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
8
|
/**
|
|
17
9
|
* @param {LH.Artifacts.NetworkRequest[]} networkRecords
|
|
18
|
-
* @param {LH.Artifacts.
|
|
10
|
+
* @param {LH.Artifacts.ScriptElement|undefined} script
|
|
19
11
|
* @return {LH.Artifacts.NetworkRequest|undefined}
|
|
20
12
|
*/
|
|
21
13
|
function getRequestForScript(networkRecords, script) {
|
|
22
|
-
|
|
14
|
+
if (!script) return;
|
|
15
|
+
let networkRequest = script.requestId &&
|
|
16
|
+
networkRecords.find(request => request.requestId === script.requestId);
|
|
17
|
+
if (!networkRequest) networkRequest = networkRecords.find(request => request.url === script.src);
|
|
23
18
|
while (networkRequest?.redirectDestination) {
|
|
24
19
|
networkRequest = networkRequest.redirectDestination;
|
|
25
20
|
}
|
|
26
21
|
return networkRequest;
|
|
27
22
|
}
|
|
28
23
|
|
|
29
|
-
module.exports = {getRequestForScript
|
|
24
|
+
module.exports = {getRequestForScript};
|
|
@@ -236,9 +236,9 @@ class URLShim extends URL {
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
if (url.protocol === 'data:') {
|
|
239
|
-
const match = url.pathname.match(
|
|
239
|
+
const match = url.pathname.match(/image\/(png|jpeg|svg\+xml|webp|gif|avif)(?=;)/);
|
|
240
240
|
if (!match) return undefined;
|
|
241
|
-
return match[
|
|
241
|
+
return match[0];
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
const match = url.pathname.toLowerCase().match(/\.(png|jpeg|jpg|svg|webp|gif|avif)$/);
|
|
@@ -158,6 +158,11 @@ class Runner {
|
|
|
158
158
|
// No browser required, just load the artifacts from disk.
|
|
159
159
|
const path = this._getDataSavePath(settings);
|
|
160
160
|
artifacts = assetSaver.loadArtifacts(path);
|
|
161
|
+
const requestedUrl = artifacts.URL.requestedUrl;
|
|
162
|
+
|
|
163
|
+
if (!requestedUrl) {
|
|
164
|
+
throw new Error('Cannot run audit mode on empty URL');
|
|
165
|
+
}
|
|
161
166
|
} else {
|
|
162
167
|
const runnerStatus = {msg: 'Gather phase', id: 'lh:runner:gather'};
|
|
163
168
|
log.time(runnerStatus, 'verbose');
|