lighthouse 10.4.0 → 11.0.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/CONTRIBUTING.md +1 -1
- package/cli/cli-flags.d.ts +1 -6
- package/cli/cli-flags.js +0 -5
- package/cli/run.js +3 -10
- package/cli/sentry-prompt.js +4 -2
- package/cli/test/smokehouse/core-tests.js +0 -2
- package/cli/test/smokehouse/frontends/smokehouse-bin.js +24 -14
- package/cli/test/smokehouse/lighthouse-runners/bundle.d.ts +1 -2
- package/cli/test/smokehouse/lighthouse-runners/bundle.js +12 -21
- package/cli/test/smokehouse/lighthouse-runners/cli.d.ts +1 -3
- package/cli/test/smokehouse/lighthouse-runners/cli.js +3 -7
- package/cli/test/smokehouse/lighthouse-runners/devtools.d.ts +1 -5
- package/cli/test/smokehouse/lighthouse-runners/devtools.js +1 -12
- package/cli/test/smokehouse/readme.md +0 -2
- package/cli/test/smokehouse/report-assert.d.ts +1 -3
- package/cli/test/smokehouse/report-assert.js +2 -19
- package/cli/test/smokehouse/smokehouse.js +3 -32
- package/core/audits/accessibility/aria-allowed-role.d.ts +10 -0
- package/core/audits/accessibility/aria-allowed-role.js +46 -0
- package/core/audits/accessibility/image-redundant-alt.d.ts +10 -0
- package/core/audits/accessibility/image-redundant-alt.js +45 -0
- package/core/audits/accessibility/label-content-name-mismatch.d.ts +10 -0
- package/core/audits/accessibility/label-content-name-mismatch.js +44 -0
- package/core/audits/accessibility/skip-link.d.ts +10 -0
- package/core/audits/accessibility/skip-link.js +43 -0
- package/core/audits/accessibility/table-duplicate-name.d.ts +10 -0
- package/core/audits/accessibility/table-duplicate-name.js +44 -0
- package/core/audits/accessibility/target-size.js +1 -1
- package/core/audits/byte-efficiency/duplicated-javascript.js +2 -2
- package/core/audits/byte-efficiency/render-blocking-resources.js +1 -0
- package/core/audits/dobetterweb/uses-http2.d.ts +18 -1
- package/core/audits/dobetterweb/uses-http2.js +62 -16
- package/core/audits/installable-manifest.d.ts +1 -5
- package/core/audits/installable-manifest.js +2 -7
- package/core/audits/largest-contentful-paint-element.d.ts +0 -6
- package/core/audits/largest-contentful-paint-element.js +13 -15
- package/core/audits/metrics/{experimental-interaction-to-next-paint.d.ts → interaction-to-next-paint.d.ts} +3 -3
- package/core/audits/metrics/{experimental-interaction-to-next-paint.js → interaction-to-next-paint.js} +3 -3
- package/core/audits/uses-rel-preconnect.js +23 -8
- package/core/audits/work-during-interaction.js +2 -2
- package/core/computed/processed-navigation.d.ts +1 -1
- package/core/config/config-helpers.d.ts +3 -3
- package/core/config/config-helpers.js +5 -12
- package/core/config/config.js +1 -7
- package/core/config/constants.d.ts +0 -2
- package/core/config/constants.js +2 -18
- package/core/config/default-config.js +59 -53
- package/core/config/filters.js +1 -1
- package/core/config/validation.d.ts +7 -12
- package/core/config/validation.js +16 -26
- package/core/gather/base-artifacts.d.ts +4 -4
- package/core/gather/base-artifacts.js +2 -6
- package/core/gather/base-gatherer.d.ts +12 -37
- package/core/gather/base-gatherer.js +7 -54
- package/core/gather/driver/dom.d.ts +4 -4
- package/core/gather/driver/dom.js +2 -2
- package/core/gather/driver/environment.d.ts +4 -4
- package/core/gather/driver/environment.js +2 -2
- package/core/gather/driver/execution-context.d.ts +12 -3
- package/core/gather/driver/execution-context.js +34 -3
- package/core/gather/driver/navigation.d.ts +2 -2
- package/core/gather/driver/navigation.js +2 -5
- package/core/gather/driver/network-monitor.d.ts +7 -6
- package/core/gather/driver/network-monitor.js +4 -4
- package/core/gather/driver/network.d.ts +2 -2
- package/core/gather/driver/network.js +1 -1
- package/core/gather/driver/prepare.d.ts +10 -10
- package/core/gather/driver/prepare.js +10 -10
- package/core/gather/driver/service-workers.d.ts +4 -4
- package/core/gather/driver/service-workers.js +2 -2
- package/core/gather/driver/storage.d.ts +6 -6
- package/core/gather/driver/storage.js +3 -3
- package/core/gather/driver/target-manager.d.ts +6 -5
- package/core/gather/driver/target-manager.js +3 -3
- package/core/gather/driver/wait-for-condition.d.ts +14 -14
- package/core/gather/driver/wait-for-condition.js +8 -8
- package/core/gather/driver.d.ts +9 -6
- package/core/gather/driver.js +14 -4
- package/core/gather/fetcher.d.ts +3 -3
- package/core/gather/fetcher.js +1 -1
- package/core/gather/gatherers/accessibility.d.ts +4 -4
- package/core/gather/gatherers/accessibility.js +8 -3
- package/core/gather/gatherers/anchor-elements.d.ts +4 -4
- package/core/gather/gatherers/anchor-elements.js +4 -4
- package/core/gather/gatherers/bf-cache-failures.d.ts +8 -14
- package/core/gather/gatherers/bf-cache-failures.js +5 -14
- package/core/gather/gatherers/cache-contents.d.ts +4 -4
- package/core/gather/gatherers/cache-contents.js +3 -3
- package/core/gather/gatherers/console-messages.d.ts +6 -6
- package/core/gather/gatherers/console-messages.js +4 -4
- package/core/gather/gatherers/css-usage.d.ts +14 -14
- package/core/gather/gatherers/css-usage.js +9 -9
- package/core/gather/gatherers/devtools-log-compat.d.ts +5 -5
- package/core/gather/gatherers/devtools-log-compat.js +4 -4
- package/core/gather/gatherers/devtools-log.d.ts +6 -6
- package/core/gather/gatherers/devtools-log.js +4 -4
- package/core/gather/gatherers/dobetterweb/doctype.d.ts +4 -4
- package/core/gather/gatherers/dobetterweb/doctype.js +3 -3
- package/core/gather/gatherers/dobetterweb/domstats.d.ts +4 -4
- package/core/gather/gatherers/dobetterweb/domstats.js +3 -3
- package/core/gather/gatherers/dobetterweb/optimized-images.d.ts +10 -22
- package/core/gather/gatherers/dobetterweb/optimized-images.js +10 -27
- package/core/gather/gatherers/dobetterweb/response-compression.d.ts +6 -12
- package/core/gather/gatherers/dobetterweb/response-compression.js +14 -21
- package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +8 -14
- package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +5 -14
- package/core/gather/gatherers/full-page-screenshot.d.ts +10 -10
- package/core/gather/gatherers/full-page-screenshot.js +7 -10
- package/core/gather/gatherers/global-listeners.d.ts +4 -4
- package/core/gather/gatherers/global-listeners.js +3 -3
- package/core/gather/gatherers/iframe-elements.d.ts +4 -4
- package/core/gather/gatherers/iframe-elements.js +3 -3
- package/core/gather/gatherers/image-elements.d.ts +10 -10
- package/core/gather/gatherers/image-elements.js +6 -6
- package/core/gather/gatherers/inputs.d.ts +4 -4
- package/core/gather/gatherers/inputs.js +3 -3
- package/core/gather/gatherers/inspector-issues.d.ts +8 -19
- package/core/gather/gatherers/inspector-issues.js +9 -26
- package/core/gather/gatherers/installability-errors.d.ts +6 -6
- package/core/gather/gatherers/installability-errors.js +4 -4
- package/core/gather/gatherers/js-usage.d.ts +6 -6
- package/core/gather/gatherers/js-usage.js +4 -4
- package/core/gather/gatherers/link-elements.d.ts +8 -20
- package/core/gather/gatherers/link-elements.js +7 -24
- package/core/gather/gatherers/main-document-content.d.ts +4 -16
- package/core/gather/gatherers/main-document-content.js +5 -23
- package/core/gather/gatherers/meta-elements.d.ts +4 -4
- package/core/gather/gatherers/meta-elements.js +3 -3
- package/core/gather/gatherers/network-user-agent.d.ts +5 -5
- package/core/gather/gatherers/network-user-agent.js +4 -4
- package/core/gather/gatherers/script-elements.d.ts +6 -11
- package/core/gather/gatherers/script-elements.js +4 -13
- package/core/gather/gatherers/scripts.d.ts +7 -6
- package/core/gather/gatherers/scripts.js +7 -9
- package/core/gather/gatherers/seo/embedded-content.d.ts +4 -4
- package/core/gather/gatherers/seo/embedded-content.js +3 -3
- package/core/gather/gatherers/seo/font-size.d.ts +6 -6
- package/core/gather/gatherers/seo/font-size.js +5 -5
- package/core/gather/gatherers/seo/robots-txt.d.ts +4 -4
- package/core/gather/gatherers/seo/robots-txt.js +3 -3
- package/core/gather/gatherers/seo/tap-targets.d.ts +8 -8
- package/core/gather/gatherers/seo/tap-targets.js +5 -5
- package/core/gather/gatherers/service-worker.d.ts +4 -10
- package/core/gather/gatherers/service-worker.js +3 -15
- package/core/gather/gatherers/source-maps.d.ts +11 -23
- package/core/gather/gatherers/source-maps.js +22 -53
- package/core/gather/gatherers/stacks.d.ts +7 -7
- package/core/gather/gatherers/stacks.js +6 -6
- package/core/gather/gatherers/trace-compat.d.ts +5 -5
- package/core/gather/gatherers/trace-compat.js +4 -4
- package/core/gather/gatherers/trace-elements.d.ts +13 -25
- package/core/gather/gatherers/trace-elements.js +19 -32
- package/core/gather/gatherers/trace.d.ts +8 -8
- package/core/gather/gatherers/trace.js +5 -5
- package/core/gather/gatherers/viewport-dimensions.d.ts +4 -4
- package/core/gather/gatherers/viewport-dimensions.js +3 -3
- package/core/gather/gatherers/web-app-manifest.d.ts +8 -8
- package/core/gather/gatherers/web-app-manifest.js +5 -5
- package/core/gather/navigation-runner.d.ts +9 -9
- package/core/gather/navigation-runner.js +14 -8
- package/core/gather/runner-helpers.d.ts +3 -3
- package/core/gather/runner-helpers.js +12 -4
- package/core/gather/session.d.ts +2 -2
- package/core/gather/session.js +1 -1
- package/core/gather/snapshot-runner.d.ts +2 -2
- package/core/gather/snapshot-runner.js +1 -1
- package/core/gather/timespan-runner.d.ts +2 -2
- package/core/gather/timespan-runner.js +1 -1
- package/core/index.cjs +0 -7
- package/core/index.d.ts +0 -15
- package/core/index.js +2 -40
- package/core/lib/asset-saver.js +14 -4
- package/core/lib/axe.js +1 -1
- package/core/lib/dependency-graph/simulator/network-analyzer.d.ts +28 -12
- package/core/lib/dependency-graph/simulator/network-analyzer.js +128 -100
- package/core/lib/emulation.d.ts +14 -14
- package/core/lib/emulation.js +7 -7
- package/core/lib/navigation-error.js +5 -0
- package/core/lib/network-recorder.d.ts +2 -1
- package/core/lib/network-recorder.js +1 -0
- package/core/lib/network-request.js +12 -3
- package/core/lib/page-functions.d.ts +10 -2
- package/core/lib/page-functions.js +85 -8
- package/core/lib/sentry.js +9 -2
- package/core/lib/stack-packs.js +4 -0
- package/core/runner.d.ts +8 -30
- package/core/runner.js +8 -39
- package/core/user-flow.d.ts +4 -4
- package/core/user-flow.js +2 -2
- package/dist/report/bundle.esm.js +2221 -5832
- package/dist/report/flow.js +2631 -235
- package/dist/report/standalone.js +2586 -234
- package/flow-report/src/i18n/i18n.d.ts +2 -2
- package/package.json +17 -24
- package/readme.md +3 -1
- package/report/assets/templates.html +3 -1
- package/report/renderer/category-renderer.d.ts +3 -2
- package/report/renderer/category-renderer.js +8 -4
- package/report/renderer/components.js +11 -5
- package/report/renderer/pwa-category-renderer.js +1 -1
- package/report/renderer/report-ui-features.js +9 -6
- package/report/renderer/report-utils.d.ts +1 -1
- package/report/renderer/report-utils.js +2 -2
- package/report/renderer/topbar-features.js +3 -0
- package/shared/localization/locales/ar-XB.json +185 -44
- package/shared/localization/locales/ar.json +185 -44
- package/shared/localization/locales/bg.json +185 -44
- package/shared/localization/locales/ca.json +190 -49
- package/shared/localization/locales/cs.json +185 -44
- package/shared/localization/locales/da.json +185 -44
- package/shared/localization/locales/de.json +185 -44
- package/shared/localization/locales/el.json +185 -44
- package/shared/localization/locales/en-GB.json +185 -44
- package/shared/localization/locales/en-US.json +99 -45
- package/shared/localization/locales/en-XA.json +185 -44
- package/shared/localization/locales/en-XL.json +99 -45
- package/shared/localization/locales/es-419.json +185 -44
- package/shared/localization/locales/es.json +185 -44
- package/shared/localization/locales/fi.json +185 -44
- package/shared/localization/locales/fil.json +185 -44
- package/shared/localization/locales/fr.json +185 -44
- package/shared/localization/locales/he.json +186 -45
- package/shared/localization/locales/hi.json +185 -44
- package/shared/localization/locales/hr.json +185 -44
- package/shared/localization/locales/hu.json +185 -44
- package/shared/localization/locales/id.json +185 -44
- package/shared/localization/locales/it.json +185 -44
- package/shared/localization/locales/ja.json +185 -44
- package/shared/localization/locales/ko.json +185 -44
- package/shared/localization/locales/lt.json +185 -44
- package/shared/localization/locales/lv.json +185 -44
- package/shared/localization/locales/nl.json +185 -44
- package/shared/localization/locales/no.json +185 -44
- package/shared/localization/locales/pl.json +185 -44
- package/shared/localization/locales/pt-PT.json +185 -44
- package/shared/localization/locales/pt.json +190 -49
- package/shared/localization/locales/ro.json +185 -44
- package/shared/localization/locales/ru.json +185 -44
- package/shared/localization/locales/sk.json +185 -44
- package/shared/localization/locales/sl.json +185 -44
- package/shared/localization/locales/sr-Latn.json +185 -44
- package/shared/localization/locales/sr.json +185 -44
- package/shared/localization/locales/sv.json +185 -44
- package/shared/localization/locales/ta.json +185 -44
- package/shared/localization/locales/te.json +185 -44
- package/shared/localization/locales/th.json +185 -44
- package/shared/localization/locales/tr.json +185 -44
- package/shared/localization/locales/uk.json +185 -44
- package/shared/localization/locales/vi.json +185 -44
- package/shared/localization/locales/zh-HK.json +185 -44
- package/shared/localization/locales/zh-TW.json +185 -44
- package/shared/localization/locales/zh.json +185 -44
- package/third-party/esbuild-plugins-polyfills/LICENSE +3 -0
- package/third-party/esbuild-plugins-polyfills/README.md +7 -0
- package/third-party/esbuild-plugins-polyfills/esbuild-polyfills.d.ts +9 -0
- package/third-party/esbuild-plugins-polyfills/esbuild-polyfills.js +129 -0
- package/tsconfig.json +2 -1
- package/types/artifacts.d.ts +16 -45
- package/types/config.d.ts +10 -52
- package/types/externs.d.ts +0 -2
- package/types/gatherer.d.ts +24 -47
- package/types/internal/rxjs.d.ts +26 -0
- package/types/internal/smokehouse.d.ts +1 -3
- package/types/lh.d.ts +0 -2
- package/types/lhr/settings.d.ts +1 -1
- package/core/audits/metrics/first-contentful-paint-3g.d.ts +0 -15
- package/core/audits/metrics/first-contentful-paint-3g.js +0 -69
- package/core/audits/resource-summary.d.ts +0 -16
- package/core/audits/resource-summary.js +0 -104
- package/core/audits/service-worker.d.ts +0 -46
- package/core/audits/service-worker.js +0 -182
- package/core/gather/gatherers/gatherer.d.ts +0 -46
- package/core/gather/gatherers/gatherer.js +0 -58
- package/core/legacy/config/config.d.ts +0 -107
- package/core/legacy/config/config.js +0 -566
- package/core/legacy/config/legacy-default-config.d.ts +0 -4
- package/core/legacy/config/legacy-default-config.js +0 -87
- package/core/legacy/gather/connections/connection.d.ts +0 -77
- package/core/legacy/gather/connections/connection.js +0 -196
- package/core/legacy/gather/connections/cri.d.ts +0 -27
- package/core/legacy/gather/connections/cri.js +0 -162
- package/core/legacy/gather/connections/raw.d.ts +0 -20
- package/core/legacy/gather/connections/raw.js +0 -57
- package/core/legacy/gather/driver.d.ts +0 -216
- package/core/legacy/gather/driver.js +0 -480
- package/core/legacy/gather/gather-runner.d.ts +0 -166
- package/core/legacy/gather/gather-runner.js +0 -590
- package/types/internal/lighthouse-logger.d.ts +0 -34
|
@@ -95,6 +95,9 @@ function getNonHtmlError(finalRecord) {
|
|
|
95
95
|
// If we never requested a document, there's no doctype error, let other cases handle it.
|
|
96
96
|
if (!finalRecord) return undefined;
|
|
97
97
|
|
|
98
|
+
// If the document request error'd, we should not complain about a bad mimeType.
|
|
99
|
+
if (!finalRecord.mimeType || finalRecord.statusCode === -1) return undefined;
|
|
100
|
+
|
|
98
101
|
// mimeType is determined by the browser, we assume Chrome is determining mimeType correctly,
|
|
99
102
|
// independently of 'Content-Type' response headers, and always sending mimeType if well-formed.
|
|
100
103
|
if (finalRecord.mimeType !== HTML_MIME_TYPE && finalRecord.mimeType !== XHTML_MIME_TYPE) {
|
|
@@ -163,6 +166,8 @@ function getPageLoadError(navigationError, context) {
|
|
|
163
166
|
// Navigation errors are rather generic and express some failure of the page to render properly.
|
|
164
167
|
// Use `navigationError` as the last resort.
|
|
165
168
|
// Example: `NO_FCP`, the page never painted content for some unknown reason.
|
|
169
|
+
// Note that the caller possibly gave this to us as undefined, in which case we have determined
|
|
170
|
+
// there to be no error with this page load - but there was perhaps a warning.
|
|
166
171
|
return navigationError;
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -17,7 +17,7 @@ export class NetworkRecorder extends NetworkRecorder_base {
|
|
|
17
17
|
* @param {LH.DevtoolsLog} devtoolsLog
|
|
18
18
|
* @return {Array<LH.Artifacts.NetworkRequest>}
|
|
19
19
|
*/
|
|
20
|
-
static recordsFromLogs(devtoolsLog:
|
|
20
|
+
static recordsFromLogs(devtoolsLog: LH.DevtoolsLog): Array<LH.Artifacts.NetworkRequest>;
|
|
21
21
|
/** @type {NetworkRequest[]} */
|
|
22
22
|
_records: NetworkRequest[];
|
|
23
23
|
/** @type {Map<string, NetworkRequest>} */
|
|
@@ -117,5 +117,6 @@ export class NetworkRecorder extends NetworkRecorder_base {
|
|
|
117
117
|
_findRealRequestAndSetSession(requestId: string, targetType: LH.Protocol.TargetType, sessionId: string | undefined): NetworkRequest | undefined;
|
|
118
118
|
}
|
|
119
119
|
import { NetworkRequest } from './network-request.js';
|
|
120
|
+
import * as LH from '../../types/lh.js';
|
|
120
121
|
export {};
|
|
121
122
|
//# sourceMappingURL=network-recorder.d.ts.map
|
|
@@ -489,7 +489,7 @@ class NetworkRequest {
|
|
|
489
489
|
// Bail if there was no totalTime.
|
|
490
490
|
if (!totalHeader) return;
|
|
491
491
|
|
|
492
|
-
|
|
492
|
+
let totalMs = parseInt(totalHeader.value);
|
|
493
493
|
const TCPMsHeader = this.responseHeaders.find(item => item.name === HEADER_TCP);
|
|
494
494
|
const SSLMsHeader = this.responseHeaders.find(item => item.name === HEADER_SSL);
|
|
495
495
|
const requestMsHeader = this.responseHeaders.find(item => item.name === HEADER_REQ);
|
|
@@ -502,11 +502,20 @@ class NetworkRequest {
|
|
|
502
502
|
const requestMs = requestMsHeader ? Math.max(0, parseInt(requestMsHeader.value)) : 0;
|
|
503
503
|
const responseMs = responseMsHeader ? Math.max(0, parseInt(responseMsHeader.value)) : 0;
|
|
504
504
|
|
|
505
|
-
|
|
506
|
-
if (TCPMs + requestMs + responseMs !== totalMs) {
|
|
505
|
+
if (Number.isNaN(TCPMs + requestMs + responseMs + totalMs)) {
|
|
507
506
|
return;
|
|
508
507
|
}
|
|
509
508
|
|
|
509
|
+
// If things don't add up, tweak the total a bit.
|
|
510
|
+
if (TCPMs + requestMs + responseMs !== totalMs) {
|
|
511
|
+
const delta = Math.abs(TCPMs + requestMs + responseMs - totalMs);
|
|
512
|
+
// We didn't see total being more than 5ms less than the total of the components.
|
|
513
|
+
// Allow some discrepancy in the timing, but not too much.
|
|
514
|
+
if (delta >= 25) return;
|
|
515
|
+
|
|
516
|
+
totalMs = TCPMs + requestMs + responseMs;
|
|
517
|
+
}
|
|
518
|
+
|
|
510
519
|
// Bail if SSL time is > TCP time.
|
|
511
520
|
if (SSLMs > TCPMs) {
|
|
512
521
|
return;
|
|
@@ -11,6 +11,8 @@ export namespace pageFunctions {
|
|
|
11
11
|
export { wrapRequestIdleCallback };
|
|
12
12
|
export { getBoundingClientRect };
|
|
13
13
|
export { truncate };
|
|
14
|
+
export { esbuildFunctionWrapperString };
|
|
15
|
+
export { getRuntimeFunctionName };
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* `typed-query-selector`'s CSS selector parser.
|
|
@@ -49,11 +51,11 @@ declare function wrapRuntimeEvalErrorInBrowser(err?: string | Error | undefined)
|
|
|
49
51
|
};
|
|
50
52
|
/**
|
|
51
53
|
* @template {string} T
|
|
52
|
-
* @param {T} selector Optional simple CSS selector to filter nodes on.
|
|
54
|
+
* @param {T=} selector Optional simple CSS selector to filter nodes on.
|
|
53
55
|
* Combinators are not supported.
|
|
54
56
|
* @return {Array<ParseSelector<T>>}
|
|
55
57
|
*/
|
|
56
|
-
declare function getElementsInDocument<T extends string>(selector
|
|
58
|
+
declare function getElementsInDocument<T extends string>(selector?: T | undefined): import("typed-query-selector/parser").ParseSelector<T, Element>[];
|
|
57
59
|
/**
|
|
58
60
|
* Gets the opening tag text of the given node.
|
|
59
61
|
* @param {Element|ShadowRoot} element
|
|
@@ -157,5 +159,11 @@ declare function truncate(string: string, characterLimit: number): string;
|
|
|
157
159
|
declare namespace truncate {
|
|
158
160
|
function toString(): string;
|
|
159
161
|
}
|
|
162
|
+
declare const esbuildFunctionWrapperString: string;
|
|
163
|
+
/**
|
|
164
|
+
* @param {Function} fn
|
|
165
|
+
* @return {string}
|
|
166
|
+
*/
|
|
167
|
+
declare function getRuntimeFunctionName(fn: Function): string;
|
|
160
168
|
export {};
|
|
161
169
|
//# sourceMappingURL=page-functions.d.ts.map
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import {createRequire} from 'module';
|
|
8
|
+
|
|
7
9
|
import {Util} from '../../shared/util.js';
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -50,7 +52,7 @@ function wrapRuntimeEvalErrorInBrowser(err) {
|
|
|
50
52
|
|
|
51
53
|
/**
|
|
52
54
|
* @template {string} T
|
|
53
|
-
* @param {T} selector Optional simple CSS selector to filter nodes on.
|
|
55
|
+
* @param {T=} selector Optional simple CSS selector to filter nodes on.
|
|
54
56
|
* Combinators are not supported.
|
|
55
57
|
* @return {Array<ParseSelector<T>>}
|
|
56
58
|
*/
|
|
@@ -513,16 +515,89 @@ function truncate(string, characterLimit) {
|
|
|
513
515
|
return Util.truncate(string, characterLimit);
|
|
514
516
|
}
|
|
515
517
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
518
|
+
function isBundledEnvironment() {
|
|
519
|
+
// If we're in DevTools or LightRider, we are definitely bundled.
|
|
520
|
+
// TODO: refactor and delete `global.isDevtools`.
|
|
521
|
+
if (global.isDevtools || global.isLightrider) return true;
|
|
522
|
+
|
|
523
|
+
const require = createRequire(import.meta.url);
|
|
524
|
+
|
|
525
|
+
try {
|
|
526
|
+
// Not foolproof, but `lighthouse-logger` is a dependency of lighthouse that should always be resolvable.
|
|
527
|
+
// `require.resolve` will only throw in atypical/bundled environments.
|
|
528
|
+
require.resolve('lighthouse-logger');
|
|
529
|
+
return false;
|
|
530
|
+
} catch (err) {
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// This is to support bundled lighthouse.
|
|
536
|
+
// esbuild calls every function with a builtin `__name` (since we set keepNames: true),
|
|
537
|
+
// whose purpose is to store the real name of the function so that esbuild can rename it to avoid
|
|
538
|
+
// collisions. Anywhere we inject dynamically generated code at runtime for the browser to process,
|
|
539
|
+
// we must manually include this function (because esbuild only does so once at the top scope of
|
|
540
|
+
// the bundle, which is irrelevant for code executed in the browser).
|
|
541
|
+
// When minified, esbuild will mangle the name of this wrapper function, so we need to determine what it
|
|
542
|
+
// is at runtime in order to recreate it within the page.
|
|
543
|
+
const esbuildFunctionWrapperString = createEsbuildFunctionWrapper();
|
|
544
|
+
|
|
545
|
+
function createEsbuildFunctionWrapper() {
|
|
546
|
+
if (!isBundledEnvironment()) {
|
|
547
|
+
return '';
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const functionAsString = (()=>{
|
|
551
|
+
// eslint-disable-next-line no-unused-vars
|
|
552
|
+
const a = ()=>{};
|
|
553
|
+
}).toString()
|
|
554
|
+
// When not minified, esbuild annotates the call to this function wrapper with PURE.
|
|
555
|
+
// We know further that the name of the wrapper function should be `__name`, but let's not
|
|
556
|
+
// hardcode that. Remove the PURE annotation to simplify the regex.
|
|
557
|
+
.replace('/* @__PURE__ */', '');
|
|
558
|
+
const functionStringMatch = functionAsString.match(/=\s*([\w_]+)\(/);
|
|
559
|
+
if (!functionStringMatch) {
|
|
560
|
+
throw new Error('Could not determine esbuild function wrapper name');
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* @param {Function} fn
|
|
565
|
+
* @param {string} value
|
|
566
|
+
*/
|
|
567
|
+
const esbuildFunctionWrapper = (fn, value) =>
|
|
568
|
+
Object.defineProperty(fn, 'name', {value, configurable: true});
|
|
569
|
+
const wrapperFnName = functionStringMatch[1];
|
|
570
|
+
return `let ${wrapperFnName}=${esbuildFunctionWrapper}`;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* @param {Function} fn
|
|
575
|
+
* @return {string}
|
|
576
|
+
*/
|
|
577
|
+
function getRuntimeFunctionName(fn) {
|
|
578
|
+
const match = fn.toString().match(/function ([\w$]+)/);
|
|
579
|
+
if (!match) throw new Error(`could not find function name for: ${fn}`);
|
|
580
|
+
return match[1];
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// We setup a number of our page functions to automatically include their dependencies.
|
|
584
|
+
// Because of esbuild bundling, we must refer to the actual (mangled) runtime function name.
|
|
585
|
+
/** @type {Record<string, string>} */
|
|
586
|
+
const names = {
|
|
587
|
+
truncate: getRuntimeFunctionName(truncate),
|
|
588
|
+
getNodeLabel: getRuntimeFunctionName(getNodeLabel),
|
|
589
|
+
getOuterHTMLSnippet: getRuntimeFunctionName(getOuterHTMLSnippet),
|
|
590
|
+
getNodeDetails: getRuntimeFunctionName(getNodeDetails),
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
truncate.toString = () => `function ${names.truncate}(string, characterLimit) {
|
|
519
594
|
const Util = { ${Util.truncate} };
|
|
520
|
-
return (
|
|
595
|
+
return Util.truncate(string, characterLimit);
|
|
521
596
|
}`;
|
|
522
597
|
|
|
523
598
|
/** @type {string} */
|
|
524
599
|
const getNodeLabelRawString = getNodeLabel.toString();
|
|
525
|
-
getNodeLabel.toString = () => `function getNodeLabel(element) {
|
|
600
|
+
getNodeLabel.toString = () => `function ${names.getNodeLabel}(element) {
|
|
526
601
|
${truncate};
|
|
527
602
|
return (${getNodeLabelRawString})(element);
|
|
528
603
|
}`;
|
|
@@ -530,14 +605,14 @@ getNodeLabel.toString = () => `function getNodeLabel(element) {
|
|
|
530
605
|
/** @type {string} */
|
|
531
606
|
const getOuterHTMLSnippetRawString = getOuterHTMLSnippet.toString();
|
|
532
607
|
// eslint-disable-next-line max-len
|
|
533
|
-
getOuterHTMLSnippet.toString = () => `function getOuterHTMLSnippet(element, ignoreAttrs = [], snippetCharacterLimit = 500) {
|
|
608
|
+
getOuterHTMLSnippet.toString = () => `function ${names.getOuterHTMLSnippet}(element, ignoreAttrs = [], snippetCharacterLimit = 500) {
|
|
534
609
|
${truncate};
|
|
535
610
|
return (${getOuterHTMLSnippetRawString})(element, ignoreAttrs, snippetCharacterLimit);
|
|
536
611
|
}`;
|
|
537
612
|
|
|
538
613
|
/** @type {string} */
|
|
539
614
|
const getNodeDetailsRawString = getNodeDetails.toString();
|
|
540
|
-
getNodeDetails.toString = () => `function getNodeDetails(element) {
|
|
615
|
+
getNodeDetails.toString = () => `function ${names.getNodeDetails}(element) {
|
|
541
616
|
${truncate};
|
|
542
617
|
${getNodePath};
|
|
543
618
|
${getNodeSelector};
|
|
@@ -560,4 +635,6 @@ export const pageFunctions = {
|
|
|
560
635
|
wrapRequestIdleCallback,
|
|
561
636
|
getBoundingClientRect,
|
|
562
637
|
truncate,
|
|
638
|
+
esbuildFunctionWrapperString,
|
|
639
|
+
getRuntimeFunctionName,
|
|
563
640
|
};
|
package/core/lib/sentry.js
CHANGED
|
@@ -126,9 +126,16 @@ async function init(opts) {
|
|
|
126
126
|
if (opts.tags) {
|
|
127
127
|
scope.setTags(opts.tags);
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
|
|
130
|
+
// Add extra details
|
|
131
|
+
let extra;
|
|
132
|
+
if (opts.extra) extra = {...opts.extra};
|
|
133
|
+
// @ts-expect-error Non-standard property
|
|
134
|
+
if (err.extra) extra = {...extra, ...err.extra};
|
|
135
|
+
if (extra) {
|
|
136
|
+
scope.setExtras(extra);
|
|
131
137
|
}
|
|
138
|
+
|
|
132
139
|
Sentry.captureException(err);
|
|
133
140
|
});
|
|
134
141
|
};
|
package/core/lib/stack-packs.js
CHANGED
package/core/runner.d.ts
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
export type Connection = import('./legacy/gather/connections/connection.js').Connection;
|
|
2
1
|
export type ArbitraryEqualityMap = import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap;
|
|
3
|
-
export type Config = LH.Config.LegacyResolvedConfig;
|
|
4
|
-
/** @typedef {import('./legacy/gather/connections/connection.js').Connection} Connection */
|
|
5
2
|
/** @typedef {import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap} ArbitraryEqualityMap */
|
|
6
|
-
/** @typedef {LH.Config.LegacyResolvedConfig} Config */
|
|
7
3
|
export class Runner {
|
|
8
4
|
/**
|
|
9
|
-
* @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
|
|
10
5
|
* @param {LH.Artifacts} artifacts
|
|
11
|
-
* @param {{resolvedConfig:
|
|
6
|
+
* @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
12
7
|
* @return {Promise<LH.RunnerResult|undefined>}
|
|
13
8
|
*/
|
|
14
|
-
static audit
|
|
15
|
-
resolvedConfig:
|
|
16
|
-
driverMock?: Driver | undefined;
|
|
9
|
+
static audit(artifacts: LH.Artifacts, options: {
|
|
10
|
+
resolvedConfig: LH.Config.ResolvedConfig;
|
|
17
11
|
computedCache: Map<string, ArbitraryEqualityMap>;
|
|
18
12
|
}): Promise<LH.RunnerResult | undefined>;
|
|
19
13
|
/**
|
|
@@ -26,17 +20,14 @@ export class Runner {
|
|
|
26
20
|
* -G and -A will run partial lighthouse pipelines,
|
|
27
21
|
* and -GA will run everything plus save artifacts and lhr to disk.
|
|
28
22
|
*
|
|
29
|
-
* @
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
23
|
+
* @param {(runnerData: {resolvedConfig: LH.Config.ResolvedConfig}) => Promise<LH.Artifacts>} gatherFn
|
|
24
|
+
* @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
32
25
|
* @return {Promise<LH.Artifacts>}
|
|
33
26
|
*/
|
|
34
|
-
static gather
|
|
35
|
-
resolvedConfig:
|
|
36
|
-
driverMock?: Driver | undefined;
|
|
27
|
+
static gather(gatherFn: (runnerData: {
|
|
28
|
+
resolvedConfig: LH.Config.ResolvedConfig;
|
|
37
29
|
}) => Promise<LH.Artifacts>, options: {
|
|
38
|
-
resolvedConfig:
|
|
39
|
-
driverMock?: Driver | undefined;
|
|
30
|
+
resolvedConfig: LH.Config.ResolvedConfig;
|
|
40
31
|
computedCache: Map<string, ArbitraryEqualityMap>;
|
|
41
32
|
}): Promise<LH.Artifacts>;
|
|
42
33
|
/**
|
|
@@ -52,18 +43,6 @@ export class Runner {
|
|
|
52
43
|
* @return {LH.Result.Timing}
|
|
53
44
|
*/
|
|
54
45
|
static _getTiming(artifacts: LH.Artifacts): LH.Result.Timing;
|
|
55
|
-
/**
|
|
56
|
-
* Establish connection, load page and collect all required artifacts
|
|
57
|
-
* @param {string} requestedUrl
|
|
58
|
-
* @param {{resolvedConfig: Config, computedCache: Map<string, ArbitraryEqualityMap>, driverMock?: Driver}} runnerOpts
|
|
59
|
-
* @param {Connection} connection
|
|
60
|
-
* @return {Promise<LH.Artifacts>}
|
|
61
|
-
*/
|
|
62
|
-
static _gatherArtifactsFromBrowser(requestedUrl: string, runnerOpts: {
|
|
63
|
-
resolvedConfig: Config;
|
|
64
|
-
computedCache: Map<string, ArbitraryEqualityMap>;
|
|
65
|
-
driverMock?: Driver;
|
|
66
|
-
}, connection: Connection): Promise<LH.Artifacts>;
|
|
67
46
|
/**
|
|
68
47
|
* Run all audits with specified settings and artifacts.
|
|
69
48
|
* @param {LH.Config.Settings} settings
|
|
@@ -109,6 +88,5 @@ export class Runner {
|
|
|
109
88
|
*/
|
|
110
89
|
static _getDataSavePath(settings: LH.Config.Settings): string;
|
|
111
90
|
}
|
|
112
|
-
import { Driver } from './legacy/gather/driver.js';
|
|
113
91
|
import { Audit } from './audits/audit.js';
|
|
114
92
|
//# sourceMappingURL=runner.d.ts.map
|
package/core/runner.js
CHANGED
|
@@ -11,8 +11,6 @@ import path from 'path';
|
|
|
11
11
|
import log from 'lighthouse-logger';
|
|
12
12
|
import isDeepEqual from 'lodash/isEqual.js';
|
|
13
13
|
|
|
14
|
-
import {Driver} from './legacy/gather/driver.js';
|
|
15
|
-
import {GatherRunner} from './legacy/gather/gather-runner.js';
|
|
16
14
|
import {ReportScoring} from './scoring.js';
|
|
17
15
|
import {Audit} from './audits/audit.js';
|
|
18
16
|
import * as format from '../shared/localization/format.js';
|
|
@@ -28,15 +26,12 @@ import UrlUtils from './lib/url-utils.js';
|
|
|
28
26
|
|
|
29
27
|
const moduleDir = getModuleDirectory(import.meta);
|
|
30
28
|
|
|
31
|
-
/** @typedef {import('./legacy/gather/connections/connection.js').Connection} Connection */
|
|
32
29
|
/** @typedef {import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap} ArbitraryEqualityMap */
|
|
33
|
-
/** @typedef {LH.Config.LegacyResolvedConfig} Config */
|
|
34
30
|
|
|
35
31
|
class Runner {
|
|
36
32
|
/**
|
|
37
|
-
* @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
|
|
38
33
|
* @param {LH.Artifacts} artifacts
|
|
39
|
-
* @param {{resolvedConfig:
|
|
34
|
+
* @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
40
35
|
* @return {Promise<LH.RunnerResult|undefined>}
|
|
41
36
|
*/
|
|
42
37
|
static async audit(artifacts, options) {
|
|
@@ -153,7 +148,7 @@ class Runner {
|
|
|
153
148
|
* @param {LH.Artifacts.ComputedContext} context
|
|
154
149
|
*/
|
|
155
150
|
static async getEntityClassification(artifacts, context) {
|
|
156
|
-
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
151
|
+
const devtoolsLog = artifacts.devtoolsLogs?.[Audit.DEFAULT_PASS];
|
|
157
152
|
if (!devtoolsLog) return;
|
|
158
153
|
const classifiedEntities = await EntityClassification.request(
|
|
159
154
|
{URL: artifacts.URL, devtoolsLog}, context);
|
|
@@ -188,9 +183,8 @@ class Runner {
|
|
|
188
183
|
* -G and -A will run partial lighthouse pipelines,
|
|
189
184
|
* and -GA will run everything plus save artifacts and lhr to disk.
|
|
190
185
|
*
|
|
191
|
-
* @
|
|
192
|
-
* @param {
|
|
193
|
-
* @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
186
|
+
* @param {(runnerData: {resolvedConfig: LH.Config.ResolvedConfig}) => Promise<LH.Artifacts>} gatherFn
|
|
187
|
+
* @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
|
|
194
188
|
* @return {Promise<LH.Artifacts>}
|
|
195
189
|
*/
|
|
196
190
|
static async gather(gatherFn, options) {
|
|
@@ -217,7 +211,6 @@ class Runner {
|
|
|
217
211
|
|
|
218
212
|
artifacts = await gatherFn({
|
|
219
213
|
resolvedConfig: options.resolvedConfig,
|
|
220
|
-
driverMock: options.driverMock,
|
|
221
214
|
});
|
|
222
215
|
|
|
223
216
|
log.timeEnd(runnerStatus);
|
|
@@ -291,28 +284,6 @@ class Runner {
|
|
|
291
284
|
return {entries: timingEntries, total: gatherTiming + auditTiming};
|
|
292
285
|
}
|
|
293
286
|
|
|
294
|
-
/**
|
|
295
|
-
* Establish connection, load page and collect all required artifacts
|
|
296
|
-
* @param {string} requestedUrl
|
|
297
|
-
* @param {{resolvedConfig: Config, computedCache: Map<string, ArbitraryEqualityMap>, driverMock?: Driver}} runnerOpts
|
|
298
|
-
* @param {Connection} connection
|
|
299
|
-
* @return {Promise<LH.Artifacts>}
|
|
300
|
-
*/
|
|
301
|
-
static async _gatherArtifactsFromBrowser(requestedUrl, runnerOpts, connection) {
|
|
302
|
-
if (!runnerOpts.resolvedConfig.passes) {
|
|
303
|
-
throw new Error('No browser artifacts are either provided or requested.');
|
|
304
|
-
}
|
|
305
|
-
const driver = runnerOpts.driverMock || new Driver(connection);
|
|
306
|
-
const gatherOpts = {
|
|
307
|
-
driver,
|
|
308
|
-
requestedUrl,
|
|
309
|
-
settings: runnerOpts.resolvedConfig.settings,
|
|
310
|
-
computedCache: runnerOpts.computedCache,
|
|
311
|
-
};
|
|
312
|
-
const artifacts = await GatherRunner.run(runnerOpts.resolvedConfig.passes, gatherOpts);
|
|
313
|
-
return artifacts;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
287
|
/**
|
|
317
288
|
* Run all audits with specified settings and artifacts.
|
|
318
289
|
* @param {LH.Config.Settings} settings
|
|
@@ -396,6 +367,8 @@ class Runner {
|
|
|
396
367
|
|
|
397
368
|
let auditResult;
|
|
398
369
|
try {
|
|
370
|
+
if (artifacts.PageLoadError) throw artifacts.PageLoadError;
|
|
371
|
+
|
|
399
372
|
// Return an early error if an artifact required for the audit is missing or an error.
|
|
400
373
|
for (const artifactName of audit.meta.requiredArtifacts) {
|
|
401
374
|
const noArtifact = artifacts[artifactName] === undefined;
|
|
@@ -419,15 +392,11 @@ class Runner {
|
|
|
419
392
|
// @ts-expect-error: TODO why is this a type error now?
|
|
420
393
|
const artifactError = artifacts[artifactName];
|
|
421
394
|
|
|
422
|
-
Sentry.captureException(artifactError, {
|
|
423
|
-
tags: {gatherer: artifactName},
|
|
424
|
-
level: 'error',
|
|
425
|
-
});
|
|
426
|
-
|
|
427
395
|
log.warn('Runner', `${artifactName} gatherer, required by audit ${audit.meta.id},` +
|
|
428
396
|
` encountered an error: ${artifactError.message}`);
|
|
429
397
|
|
|
430
|
-
// Create a friendlier display error and mark it as expected to avoid duplicates in Sentry
|
|
398
|
+
// Create a friendlier display error and mark it as expected to avoid duplicates in Sentry.
|
|
399
|
+
// The artifact error was already sent to Sentry in `collectPhaseArtifacts`.
|
|
431
400
|
const error = new LighthouseError(LighthouseError.errors.ERRORED_REQUIRED_ARTIFACT,
|
|
432
401
|
{artifactName, errorMessage: artifactError.message}, {cause: artifactError});
|
|
433
402
|
// @ts-expect-error Non-standard property added to Error
|
package/core/user-flow.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type GatherStepRunnerOptions = WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.
|
|
1
|
+
export type GatherStepRunnerOptions = WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.GatherResult['runnerOptions']>;
|
|
2
2
|
export class UserFlow {
|
|
3
3
|
/**
|
|
4
4
|
* @param {LH.Puppeteer.Page} page
|
|
@@ -24,10 +24,10 @@ export class UserFlow {
|
|
|
24
24
|
*/
|
|
25
25
|
_getNextNavigationFlags(flags: LH.UserFlow.StepFlags | undefined): LH.UserFlow.StepFlags;
|
|
26
26
|
/**
|
|
27
|
-
* @param {LH.Gatherer.
|
|
27
|
+
* @param {LH.Gatherer.GatherResult} gatherResult
|
|
28
28
|
* @param {LH.UserFlow.StepFlags} [flags]
|
|
29
29
|
*/
|
|
30
|
-
_addGatherStep(gatherResult: LH.Gatherer.
|
|
30
|
+
_addGatherStep(gatherResult: LH.Gatherer.GatherResult, flags?: LH.UserFlow.StepFlags | undefined): void;
|
|
31
31
|
/**
|
|
32
32
|
* @param {LH.NavigationRequestor} requestor
|
|
33
33
|
* @param {LH.UserFlow.StepFlags} [flags]
|
|
@@ -50,7 +50,7 @@ export class UserFlow {
|
|
|
50
50
|
startTimespan(flags?: LH.UserFlow.StepFlags | undefined): Promise<void>;
|
|
51
51
|
currentTimespan: {
|
|
52
52
|
timespan: {
|
|
53
|
-
endTimespanGather(): Promise<LH.Gatherer.
|
|
53
|
+
endTimespanGather(): Promise<LH.Gatherer.GatherResult>;
|
|
54
54
|
};
|
|
55
55
|
flags: LH.UserFlow.StepFlags | undefined;
|
|
56
56
|
} | undefined;
|
package/core/user-flow.js
CHANGED
|
@@ -15,7 +15,7 @@ import {mergeConfigFragment, deepClone} from './config/config-helpers.js';
|
|
|
15
15
|
import * as i18n from './lib/i18n/i18n.js';
|
|
16
16
|
import * as LH from '../types/lh.js';
|
|
17
17
|
|
|
18
|
-
/** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.
|
|
18
|
+
/** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.GatherResult['runnerOptions']>} GatherStepRunnerOptions */
|
|
19
19
|
|
|
20
20
|
const UIStrings = {
|
|
21
21
|
/**
|
|
@@ -107,7 +107,7 @@ class UserFlow {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* @param {LH.Gatherer.
|
|
110
|
+
* @param {LH.Gatherer.GatherResult} gatherResult
|
|
111
111
|
* @param {LH.UserFlow.StepFlags} [flags]
|
|
112
112
|
*/
|
|
113
113
|
_addGatherStep(gatherResult, flags) {
|