lighthouse 12.6.1-dev.20250611 → 12.6.1-dev.20250613
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/cli/test/smokehouse/frontends/lib.js +0 -2
- package/cli/test/smokehouse/frontends/smokehouse-bin.js +1 -3
- package/cli/test/smokehouse/lighthouse-runners/cli.js +1 -1
- package/cli/test/smokehouse/smokehouse.js +0 -2
- package/core/audits/byte-efficiency/legacy-javascript.js +0 -1
- package/core/audits/deprecations.js +0 -2
- package/core/audits/insights/cls-culprits-insight.js +0 -2
- package/core/audits/insights/modern-http-insight.js +0 -2
- package/core/audits/third-party-cookies.js +0 -2
- package/core/audits/valid-source-maps.js +0 -2
- package/core/computed/js-bundles.js +0 -1
- package/core/computed/metrics/cumulative-layout-shift.js +1 -1
- package/core/computed/trace-engine-result.js +0 -1
- package/core/config/config.js +1 -1
- package/core/gather/driver/navigation.js +1 -3
- package/core/gather/driver/wait-for-condition.js +0 -1
- package/core/gather/fetcher.js +0 -2
- package/core/gather/gatherers/accessibility.js +1 -1
- package/core/gather/gatherers/anchor-elements.js +0 -2
- package/core/gather/gatherers/cache-contents.js +0 -2
- package/core/gather/gatherers/css-usage.js +0 -1
- package/core/gather/gatherers/dobetterweb/doctype.js +0 -2
- package/core/gather/gatherers/dobetterweb/domstats.js +1 -1
- package/core/gather/gatherers/full-page-screenshot.js +1 -1
- package/core/gather/gatherers/image-elements.js +1 -1
- package/core/gather/gatherers/link-elements.js +1 -1
- package/core/gather/gatherers/stacks.js +0 -1
- package/core/gather/gatherers/stylesheets.js +0 -1
- package/core/gather/gatherers/trace-elements.js +1 -1
- package/core/gather/gatherers/viewport-dimensions.js +0 -2
- package/core/index.cjs +0 -1
- package/core/index.d.cts +5 -0
- package/core/lib/i18n/i18n.js +0 -2
- package/core/lib/lantern-trace-saver.js +1 -1
- package/core/lib/lh-error.js +0 -1
- package/core/lib/manifest-parser.js +0 -2
- package/core/lib/minify-devtoolslog.js +0 -2
- package/core/lib/sentry.d.ts +1 -1
- package/core/lib/sentry.js +2 -2
- package/core/runner.js +0 -1
- package/core/scripts/manual-chrome-launcher.js +0 -1
- package/eslint.config.mjs +242 -0
- package/flow-report/src/common.tsx +1 -0
- package/flow-report/src/i18n/i18n.tsx +1 -0
- package/flow-report/src/util.ts +2 -0
- package/package.json +10 -6
- package/report/generator/file-namer.d.ts +5 -0
- package/report/generator/file-namer.js +1 -1
- package/report/generator/flow-report-assets.js +1 -1
- package/report/generator/report-assets.js +1 -1
- package/report/generator/report-generator.js +3 -3
- package/report/renderer/i18n-formatter.js +2 -1
- package/report/renderer/report-renderer.js +1 -0
- package/report/renderer/report-utils.js +3 -2
- package/report/renderer/text-encoding.js +0 -2
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
* flags, start fixture webservers, then run smokehouse.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
/* eslint-disable no-console */
|
|
14
|
-
|
|
15
13
|
import path from 'path';
|
|
16
14
|
import fs from 'fs';
|
|
17
15
|
import url from 'url';
|
|
@@ -173,7 +171,7 @@ async function begin() {
|
|
|
173
171
|
},
|
|
174
172
|
'no-headless': {
|
|
175
173
|
type: 'boolean',
|
|
176
|
-
describe: 'Launch Chrome in typical desktop headful mode, rather than our default of `--headless=new` (https://developer.chrome.com/articles/new-headless/).',
|
|
174
|
+
describe: 'Launch Chrome in typical desktop headful mode, rather than our default of `--headless=new` (https://developer.chrome.com/articles/new-headless/).',
|
|
177
175
|
},
|
|
178
176
|
})
|
|
179
177
|
.wrap(y.terminalWidth())
|
|
@@ -25,7 +25,6 @@ import {detectLegacyJavaScript} from '../../lib/legacy-javascript/legacy-javascr
|
|
|
25
25
|
const UIStrings = {
|
|
26
26
|
/** Title of a Lighthouse audit that tells the user about legacy polyfills and transforms used on the page. This is displayed in a list of audit titles that Lighthouse generates. */
|
|
27
27
|
title: 'Avoid serving legacy JavaScript to modern browsers',
|
|
28
|
-
// eslint-disable-next-line max-len
|
|
29
28
|
// TODO: developer.chrome.com article. this codelab is good starting place: https://web.dev/articles/codelab-serve-modern-code
|
|
30
29
|
/** Description of a Lighthouse audit that tells the user about old JavaScript that is no longer needed. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
|
|
31
30
|
description: 'Polyfills and transforms enable legacy browsers to use new JavaScript features. However, many aren\'t necessary for modern browsers. Consider modifying your JavaScript build process to not transpile [Baseline](https://web.dev/baseline) features, unless you know you must support legacy browsers. [Learn why most sites can deploy ES6+ code without transpiling](https://philipwalton.com/articles/the-state-of-es5-on-the-web/)',
|
|
@@ -13,7 +13,6 @@ import {JSBundles} from '../computed/js-bundles.js';
|
|
|
13
13
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
14
14
|
import {getIssueDetailDescription} from '../lib/deprecation-description.js';
|
|
15
15
|
|
|
16
|
-
/* eslint-disable max-len */
|
|
17
16
|
const UIStrings = {
|
|
18
17
|
/** Title of a Lighthouse audit that provides detail on the use of deprecated APIs. This descriptive title is shown to users when the page does not use deprecated APIs. */
|
|
19
18
|
title: 'Avoids deprecated APIs',
|
|
@@ -32,7 +31,6 @@ const UIStrings = {
|
|
|
32
31
|
/** Table column header for line of code (eg. 432) that is using a deprecated API. */
|
|
33
32
|
columnLine: 'Line',
|
|
34
33
|
};
|
|
35
|
-
/* eslint-enable max-len */
|
|
36
34
|
|
|
37
35
|
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
38
36
|
|
|
@@ -19,12 +19,10 @@ const MAX_LAYOUT_SHIFTS_PER_CLUSTER = 5;
|
|
|
19
19
|
// eslint-disable-next-line max-len
|
|
20
20
|
const insightStr_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/CLSCulprits.js', InsightUIStrings);
|
|
21
21
|
|
|
22
|
-
/* eslint-disable max-len */
|
|
23
22
|
const UIStrings = {
|
|
24
23
|
/** Label for a column in a data table; entries in this column will be a number representing how large the layout shift was. */
|
|
25
24
|
columnScore: 'Layout shift score',
|
|
26
25
|
};
|
|
27
|
-
/* eslint-enable max-len */
|
|
28
26
|
|
|
29
27
|
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
30
28
|
|
|
@@ -37,10 +37,8 @@ class ModernHTTPInsight extends Audit {
|
|
|
37
37
|
return adaptInsightToAuditProduct(artifacts, context, 'ModernHTTP', (insight) => {
|
|
38
38
|
/** @type {LH.Audit.Details.Table['headings']} */
|
|
39
39
|
const headings = [
|
|
40
|
-
/* eslint-disable max-len */
|
|
41
40
|
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
|
|
42
41
|
{key: 'protocol', valueType: 'text', label: str_(UIStrings.protocol)},
|
|
43
|
-
/* eslint-enable max-len */
|
|
44
42
|
];
|
|
45
43
|
/** @type {LH.Audit.Details.Table['items']} */
|
|
46
44
|
const items =
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
import {Audit} from './audit.js';
|
|
12
12
|
import * as i18n from '../lib/i18n/i18n.js';
|
|
13
13
|
|
|
14
|
-
/* eslint-disable max-len */
|
|
15
14
|
const UIStrings = {
|
|
16
15
|
/** Title of a Lighthouse audit that provides detail on the use of third party cookies. This descriptive title is shown to users when the page does not use third party cookies. */
|
|
17
16
|
title: 'Avoids third-party cookies',
|
|
@@ -25,7 +24,6 @@ const UIStrings = {
|
|
|
25
24
|
other {# cookies found}
|
|
26
25
|
}`,
|
|
27
26
|
};
|
|
28
|
-
/* eslint-enable max-len */
|
|
29
27
|
|
|
30
28
|
const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
31
29
|
|
|
@@ -121,7 +121,6 @@ class ValidSourceMaps extends Audit {
|
|
|
121
121
|
|
|
122
122
|
/** @type {LH.Audit.Details.TableColumnHeading[]} */
|
|
123
123
|
const headings = [
|
|
124
|
-
/* eslint-disable max-len */
|
|
125
124
|
{
|
|
126
125
|
key: 'scriptUrl',
|
|
127
126
|
valueType: 'url',
|
|
@@ -129,7 +128,6 @@ class ValidSourceMaps extends Audit {
|
|
|
129
128
|
label: str_(i18n.UIStrings.columnURL),
|
|
130
129
|
},
|
|
131
130
|
{key: 'sourceMapUrl', valueType: 'url', label: str_(UIStrings.columnMapURL)},
|
|
132
|
-
/* eslint-enable max-len */
|
|
133
131
|
];
|
|
134
132
|
|
|
135
133
|
results.sort((a, b) => {
|
|
@@ -55,7 +55,6 @@ function computeGeneratedFileSizes(map, contentLength, content) {
|
|
|
55
55
|
let mappingLength = 0;
|
|
56
56
|
if (lastColNum !== undefined) {
|
|
57
57
|
if (lastColNum > line.length) {
|
|
58
|
-
// eslint-disable-next-line max-len
|
|
59
58
|
const errorMessage =
|
|
60
59
|
`${map.url()} mapping for last column out of bounds: ${lineNum + 1}:${lastColNum}`;
|
|
61
60
|
log.error('JSBundles', errorMessage);
|
|
@@ -159,7 +159,6 @@ class CumulativeLayoutShift {
|
|
|
159
159
|
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
|
|
160
160
|
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
161
161
|
});
|
|
162
|
-
// eslint-disable-next-line max-len
|
|
163
162
|
await processor.parse(/** @type {import('@paulirish/trace_engine').Types.Events.Event[]} */ (
|
|
164
163
|
events
|
|
165
164
|
), {});
|
|
@@ -212,6 +211,7 @@ class CumulativeLayoutShift {
|
|
|
212
211
|
throw new Error(`new trace engine differed. expected: ${expected}, got: ${got}`);
|
|
213
212
|
}
|
|
214
213
|
} catch (err) {
|
|
214
|
+
// eslint-disable-next-line no-console
|
|
215
215
|
console.error(err);
|
|
216
216
|
newEngineResultDiffered = true;
|
|
217
217
|
|
|
@@ -34,7 +34,6 @@ class TraceEngineResult {
|
|
|
34
34
|
lanternSettings.precomputedLanternData = settings.precomputedLanternData;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
// eslint-disable-next-line max-len
|
|
38
37
|
await processor.parse(/** @type {import('@paulirish/trace_engine').Types.Events.Event[]} */ (
|
|
39
38
|
traceEvents
|
|
40
39
|
), {
|
package/core/config/config.js
CHANGED
|
@@ -10,7 +10,7 @@ import log from 'lighthouse-logger';
|
|
|
10
10
|
|
|
11
11
|
import {Runner} from '../runner.js';
|
|
12
12
|
import defaultConfig from './default-config.js';
|
|
13
|
-
import {nonSimulatedSettingsOverrides} from './constants.js';
|
|
13
|
+
import {nonSimulatedSettingsOverrides} from './constants.js';
|
|
14
14
|
import {
|
|
15
15
|
throwInvalidDependencyOrder,
|
|
16
16
|
isValidArtifactDependency,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import log from 'lighthouse-logger';
|
|
8
8
|
|
|
9
|
-
import {waitForFullyLoaded, waitForFrameNavigated, waitForUserToContinue} from './wait-for-condition.js';
|
|
9
|
+
import {waitForFullyLoaded, waitForFrameNavigated, waitForUserToContinue} from './wait-for-condition.js';
|
|
10
10
|
import * as constants from '../../config/constants.js';
|
|
11
11
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
12
12
|
import UrlUtils from '../../lib/url-utils.js';
|
|
@@ -43,7 +43,6 @@ const DEFAULT_CPU_QUIET_THRESHOLD = 0;
|
|
|
43
43
|
|
|
44
44
|
/** @param {NavigationOptions} options */
|
|
45
45
|
function resolveWaitForFullyLoadedOptions(options) {
|
|
46
|
-
/* eslint-disable max-len */
|
|
47
46
|
let {pauseAfterFcpMs, pauseAfterLoadMs, networkQuietThresholdMs, cpuQuietThresholdMs} = options;
|
|
48
47
|
let maxWaitMs = options.maxWaitForLoad;
|
|
49
48
|
let maxFCPMs = options.maxWaitForFcp;
|
|
@@ -56,7 +55,6 @@ function resolveWaitForFullyLoadedOptions(options) {
|
|
|
56
55
|
if (typeof cpuQuietThresholdMs !== 'number') cpuQuietThresholdMs = DEFAULT_CPU_QUIET_THRESHOLD;
|
|
57
56
|
if (typeof maxWaitMs !== 'number') maxWaitMs = constants.defaultSettings.maxWaitForLoad;
|
|
58
57
|
if (typeof maxFCPMs !== 'number') maxFCPMs = constants.defaultSettings.maxWaitForFcp;
|
|
59
|
-
/* eslint-enable max-len */
|
|
60
58
|
|
|
61
59
|
if (!options.waitUntil.includes('fcp')) maxFCPMs = undefined;
|
|
62
60
|
|
|
@@ -138,7 +138,6 @@ function waitForNetworkIdle(session, networkMonitor, networkQuietOptions) {
|
|
|
138
138
|
/** @type {Promise<void>} */
|
|
139
139
|
const promise = new Promise((resolve, reject) => {
|
|
140
140
|
const onIdle = () => {
|
|
141
|
-
// eslint-disable-next-line no-use-before-define
|
|
142
141
|
networkMonitor.once(busyEvent, onBusy);
|
|
143
142
|
idleTimeout = setTimeout(() => {
|
|
144
143
|
cancel();
|
package/core/gather/fetcher.js
CHANGED
|
@@ -10,8 +10,6 @@ import BaseGatherer from '../base-gatherer.js';
|
|
|
10
10
|
import {pageFunctions} from '../../lib/page-functions.js';
|
|
11
11
|
import {resolveDevtoolsNodePathToObjectId} from '../driver/dom.js';
|
|
12
12
|
|
|
13
|
-
/* eslint-env browser, node */
|
|
14
|
-
|
|
15
13
|
/**
|
|
16
14
|
* Function that is stringified and run in the page to collect anchor elements.
|
|
17
15
|
* Additional complexity is introduced because anchors can be HTML or SVG elements.
|
|
@@ -30,7 +30,6 @@ class CSSUsage extends BaseGatherer {
|
|
|
30
30
|
|
|
31
31
|
// Force style to recompute.
|
|
32
32
|
// Doesn't appear to be necessary in newer versions of Chrome.
|
|
33
|
-
/* global window, document */
|
|
34
33
|
await executionContext.evaluate(() => window.getComputedStyle(document.body), {
|
|
35
34
|
args: [],
|
|
36
35
|
});
|
|
@@ -15,7 +15,7 @@ import BaseGatherer from '../base-gatherer.js';
|
|
|
15
15
|
import {pageFunctions} from '../../lib/page-functions.js';
|
|
16
16
|
import * as FontSize from './seo/font-size.js';
|
|
17
17
|
|
|
18
|
-
/* global
|
|
18
|
+
/* global getElementsInDocument, getNodeDetails */
|
|
19
19
|
|
|
20
20
|
/** @param {Element} element */
|
|
21
21
|
/* c8 ignore start */
|
|
@@ -13,7 +13,7 @@ import {MainResource} from '../../computed/main-resource.js';
|
|
|
13
13
|
import {Util} from '../../../shared/util.js';
|
|
14
14
|
import * as i18n from '../../lib/i18n/i18n.js';
|
|
15
15
|
|
|
16
|
-
/* globals
|
|
16
|
+
/* globals getNodeDetails */
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @fileoverview
|
|
@@ -74,7 +74,6 @@ class Stylesheets extends BaseGatherer {
|
|
|
74
74
|
|
|
75
75
|
// Force style to recompute.
|
|
76
76
|
// Doesn't appear to be necessary in newer versions of Chrome.
|
|
77
|
-
/* global window, document */
|
|
78
77
|
await executionContext.evaluate(() => window.getComputedStyle(document.body), {
|
|
79
78
|
args: [],
|
|
80
79
|
});
|
|
@@ -35,7 +35,7 @@ const MAX_LAYOUT_SHIFTS = 15;
|
|
|
35
35
|
*/
|
|
36
36
|
/* c8 ignore start */
|
|
37
37
|
function getNodeDetailsData() {
|
|
38
|
-
const elem = this.nodeType === document.ELEMENT_NODE ? this : this.parentElement;
|
|
38
|
+
const elem = this.nodeType === document.ELEMENT_NODE ? this : this.parentElement;
|
|
39
39
|
let traceElement;
|
|
40
40
|
if (elem) {
|
|
41
41
|
// @ts-expect-error - getNodeDetails put into scope via stringification
|
package/core/index.cjs
CHANGED
package/core/index.d.cts
CHANGED
package/core/lib/i18n/i18n.js
CHANGED
|
@@ -17,7 +17,6 @@ import {LH_ROOT} from '../../../shared/root.js';
|
|
|
17
17
|
import {isIcuMessage, formatMessage, DEFAULT_LOCALE} from '../../../shared/localization/format.js';
|
|
18
18
|
import {getModulePath} from '../../../shared/esm-utils.js';
|
|
19
19
|
|
|
20
|
-
/* eslint-disable max-len */
|
|
21
20
|
const UIStrings = {
|
|
22
21
|
/** Used to show the duration in milliseconds that something lasted. The `{timeInMs}` placeholder will be replaced with the time duration, shown in milliseconds (e.g. 63 ms) */
|
|
23
22
|
ms: '{timeInMs, number, milliseconds}\xa0ms',
|
|
@@ -114,7 +113,6 @@ const UIStrings = {
|
|
|
114
113
|
/** Table item value for the severity of a high impact, or dangerous vulnerability. Part of a ranking scale in the form: low, medium, high. */
|
|
115
114
|
itemSeverityHigh: 'High',
|
|
116
115
|
};
|
|
117
|
-
/* eslint-enable max-len */
|
|
118
116
|
|
|
119
117
|
/**
|
|
120
118
|
* Look up the best available locale for the requested language through these fall backs:
|
|
@@ -153,7 +153,7 @@ function convertNodeTimingsToTrace(nodeTimings) {
|
|
|
153
153
|
|
|
154
154
|
// 0ms requests get super-messed up rendering
|
|
155
155
|
// Use 0.3ms instead so they're still hoverable, https://github.com/GoogleChrome/lighthouse/pull/5350#discussion_r194563201
|
|
156
|
-
let {startTime, endTime} = timing;
|
|
156
|
+
let {startTime, endTime} = timing;
|
|
157
157
|
if (startTime === endTime) endTime += 0.3;
|
|
158
158
|
|
|
159
159
|
const requestData = {requestId: requestId.toString(), frame};
|
package/core/lib/lh-error.js
CHANGED
|
@@ -214,7 +214,6 @@ class LighthouseError extends Error {
|
|
|
214
214
|
if (typeof possibleError === 'object' && possibleError !== null) {
|
|
215
215
|
if (possibleError.sentinel === LHERROR_SENTINEL) {
|
|
216
216
|
// Include sentinel in destructuring so it doesn't end up in `properties`.
|
|
217
|
-
// eslint-disable-next-line no-unused-vars
|
|
218
217
|
const {code, stack, cause, properties} = /** @type {SerializedLighthouseError} */ (possibleError);
|
|
219
218
|
const errorDefinition = LighthouseError.errors[/** @type {keyof typeof ERRORS} */ (code)];
|
|
220
219
|
const lhError = new LighthouseError(errorDefinition, properties, {cause});
|
|
@@ -458,7 +458,6 @@ function parseManifest(string, manifestUrl, documentUrl) {
|
|
|
458
458
|
};
|
|
459
459
|
}
|
|
460
460
|
|
|
461
|
-
/* eslint-disable camelcase */
|
|
462
461
|
const manifest = {
|
|
463
462
|
name: parseName(jsonInput),
|
|
464
463
|
short_name: parseShortName(jsonInput),
|
|
@@ -471,7 +470,6 @@ function parseManifest(string, manifestUrl, documentUrl) {
|
|
|
471
470
|
theme_color: parseThemeColor(jsonInput),
|
|
472
471
|
background_color: parseBackgroundColor(jsonInput),
|
|
473
472
|
};
|
|
474
|
-
/* eslint-enable camelcase */
|
|
475
473
|
|
|
476
474
|
/** @type {string|undefined} */
|
|
477
475
|
let manifestUrlWarning;
|
package/core/lib/sentry.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export namespace Sentry {
|
|
|
17
17
|
export type Breadcrumb = import("@sentry/node").Breadcrumb;
|
|
18
18
|
export type NodeClient = import("@sentry/node").NodeClient;
|
|
19
19
|
export type NodeOptions = import("@sentry/node").NodeOptions;
|
|
20
|
-
export type
|
|
20
|
+
export type SeverityLevel = import("@sentry/node").SeverityLevel;
|
|
21
21
|
/**
|
|
22
22
|
* When called, replaces noops with actual Sentry implementation.
|
|
23
23
|
* @param {{url: string, flags: LH.CliFlags, config?: LH.Config, environmentData: NodeOptions}} opts
|
package/core/lib/sentry.js
CHANGED
|
@@ -11,7 +11,7 @@ import {initializeConfig} from '../config/config.js';
|
|
|
11
11
|
/** @typedef {import('@sentry/node').Breadcrumb} Breadcrumb */
|
|
12
12
|
/** @typedef {import('@sentry/node').NodeClient} NodeClient */
|
|
13
13
|
/** @typedef {import('@sentry/node').NodeOptions} NodeOptions */
|
|
14
|
-
/** @typedef {import('@sentry/node').
|
|
14
|
+
/** @typedef {import('@sentry/node').SeverityLevel} SeverityLevel */
|
|
15
15
|
|
|
16
16
|
const SENTRY_URL = 'https://a6bb0da87ee048cc9ae2a345fc09ab2e:63a7029f46f74265981b7e005e0f69f8@sentry.io/174697';
|
|
17
17
|
|
|
@@ -26,7 +26,7 @@ const noop = () => { };
|
|
|
26
26
|
*/
|
|
27
27
|
const sentryDelegate = {
|
|
28
28
|
init,
|
|
29
|
-
/** @type {(message: string, level?:
|
|
29
|
+
/** @type {(message: string, level?: SeverityLevel) => void} */
|
|
30
30
|
captureMessage: noop,
|
|
31
31
|
/** @type {(breadcrumb: Breadcrumb) => void} */
|
|
32
32
|
captureBreadcrumb: noop,
|
package/core/runner.js
CHANGED
|
@@ -458,7 +458,6 @@ vs: ${JSON.stringify(normalizedAuditSettings[k], null, 2)}`);
|
|
|
458
458
|
for (const [artifactKey, possibleErrorArtifact] of possibleErrorArtifacts) {
|
|
459
459
|
const isError = possibleErrorArtifact instanceof LighthouseError;
|
|
460
460
|
|
|
461
|
-
// eslint-disable-next-line max-len
|
|
462
461
|
if (isError && possibleErrorArtifact.lhrRuntimeError) {
|
|
463
462
|
const errorMessage = possibleErrorArtifact.friendlyMessage || possibleErrorArtifact.message;
|
|
464
463
|
// Prefer the stack trace closest to the error.
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {fileURLToPath} from 'node:url';
|
|
3
|
+
|
|
4
|
+
import localRules from 'eslint-plugin-local-rules';
|
|
5
|
+
import _import from 'eslint-plugin-import';
|
|
6
|
+
import {fixupPluginRules} from '@eslint/compat';
|
|
7
|
+
import globals from 'globals';
|
|
8
|
+
import tsParser from '@typescript-eslint/parser';
|
|
9
|
+
import js from '@eslint/js';
|
|
10
|
+
import {FlatCompat} from '@eslint/eslintrc';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
const compat = new FlatCompat({
|
|
15
|
+
baseDirectory: __dirname,
|
|
16
|
+
recommendedConfig: js.configs.recommended,
|
|
17
|
+
allConfig: js.configs.all,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// See https://eslint.org/docs/latest/use/configure/configuration-files
|
|
21
|
+
export default [{
|
|
22
|
+
files: [
|
|
23
|
+
'**/*.cjs',
|
|
24
|
+
'**/*.js',
|
|
25
|
+
'**/*.mjs',
|
|
26
|
+
'**/*.ts',
|
|
27
|
+
'**/*.tsx',
|
|
28
|
+
],
|
|
29
|
+
}, {
|
|
30
|
+
// Global ignores.
|
|
31
|
+
ignores: [
|
|
32
|
+
'.cz-config.js',
|
|
33
|
+
'**/.tmp',
|
|
34
|
+
'**/*.d.cts', // ignore d.ts files until we can properly lint them
|
|
35
|
+
'**/*.d.ts',
|
|
36
|
+
'**/dist',
|
|
37
|
+
'**/fixtures/**',
|
|
38
|
+
'**/node_modules/**',
|
|
39
|
+
'**/source-maps/**',
|
|
40
|
+
'**/third_party/**',
|
|
41
|
+
'**/third-party/**',
|
|
42
|
+
'build/test/page-functions-test-case*out*.js',
|
|
43
|
+
'core/scripts/legacy-javascript/variants/**',
|
|
44
|
+
'coverage/**',
|
|
45
|
+
],
|
|
46
|
+
}, ...compat.extends('eslint:recommended', 'google'), {
|
|
47
|
+
plugins: {
|
|
48
|
+
'local-rules': localRules,
|
|
49
|
+
'import': fixupPluginRules(_import),
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
languageOptions: {
|
|
53
|
+
globals: {
|
|
54
|
+
...globals.node,
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
parser: tsParser,
|
|
58
|
+
ecmaVersion: 2020,
|
|
59
|
+
sourceType: 'module',
|
|
60
|
+
|
|
61
|
+
parserOptions: {
|
|
62
|
+
ecmaFeatures: {
|
|
63
|
+
globalReturn: true,
|
|
64
|
+
jsx: false,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
rules: {
|
|
70
|
+
'import/order': [2, {
|
|
71
|
+
'groups': ['builtin', 'external', ['sibling', 'parent'], 'index', 'object', 'type'],
|
|
72
|
+
'newlines-between': 'always',
|
|
73
|
+
}],
|
|
74
|
+
|
|
75
|
+
'import/group-exports': 2,
|
|
76
|
+
'import/exports-last': 2,
|
|
77
|
+
'eqeqeq': 2,
|
|
78
|
+
'no-console': 2,
|
|
79
|
+
|
|
80
|
+
'indent': [2, 2, {
|
|
81
|
+
SwitchCase: 1,
|
|
82
|
+
VariableDeclarator: 2,
|
|
83
|
+
|
|
84
|
+
CallExpression: {
|
|
85
|
+
arguments: 'off',
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
MemberExpression: 'off',
|
|
89
|
+
|
|
90
|
+
FunctionExpression: {
|
|
91
|
+
body: 1,
|
|
92
|
+
parameters: 2,
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
ignoredNodes: [
|
|
96
|
+
'ConditionalExpression > :matches(.consequent, .alternate)',
|
|
97
|
+
'VariableDeclarator > ArrowFunctionExpression > :expression.body',
|
|
98
|
+
'CallExpression > ArrowFunctionExpression > :expression.body',
|
|
99
|
+
],
|
|
100
|
+
}],
|
|
101
|
+
|
|
102
|
+
'no-floating-decimal': 2,
|
|
103
|
+
|
|
104
|
+
'max-len': [2, 100, {
|
|
105
|
+
ignorePattern: 'readJson\\(|^import ',
|
|
106
|
+
ignoreComments: true,
|
|
107
|
+
ignoreUrls: true,
|
|
108
|
+
tabWidth: 2,
|
|
109
|
+
}],
|
|
110
|
+
|
|
111
|
+
'no-empty': [2, {
|
|
112
|
+
allowEmptyCatch: true,
|
|
113
|
+
}],
|
|
114
|
+
|
|
115
|
+
'no-implicit-coercion': [2, {
|
|
116
|
+
boolean: false,
|
|
117
|
+
number: true,
|
|
118
|
+
string: true,
|
|
119
|
+
}],
|
|
120
|
+
|
|
121
|
+
'no-unused-expressions': [2, {
|
|
122
|
+
allowShortCircuit: true,
|
|
123
|
+
allowTernary: false,
|
|
124
|
+
}],
|
|
125
|
+
|
|
126
|
+
'no-unused-vars': [2, {
|
|
127
|
+
vars: 'all',
|
|
128
|
+
args: 'after-used',
|
|
129
|
+
caughtErrors: 'none', // TODO: remove for new "all" default.
|
|
130
|
+
argsIgnorePattern: '(^reject$|^_+$)',
|
|
131
|
+
varsIgnorePattern: '(^_$|^LH$|^Lantern$|^TraceEngine$|^Protocol$)',
|
|
132
|
+
}],
|
|
133
|
+
|
|
134
|
+
'no-cond-assign': 2,
|
|
135
|
+
'space-infix-ops': 2,
|
|
136
|
+
'strict': [2, 'global'],
|
|
137
|
+
'prefer-const': 2,
|
|
138
|
+
'curly': [2, 'multi-line'],
|
|
139
|
+
|
|
140
|
+
'comma-dangle': [2, {
|
|
141
|
+
arrays: 'always-multiline',
|
|
142
|
+
objects: 'always-multiline',
|
|
143
|
+
imports: 'always-multiline',
|
|
144
|
+
exports: 'always-multiline',
|
|
145
|
+
functions: 'never',
|
|
146
|
+
}],
|
|
147
|
+
|
|
148
|
+
'operator-linebreak': ['error', 'after', {
|
|
149
|
+
overrides: {
|
|
150
|
+
'?': 'ignore',
|
|
151
|
+
':': 'ignore',
|
|
152
|
+
},
|
|
153
|
+
}],
|
|
154
|
+
|
|
155
|
+
'local-rules/require-file-extension': 2,
|
|
156
|
+
'require-jsdoc': 0,
|
|
157
|
+
'valid-jsdoc': 0,
|
|
158
|
+
'arrow-parens': 0,
|
|
159
|
+
},
|
|
160
|
+
}, {
|
|
161
|
+
files: ['cli/test/smokehouse/test-definitions/**'],
|
|
162
|
+
|
|
163
|
+
rules: {
|
|
164
|
+
'max-len': 0,
|
|
165
|
+
},
|
|
166
|
+
}, {
|
|
167
|
+
files: [
|
|
168
|
+
'**/build/**',
|
|
169
|
+
'**/scripts/**',
|
|
170
|
+
'**/test/**',
|
|
171
|
+
],
|
|
172
|
+
|
|
173
|
+
rules: {
|
|
174
|
+
'no-console': 0,
|
|
175
|
+
},
|
|
176
|
+
}, {
|
|
177
|
+
files: [
|
|
178
|
+
'docs/recipes/auth/**',
|
|
179
|
+
],
|
|
180
|
+
|
|
181
|
+
rules: {
|
|
182
|
+
'new-cap': 0,
|
|
183
|
+
'no-console': 0,
|
|
184
|
+
'no-unused-vars': 0,
|
|
185
|
+
},
|
|
186
|
+
}, {
|
|
187
|
+
files: [
|
|
188
|
+
'**/test/**',
|
|
189
|
+
'docs/recipes/**',
|
|
190
|
+
],
|
|
191
|
+
|
|
192
|
+
languageOptions: {
|
|
193
|
+
globals: {
|
|
194
|
+
...globals.jest,
|
|
195
|
+
...globals.mocha,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
}, {
|
|
199
|
+
files: [
|
|
200
|
+
'clients/**',
|
|
201
|
+
'core/gather/gatherers/**',
|
|
202
|
+
'docs/recipes/auth/**',
|
|
203
|
+
'flow-report/**',
|
|
204
|
+
'report/**',
|
|
205
|
+
'treemap/**',
|
|
206
|
+
'viewer/**',
|
|
207
|
+
],
|
|
208
|
+
ignores: [
|
|
209
|
+
'report/generator/**',
|
|
210
|
+
'report/test/generator/**',
|
|
211
|
+
],
|
|
212
|
+
|
|
213
|
+
languageOptions: {
|
|
214
|
+
globals: {
|
|
215
|
+
...globals.browser,
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
}, {
|
|
219
|
+
files: [
|
|
220
|
+
'clients/**',
|
|
221
|
+
],
|
|
222
|
+
|
|
223
|
+
languageOptions: {
|
|
224
|
+
globals: {
|
|
225
|
+
chrome: true,
|
|
226
|
+
__lighthouse: true,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
}, {
|
|
230
|
+
files: ['flow-report/**'],
|
|
231
|
+
|
|
232
|
+
languageOptions: {
|
|
233
|
+
globals: {
|
|
234
|
+
...globals.browser,
|
|
235
|
+
...globals.node,
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
rules: {
|
|
240
|
+
'no-undef': 'off',
|
|
241
|
+
},
|
|
242
|
+
}];
|
|
@@ -26,6 +26,7 @@ function useLhrLocale() {
|
|
|
26
26
|
const locale = firstLhr.configSettings.locale;
|
|
27
27
|
|
|
28
28
|
if (flowResult.steps.some(step => step.lhr.configSettings.locale !== locale)) {
|
|
29
|
+
// eslint-disable-next-line no-console
|
|
29
30
|
console.warn('LHRs have inconsistent locales');
|
|
30
31
|
}
|
|
31
32
|
|
package/flow-report/src/util.ts
CHANGED
|
@@ -97,12 +97,14 @@ function useHashState(): LH.HashState|null {
|
|
|
97
97
|
|
|
98
98
|
const index = Number(indexString);
|
|
99
99
|
if (!Number.isFinite(index)) {
|
|
100
|
+
// eslint-disable-next-line no-console
|
|
100
101
|
console.warn(`Invalid hash index: ${indexString}`);
|
|
101
102
|
return null;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
105
|
const step = flowResult.steps[index];
|
|
105
106
|
if (!step) {
|
|
107
|
+
// eslint-disable-next-line no-console
|
|
106
108
|
console.warn(`No flow step at index ${index}`);
|
|
107
109
|
return null;
|
|
108
110
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "12.6.1-dev.
|
|
4
|
+
"version": "12.6.1-dev.20250613",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -105,6 +105,9 @@
|
|
|
105
105
|
"@build-tracker/cli": "^1.0.0-beta.15",
|
|
106
106
|
"@esbuild-kit/esm-loader": "^2.1.1",
|
|
107
107
|
"@esbuild-plugins/node-modules-polyfill": "^0.1.4",
|
|
108
|
+
"@eslint/compat": "^1.3.0",
|
|
109
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
110
|
+
"@eslint/js": "^9.28.0",
|
|
108
111
|
"@formatjs/icu-messageformat-parser": "^2.6.2",
|
|
109
112
|
"@jest/fake-timers": "^29.7.0",
|
|
110
113
|
"@testing-library/preact": "^3.1.1",
|
|
@@ -114,7 +117,7 @@
|
|
|
114
117
|
"@types/configstore": "^6.0.2",
|
|
115
118
|
"@types/cpy": "^5.1.0",
|
|
116
119
|
"@types/debug": "^4.1.7",
|
|
117
|
-
"@types/eslint": "^
|
|
120
|
+
"@types/eslint": "^9.6.1",
|
|
118
121
|
"@types/estree": "^0.0.50",
|
|
119
122
|
"@types/gh-pages": "^2.0.0",
|
|
120
123
|
"@types/google.analytics": "0.0.39",
|
|
@@ -131,8 +134,8 @@
|
|
|
131
134
|
"@types/ws": "^7.0.0",
|
|
132
135
|
"@types/yargs": "^17.0.8",
|
|
133
136
|
"@types/yargs-parser": "^20.2.1",
|
|
134
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
135
|
-
"@typescript-eslint/parser": "^
|
|
137
|
+
"@typescript-eslint/eslint-plugin": "^8.34.0",
|
|
138
|
+
"@typescript-eslint/parser": "^8.34.0",
|
|
136
139
|
"acorn": "^8.5.0",
|
|
137
140
|
"angular": "^1.7.4",
|
|
138
141
|
"archiver": "^3.0.0",
|
|
@@ -149,7 +152,7 @@
|
|
|
149
152
|
"csv-validator": "^0.0.3",
|
|
150
153
|
"es-main": "^1.2.0",
|
|
151
154
|
"esbuild": "0.19.11",
|
|
152
|
-
"eslint": "^
|
|
155
|
+
"eslint": "^9.28.0",
|
|
153
156
|
"eslint-config-google": "^0.14.0",
|
|
154
157
|
"eslint-formatter-codeframe": "^7.32.1",
|
|
155
158
|
"eslint-plugin-import": "^2.25.3",
|
|
@@ -159,6 +162,7 @@
|
|
|
159
162
|
"firebase": "^9.0.2",
|
|
160
163
|
"gh-pages": "^2.0.1",
|
|
161
164
|
"glob": "^7.1.3",
|
|
165
|
+
"globals": "^15.14.0",
|
|
162
166
|
"idb-keyval": "2.2.0",
|
|
163
167
|
"jest-mock": "^29.7.0",
|
|
164
168
|
"jest-snapshot": "^29.7.0",
|
|
@@ -186,7 +190,7 @@
|
|
|
186
190
|
},
|
|
187
191
|
"dependencies": {
|
|
188
192
|
"@paulirish/trace_engine": "0.0.53",
|
|
189
|
-
"@sentry/node": "^
|
|
193
|
+
"@sentry/node": "^9.28.1",
|
|
190
194
|
"axe-core": "^4.10.3",
|
|
191
195
|
"chrome-launcher": "^1.2.0",
|
|
192
196
|
"configstore": "^7.0.0",
|
|
@@ -7,6 +7,11 @@ export function getLhrFilenamePrefix(lhr: {
|
|
|
7
7
|
finalDisplayedUrl: string;
|
|
8
8
|
fetchTime: string;
|
|
9
9
|
}): string;
|
|
10
|
+
/**
|
|
11
|
+
* @license
|
|
12
|
+
* Copyright 2017 Google LLC
|
|
13
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
14
|
+
*/
|
|
10
15
|
/**
|
|
11
16
|
* @fileoverview
|
|
12
17
|
* @suppress {reportUnknownTypes}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright 2017 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
|
|
8
8
|
import {reportAssets} from './report-assets.js';
|
|
9
9
|
|
|
@@ -69,11 +69,11 @@ class ReportGenerator {
|
|
|
69
69
|
// we want to generate a report without minification.
|
|
70
70
|
const sanitizedJavascript = reportAssets.FLOW_REPORT_JAVASCRIPT.replace(/<\//g, '\\u003c/');
|
|
71
71
|
return ReportGenerator.replaceStrings(reportAssets.FLOW_REPORT_TEMPLATE, [
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
{search: '%%LIGHTHOUSE_FLOW_JSON%%', replacement: sanitizedJson},
|
|
74
74
|
{search: '%%LIGHTHOUSE_FLOW_JAVASCRIPT%%', replacement: sanitizedJavascript},
|
|
75
75
|
{search: '/*%%LIGHTHOUSE_FLOW_CSS%%*/', replacement: reportAssets.FLOW_REPORT_CSS},
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
]);
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -31,6 +31,7 @@ export class I18nFormatter {
|
|
|
31
31
|
if (granularity !== undefined) {
|
|
32
32
|
const log10 = -Math.log10(granularity);
|
|
33
33
|
if (!Number.isInteger(log10)) {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
34
35
|
console.warn(`granularity of ${granularity} is invalid. Using 1 instead`);
|
|
35
36
|
granularity = 1;
|
|
36
37
|
}
|
|
@@ -50,7 +51,7 @@ export class I18nFormatter {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
let formatter;
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
const cacheKey = [
|
|
55
56
|
opts.minimumFractionDigits,
|
|
56
57
|
opts.maximumFractionDigits,
|
|
@@ -37,6 +37,7 @@ export class ReportRenderer {
|
|
|
37
37
|
renderReport(lhr, rootEl, opts) {
|
|
38
38
|
// Allow legacy report rendering API
|
|
39
39
|
if (!this._dom.rootEl && rootEl) {
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
40
41
|
console.warn('Please adopt the new report API in renderer/api.js.');
|
|
41
42
|
const closestRoot = rootEl.closest('.lh-root');
|
|
42
43
|
if (closestRoot) {
|
|
@@ -159,6 +159,7 @@ class ReportUtils {
|
|
|
159
159
|
const aVal = a[key];
|
|
160
160
|
const bVal = b[key];
|
|
161
161
|
if (typeof aVal !== typeof bVal || !['number', 'string'].includes(typeof aVal)) {
|
|
162
|
+
// eslint-disable-next-line no-console
|
|
162
163
|
console.warn(`Warning: Attempting to sort unsupported value type: ${key}.`);
|
|
163
164
|
}
|
|
164
165
|
if (typeof aVal === 'number' && typeof bVal === 'number' && aVal !== bVal) {
|
|
@@ -191,7 +192,7 @@ class ReportUtils {
|
|
|
191
192
|
break;
|
|
192
193
|
case 'devtools': {
|
|
193
194
|
const {cpuSlowdownMultiplier, requestLatencyMs} = throttling;
|
|
194
|
-
|
|
195
|
+
|
|
195
196
|
cpuThrottling = `${i18n.formatNumber(cpuSlowdownMultiplier)}x slowdown (DevTools)`;
|
|
196
197
|
networkThrottling = `${i18n.formatMilliseconds(requestLatencyMs)} HTTP RTT, ` +
|
|
197
198
|
`${i18n.formatKbps(throttling.downloadThroughputKbps)} down, ` +
|
|
@@ -207,7 +208,7 @@ class ReportUtils {
|
|
|
207
208
|
}
|
|
208
209
|
case 'simulate': {
|
|
209
210
|
const {cpuSlowdownMultiplier, rttMs, throughputKbps} = throttling;
|
|
210
|
-
|
|
211
|
+
|
|
211
212
|
cpuThrottling = `${i18n.formatNumber(cpuSlowdownMultiplier)}x slowdown (Simulated)`;
|
|
212
213
|
networkThrottling = `${i18n.formatMilliseconds(rttMs)} TCP RTT, ` +
|
|
213
214
|
`${i18n.formatKbps(throughputKbps)} throughput (Simulated)`;
|