lighthouse 10.2.0 → 10.3.0-dev.20230614
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/__snapshots__/report-assert-test.js.snap +4 -6
- package/core/audits/accessibility/html-xml-lang-mismatch.d.ts +10 -0
- package/core/audits/accessibility/html-xml-lang-mismatch.js +47 -0
- package/core/audits/accessibility/input-button-name.d.ts +10 -0
- package/core/audits/accessibility/input-button-name.js +44 -0
- package/core/audits/accessibility/table-fake-caption.d.ts +10 -0
- package/core/audits/accessibility/table-fake-caption.js +47 -0
- package/core/audits/accessibility/td-has-header.d.ts +10 -0
- package/core/audits/accessibility/td-has-header.js +45 -0
- package/core/audits/audit.d.ts +2 -1
- package/core/audits/audit.js +5 -2
- package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +3 -3
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +14 -19
- package/core/audits/deprecations.js +1 -1
- package/core/audits/largest-contentful-paint-element.d.ts +14 -2
- package/core/audits/largest-contentful-paint-element.js +49 -31
- package/core/audits/layout-shift-elements.d.ts +3 -2
- package/core/audits/layout-shift-elements.js +10 -2
- package/core/audits/metrics.js +0 -2
- package/core/audits/network-requests.js +6 -0
- package/core/audits/seo/crawlable-anchors.js +4 -0
- package/core/audits/server-response-time.d.ts +2 -1
- package/core/audits/server-response-time.js +17 -3
- package/core/audits/uses-rel-preconnect.js +20 -4
- package/core/computed/entity-classification.d.ts +14 -1
- package/core/computed/entity-classification.js +61 -6
- package/core/computed/metrics/cumulative-layout-shift.d.ts +2 -9
- package/core/computed/metrics/cumulative-layout-shift.js +3 -16
- package/core/computed/metrics/time-to-first-byte.js +10 -7
- package/core/computed/metrics/timing-summary.js +0 -3
- package/core/config/default-config.js +8 -0
- package/core/gather/driver/execution-context.js +13 -5
- package/core/gather/driver/target-manager.d.ts +13 -0
- package/core/gather/driver/target-manager.js +49 -0
- package/core/gather/gatherers/accessibility.js +19 -20
- package/core/gather/gatherers/anchor-elements.js +2 -0
- package/core/gather/gatherers/global-listeners.js +38 -21
- package/core/gather/gatherers/inspector-issues.js +2 -1
- package/core/gather/gatherers/trace-elements.d.ts +3 -2
- package/core/gather/gatherers/trace-elements.js +10 -19
- package/core/legacy/config/config.d.ts +1 -1
- package/core/legacy/config/config.js +1 -1
- package/core/legacy/gather/driver.d.ts +1 -0
- package/core/legacy/gather/driver.js +11 -0
- package/core/lib/asset-saver.d.ts +4 -0
- package/core/lib/asset-saver.js +19 -0
- package/core/lib/bf-cache-strings.d.ts +3 -0
- package/core/lib/bf-cache-strings.js +248 -232
- package/core/lib/cdt/generated/SourceMap.d.ts +18 -31
- package/core/lib/cdt/generated/SourceMap.js +51 -101
- package/core/lib/dependency-graph/simulator/network-analyzer.d.ts +6 -2
- package/core/lib/dependency-graph/simulator/network-analyzer.js +45 -13
- package/core/lib/deprecation-description.d.ts +17 -0
- package/core/lib/deprecation-description.js +71 -0
- package/core/lib/deprecations-strings.d.ts +282 -63
- package/core/lib/deprecations-strings.js +282 -551
- package/core/lib/lh-error.d.ts +9 -4
- package/core/lib/lh-error.js +15 -11
- package/core/lib/network-request.d.ts +13 -6
- package/core/lib/network-request.js +39 -14
- package/core/lib/stack-packs.js +4 -0
- package/core/lib/tracehouse/trace-processor.js +1 -1
- package/core/lib/url-utils.js +4 -0
- package/core/runner.js +4 -2
- package/dist/report/bundle.esm.js +24 -7
- package/dist/report/flow.js +3 -3
- package/dist/report/standalone.js +8 -8
- package/package.json +13 -13
- package/readme.md +7 -0
- package/report/assets/styles.css +18 -2
- package/report/assets/templates.html +4 -0
- package/report/renderer/category-renderer.js +5 -2
- package/report/renderer/components.js +2 -2
- package/report/renderer/dom.d.ts +4 -1
- package/report/renderer/dom.js +3 -2
- package/shared/localization/locales/ar-XB.json +20 -170
- package/shared/localization/locales/ar.json +20 -170
- package/shared/localization/locales/bg.json +19 -169
- package/shared/localization/locales/ca.json +19 -169
- package/shared/localization/locales/cs.json +19 -169
- package/shared/localization/locales/da.json +19 -169
- package/shared/localization/locales/de.json +19 -169
- package/shared/localization/locales/el.json +19 -169
- package/shared/localization/locales/en-GB.json +9 -159
- package/shared/localization/locales/en-US.json +166 -70
- package/shared/localization/locales/en-XA.json +20 -170
- package/shared/localization/locales/en-XL.json +166 -70
- package/shared/localization/locales/es-419.json +19 -169
- package/shared/localization/locales/es.json +19 -169
- package/shared/localization/locales/fi.json +19 -169
- package/shared/localization/locales/fil.json +17 -167
- package/shared/localization/locales/fr.json +18 -168
- package/shared/localization/locales/he.json +19 -169
- package/shared/localization/locales/hi.json +20 -170
- package/shared/localization/locales/hr.json +19 -169
- package/shared/localization/locales/hu.json +19 -169
- package/shared/localization/locales/id.json +19 -169
- package/shared/localization/locales/it.json +19 -169
- package/shared/localization/locales/ja.json +19 -169
- package/shared/localization/locales/ko.json +19 -169
- package/shared/localization/locales/lt.json +20 -170
- package/shared/localization/locales/lv.json +20 -170
- package/shared/localization/locales/nl.json +18 -168
- package/shared/localization/locales/no.json +19 -169
- package/shared/localization/locales/pl.json +19 -169
- package/shared/localization/locales/pt-PT.json +19 -169
- package/shared/localization/locales/pt.json +19 -169
- package/shared/localization/locales/ro.json +19 -169
- package/shared/localization/locales/ru.json +19 -169
- package/shared/localization/locales/sk.json +20 -170
- package/shared/localization/locales/sl.json +19 -169
- package/shared/localization/locales/sr-Latn.json +19 -169
- package/shared/localization/locales/sr.json +19 -169
- package/shared/localization/locales/sv.json +19 -169
- package/shared/localization/locales/ta.json +19 -169
- package/shared/localization/locales/te.json +19 -169
- package/shared/localization/locales/th.json +19 -169
- package/shared/localization/locales/tr.json +19 -169
- package/shared/localization/locales/uk.json +19 -169
- package/shared/localization/locales/vi.json +20 -170
- package/shared/localization/locales/zh-HK.json +19 -169
- package/shared/localization/locales/zh-TW.json +19 -169
- package/shared/localization/locales/zh.json +19 -169
- package/shared/util.d.ts +6 -0
- package/shared/util.js +14 -1
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -1
- package/tsconfig-base.json +1 -1
- package/types/artifacts.d.ts +10 -8
- package/types/audit.d.ts +5 -0
- package/types/gatherer.d.ts +1 -0
- package/types/lhr/audit-details.d.ts +1 -0
- package/types/lhr/audit-result.d.ts +10 -0
- package/types/internal/es-main.d.ts +0 -18
package/core/lib/lh-error.d.ts
CHANGED
|
@@ -8,20 +8,24 @@ export type LighthouseErrorDefinition = {
|
|
|
8
8
|
lhrRuntimeError?: boolean | undefined;
|
|
9
9
|
};
|
|
10
10
|
export type SerializedLighthouseError = {
|
|
11
|
-
[p: string]: string | undefined;
|
|
12
11
|
sentinel: '__LighthouseErrorSentinel';
|
|
13
12
|
code: string;
|
|
14
13
|
stack?: string | undefined;
|
|
14
|
+
cause?: unknown;
|
|
15
|
+
properties?: {
|
|
16
|
+
[p: string]: string | undefined;
|
|
17
|
+
} | undefined;
|
|
15
18
|
};
|
|
16
19
|
export type SerializedBaseError = {
|
|
17
20
|
sentinel: '__ErrorSentinel';
|
|
18
21
|
message: string;
|
|
19
22
|
code?: string;
|
|
20
23
|
stack?: string;
|
|
24
|
+
cause?: unknown;
|
|
21
25
|
};
|
|
22
26
|
/**
|
|
23
|
-
* @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, [p: string]: string|undefined}} SerializedLighthouseError
|
|
24
|
-
* @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string}} SerializedBaseError
|
|
27
|
+
* @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, cause?: unknown, properties?: {[p: string]: string|undefined}}} SerializedLighthouseError
|
|
28
|
+
* @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string, cause?: unknown}} SerializedBaseError
|
|
25
29
|
*/
|
|
26
30
|
export class LighthouseError extends Error {
|
|
27
31
|
/**
|
|
@@ -55,8 +59,9 @@ export class LighthouseError extends Error {
|
|
|
55
59
|
/**
|
|
56
60
|
* @param {LighthouseErrorDefinition} errorDefinition
|
|
57
61
|
* @param {Record<string, string|undefined>=} properties
|
|
62
|
+
* @param {ErrorOptions=} options
|
|
58
63
|
*/
|
|
59
|
-
constructor(errorDefinition: LighthouseErrorDefinition, properties?: Record<string, string | undefined> | undefined);
|
|
64
|
+
constructor(errorDefinition: LighthouseErrorDefinition, properties?: Record<string, string | undefined> | undefined, options?: ErrorOptions | undefined);
|
|
60
65
|
code: string;
|
|
61
66
|
friendlyMessage: import("../index.js").IcuMessage;
|
|
62
67
|
lhrRuntimeError: boolean;
|
package/core/lib/lh-error.js
CHANGED
|
@@ -107,17 +107,18 @@ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
|
|
|
107
107
|
const LHERROR_SENTINEL = '__LighthouseErrorSentinel';
|
|
108
108
|
const ERROR_SENTINEL = '__ErrorSentinel';
|
|
109
109
|
/**
|
|
110
|
-
* @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, [p: string]: string|undefined}} SerializedLighthouseError
|
|
111
|
-
* @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string}} SerializedBaseError
|
|
110
|
+
* @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, cause?: unknown, properties?: {[p: string]: string|undefined}}} SerializedLighthouseError
|
|
111
|
+
* @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string, cause?: unknown}} SerializedBaseError
|
|
112
112
|
*/
|
|
113
113
|
|
|
114
114
|
class LighthouseError extends Error {
|
|
115
115
|
/**
|
|
116
116
|
* @param {LighthouseErrorDefinition} errorDefinition
|
|
117
117
|
* @param {Record<string, string|undefined>=} properties
|
|
118
|
+
* @param {ErrorOptions=} options
|
|
118
119
|
*/
|
|
119
|
-
constructor(errorDefinition, properties) {
|
|
120
|
-
super(errorDefinition.code);
|
|
120
|
+
constructor(errorDefinition, properties, options) {
|
|
121
|
+
super(errorDefinition.code, options);
|
|
121
122
|
this.name = 'LighthouseError';
|
|
122
123
|
this.code = errorDefinition.code;
|
|
123
124
|
// Add additional properties to be ICU replacements in the error string.
|
|
@@ -163,19 +164,20 @@ class LighthouseError extends Error {
|
|
|
163
164
|
if (err instanceof LighthouseError) {
|
|
164
165
|
// Remove class props so that remaining values were what was passed in as `properties`.
|
|
165
166
|
// eslint-disable-next-line no-unused-vars
|
|
166
|
-
const {name, code, message, friendlyMessage, lhrRuntimeError, stack, ...properties} = err;
|
|
167
|
+
const {name, code, message, friendlyMessage, lhrRuntimeError, stack, cause, ...properties} = err;
|
|
167
168
|
|
|
168
169
|
return {
|
|
169
170
|
sentinel: LHERROR_SENTINEL,
|
|
170
171
|
code,
|
|
171
172
|
stack,
|
|
172
|
-
|
|
173
|
+
cause,
|
|
174
|
+
properties: /** @type {{ [p: string]: string | undefined }} */ (properties),
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
// Unexpected errors won't be LighthouseErrors, but we want them serialized as well.
|
|
177
179
|
if (err instanceof Error) {
|
|
178
|
-
const {message, stack} = err;
|
|
180
|
+
const {message, stack, cause} = err;
|
|
179
181
|
// @ts-expect-error - code can be helpful for e.g. node errors, so preserve it if it's present.
|
|
180
182
|
const code = err.code;
|
|
181
183
|
return {
|
|
@@ -183,6 +185,7 @@ class LighthouseError extends Error {
|
|
|
183
185
|
message,
|
|
184
186
|
code,
|
|
185
187
|
stack,
|
|
188
|
+
cause,
|
|
186
189
|
};
|
|
187
190
|
}
|
|
188
191
|
|
|
@@ -203,17 +206,18 @@ class LighthouseError extends Error {
|
|
|
203
206
|
if (possibleError.sentinel === LHERROR_SENTINEL) {
|
|
204
207
|
// Include sentinel in destructuring so it doesn't end up in `properties`.
|
|
205
208
|
// eslint-disable-next-line no-unused-vars
|
|
206
|
-
const {
|
|
209
|
+
const {code, stack, cause, properties} = /** @type {SerializedLighthouseError} */ (possibleError);
|
|
207
210
|
const errorDefinition = LighthouseError.errors[/** @type {keyof typeof ERRORS} */ (code)];
|
|
208
|
-
const lhError = new LighthouseError(errorDefinition, properties);
|
|
211
|
+
const lhError = new LighthouseError(errorDefinition, properties, {cause});
|
|
209
212
|
lhError.stack = stack;
|
|
210
213
|
|
|
211
214
|
return lhError;
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
if (possibleError.sentinel === ERROR_SENTINEL) {
|
|
215
|
-
const {message, code, stack} = /** @type {SerializedBaseError} */ (possibleError);
|
|
216
|
-
const
|
|
218
|
+
const {message, code, stack, cause} = /** @type {SerializedBaseError} */ (possibleError);
|
|
219
|
+
const opts = cause ? {cause} : undefined;
|
|
220
|
+
const error = new Error(message, opts);
|
|
217
221
|
Object.assign(error, {code, stack});
|
|
218
222
|
return error;
|
|
219
223
|
}
|
|
@@ -13,22 +13,22 @@ export type ParsedURL = {
|
|
|
13
13
|
host: string;
|
|
14
14
|
securityOrigin: string;
|
|
15
15
|
};
|
|
16
|
-
/**
|
|
17
|
-
* The difference in networkEndTime between the observed Lighthouse networkEndTime and Lightrider's derived networkEndTime.
|
|
18
|
-
*/
|
|
19
16
|
export type LightriderStatistics = {
|
|
20
17
|
/**
|
|
21
|
-
* The
|
|
18
|
+
* The difference in networkEndTime between the observed Lighthouse networkEndTime and Lightrider's derived networkEndTime.
|
|
22
19
|
*/
|
|
23
20
|
endTimeDeltaMs: number;
|
|
24
21
|
/**
|
|
25
|
-
* The time spent
|
|
22
|
+
* The time spent making a TCP connection (connect + SSL). Note: this is poorly named.
|
|
26
23
|
*/
|
|
27
24
|
TCPMs: number;
|
|
28
25
|
/**
|
|
29
|
-
* The time spent
|
|
26
|
+
* The time spent requesting a resource from a remote server, we use this to approx RTT. Note: this is poorly names, it really should be "server response time".
|
|
30
27
|
*/
|
|
31
28
|
requestMs: number;
|
|
29
|
+
/**
|
|
30
|
+
* Time to receive the entire response payload starting the clock on receiving the first fragment (first non-header byte).
|
|
31
|
+
*/
|
|
32
32
|
responseMs: number;
|
|
33
33
|
};
|
|
34
34
|
export class NetworkRequest {
|
|
@@ -219,6 +219,13 @@ export class NetworkRequest {
|
|
|
219
219
|
* LR loses protocol information.
|
|
220
220
|
*/
|
|
221
221
|
_updateProtocolForLightrider(): void;
|
|
222
|
+
/**
|
|
223
|
+
* TODO(compat): remove M116.
|
|
224
|
+
* `timing.receiveHeadersStart` was added recently, and will be in M116. Until then,
|
|
225
|
+
* set it to receiveHeadersEnd, which is close enough, to allow consumers of NetworkRequest
|
|
226
|
+
* to use the new field without accounting for this backcompat.
|
|
227
|
+
*/
|
|
228
|
+
_backfillReceiveHeaderStartTiming(): void;
|
|
222
229
|
/**
|
|
223
230
|
* LR gets additional, accurate timing information from its underlying fetch infrastructure. This
|
|
224
231
|
* is passed in via X-Headers similar to 'X-TotalFetchedSize'.
|
|
@@ -57,7 +57,7 @@ import UrlUtils from './url-utils.js';
|
|
|
57
57
|
|
|
58
58
|
// Lightrider X-Header names for timing information.
|
|
59
59
|
// See: _updateTransferSizeForLightrider and _updateTimingsForLightrider.
|
|
60
|
-
const HEADER_TCP = 'X-TCPMs';
|
|
60
|
+
const HEADER_TCP = 'X-TCPMs'; // Note: this should have been called something like ConnectMs, as it includes SSL.
|
|
61
61
|
const HEADER_SSL = 'X-SSLMs';
|
|
62
62
|
const HEADER_REQ = 'X-RequestMs';
|
|
63
63
|
const HEADER_RES = 'X-ResponseMs';
|
|
@@ -80,14 +80,10 @@ const HEADER_PROTOCOL_IS_H2 = 'X-ProtocolIsH2';
|
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* @typedef LightriderStatistics
|
|
83
|
-
* The difference in networkEndTime between the observed Lighthouse networkEndTime and Lightrider's derived networkEndTime.
|
|
84
|
-
* @property {number}
|
|
85
|
-
* The time spent
|
|
86
|
-
* @property {number}
|
|
87
|
-
* The time spent requesting a resource from a remote server, we use this to approx RTT.
|
|
88
|
-
* @property {number} requestMs
|
|
89
|
-
* The time spent transferring a resource from a remote server.
|
|
90
|
-
* @property {number} responseMs
|
|
83
|
+
* @property {number} endTimeDeltaMs The difference in networkEndTime between the observed Lighthouse networkEndTime and Lightrider's derived networkEndTime.
|
|
84
|
+
* @property {number} TCPMs The time spent making a TCP connection (connect + SSL). Note: this is poorly named.
|
|
85
|
+
* @property {number} requestMs The time spent requesting a resource from a remote server, we use this to approx RTT. Note: this is poorly names, it really should be "server response time".
|
|
86
|
+
* @property {number} responseMs Time to receive the entire response payload starting the clock on receiving the first fragment (first non-header byte).
|
|
91
87
|
*/
|
|
92
88
|
|
|
93
89
|
/** @type {LH.Util.SelfMap<LH.Crdp.Network.ResourceType>} */
|
|
@@ -274,6 +270,7 @@ class NetworkRequest {
|
|
|
274
270
|
}
|
|
275
271
|
|
|
276
272
|
this._updateResponseHeadersEndTimeIfNecessary();
|
|
273
|
+
this._backfillReceiveHeaderStartTiming();
|
|
277
274
|
this._updateTransferSizeForLightrider();
|
|
278
275
|
this._updateTimingsForLightrider();
|
|
279
276
|
}
|
|
@@ -293,6 +290,7 @@ class NetworkRequest {
|
|
|
293
290
|
this.localizedFailDescription = data.errorText;
|
|
294
291
|
|
|
295
292
|
this._updateResponseHeadersEndTimeIfNecessary();
|
|
293
|
+
this._backfillReceiveHeaderStartTiming();
|
|
296
294
|
this._updateTransferSizeForLightrider();
|
|
297
295
|
this._updateTimingsForLightrider();
|
|
298
296
|
}
|
|
@@ -315,6 +313,7 @@ class NetworkRequest {
|
|
|
315
313
|
this.networkEndTime = data.timestamp * 1000;
|
|
316
314
|
|
|
317
315
|
this._updateResponseHeadersEndTimeIfNecessary();
|
|
316
|
+
this._backfillReceiveHeaderStartTiming();
|
|
318
317
|
}
|
|
319
318
|
|
|
320
319
|
/**
|
|
@@ -341,6 +340,7 @@ class NetworkRequest {
|
|
|
341
340
|
|
|
342
341
|
if (response.protocol) this.protocol = response.protocol;
|
|
343
342
|
|
|
343
|
+
// This is updated in _recomputeTimesWithResourceTiming, if timings are present.
|
|
344
344
|
this.responseHeadersEndTime = timestamp * 1000;
|
|
345
345
|
|
|
346
346
|
this.transferSize = response.encodedDataLength;
|
|
@@ -372,16 +372,27 @@ class NetworkRequest {
|
|
|
372
372
|
// Don't recompute times if the data is invalid. RequestTime should always be a thread timestamp.
|
|
373
373
|
// If we don't have receiveHeadersEnd, we really don't have more accurate data.
|
|
374
374
|
if (timing.requestTime === 0 || timing.receiveHeadersEnd === -1) return;
|
|
375
|
+
|
|
375
376
|
// Take networkRequestTime and responseHeadersEndTime from timing data for better accuracy.
|
|
377
|
+
// Before this, networkRequestTime and responseHeadersEndTime were set to bogus values based on
|
|
378
|
+
// CDP event timestamps, though they should be somewhat close to the network timings.
|
|
379
|
+
// Note: requests served from cache never run this function, so they use the "bogus" values.
|
|
380
|
+
|
|
376
381
|
// Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis.
|
|
382
|
+
// See https://raw.githubusercontent.com/GoogleChrome/lighthouse/main/docs/Network-Timings.svg
|
|
377
383
|
this.networkRequestTime = timing.requestTime * 1000;
|
|
378
384
|
const headersReceivedTime = this.networkRequestTime + timing.receiveHeadersEnd;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
385
|
+
// This was set in `_onResponse` as that event's timestamp.
|
|
386
|
+
const responseTimestamp = this.responseHeadersEndTime;
|
|
387
|
+
|
|
388
|
+
// Update this.responseHeadersEndTime. All timing values from the netstack (timing) are well-ordered, and
|
|
389
|
+
// so are the timestamps from CDP (which this.responseHeadersEndTime belongs to). It shouldn't be possible
|
|
390
|
+
// that this timing from the netstack is greater than the onResponse timestamp, but just to ensure proper order
|
|
391
|
+
// is maintained we bound the new timing by the network request time and the response timestamp.
|
|
392
|
+
this.responseHeadersEndTime = headersReceivedTime;
|
|
393
|
+
this.responseHeadersEndTime = Math.min(this.responseHeadersEndTime, responseTimestamp);
|
|
384
394
|
this.responseHeadersEndTime = Math.max(this.responseHeadersEndTime, this.networkRequestTime);
|
|
395
|
+
|
|
385
396
|
// We're only at responseReceived (_onResponse) at this point.
|
|
386
397
|
// This networkEndTime may be redefined again after onLoading is done.
|
|
387
398
|
this.networkEndTime = Math.max(this.networkEndTime, this.responseHeadersEndTime);
|
|
@@ -437,6 +448,19 @@ class NetworkRequest {
|
|
|
437
448
|
}
|
|
438
449
|
}
|
|
439
450
|
|
|
451
|
+
/**
|
|
452
|
+
* TODO(compat): remove M116.
|
|
453
|
+
* `timing.receiveHeadersStart` was added recently, and will be in M116. Until then,
|
|
454
|
+
* set it to receiveHeadersEnd, which is close enough, to allow consumers of NetworkRequest
|
|
455
|
+
* to use the new field without accounting for this backcompat.
|
|
456
|
+
*/
|
|
457
|
+
_backfillReceiveHeaderStartTiming() {
|
|
458
|
+
// Do nothing if a value is already present!
|
|
459
|
+
if (!this.timing || this.timing.receiveHeadersStart !== undefined) return;
|
|
460
|
+
|
|
461
|
+
this.timing.receiveHeadersStart = this.timing.receiveHeadersEnd;
|
|
462
|
+
}
|
|
463
|
+
|
|
440
464
|
/**
|
|
441
465
|
* LR gets additional, accurate timing information from its underlying fetch infrastructure. This
|
|
442
466
|
* is passed in via X-Headers similar to 'X-TotalFetchedSize'.
|
|
@@ -473,6 +497,7 @@ class NetworkRequest {
|
|
|
473
497
|
|
|
474
498
|
// Make sure all times are initialized and are non-negative.
|
|
475
499
|
const TCPMs = TCPMsHeader ? Math.max(0, parseInt(TCPMsHeader.value)) : 0;
|
|
500
|
+
// This is missing for h2 requests, but present for h1. See b/283843975
|
|
476
501
|
const SSLMs = SSLMsHeader ? Math.max(0, parseInt(SSLMsHeader.value)) : 0;
|
|
477
502
|
const requestMs = requestMsHeader ? Math.max(0, parseInt(requestMsHeader.value)) : 0;
|
|
478
503
|
const responseMs = responseMsHeader ? Math.max(0, parseInt(responseMsHeader.value)) : 0;
|
package/core/lib/stack-packs.js
CHANGED
package/core/lib/url-utils.js
CHANGED
|
@@ -87,6 +87,10 @@ class UrlUtils {
|
|
|
87
87
|
static getOrigin(url) {
|
|
88
88
|
try {
|
|
89
89
|
const urlInfo = new URL(url);
|
|
90
|
+
if (urlInfo.protocol === 'chrome-extension:') {
|
|
91
|
+
// Chrome extensions return string "null" as origin, so we reconstruct the extension origin.
|
|
92
|
+
return Util.getChromeExtensionOrigin(url);
|
|
93
|
+
}
|
|
90
94
|
// check for both host and origin since some URLs schemes like data and file set origin to the
|
|
91
95
|
// string "null" instead of the object
|
|
92
96
|
return (urlInfo.host && urlInfo.origin) || null;
|
package/core/runner.js
CHANGED
|
@@ -429,7 +429,7 @@ class Runner {
|
|
|
429
429
|
|
|
430
430
|
// Create a friendlier display error and mark it as expected to avoid duplicates in Sentry
|
|
431
431
|
const error = new LighthouseError(LighthouseError.errors.ERRORED_REQUIRED_ARTIFACT,
|
|
432
|
-
{artifactName, errorMessage: artifactError.message});
|
|
432
|
+
{artifactName, errorMessage: artifactError.message}, {cause: artifactError});
|
|
433
433
|
// @ts-expect-error Non-standard property added to Error
|
|
434
434
|
error.expected = true;
|
|
435
435
|
throw error;
|
|
@@ -468,7 +468,9 @@ class Runner {
|
|
|
468
468
|
Sentry.captureException(err, {tags: {audit: audit.meta.id}, level: 'error'});
|
|
469
469
|
// Errors become error audit result.
|
|
470
470
|
const errorMessage = err.friendlyMessage ? err.friendlyMessage : err.message;
|
|
471
|
-
|
|
471
|
+
// Prefer the stack trace closest to the error.
|
|
472
|
+
const stack = err.cause?.stack ?? err.stack;
|
|
473
|
+
auditResult = Audit.generateErrorAuditResult(audit, errorMessage, stack);
|
|
472
474
|
}
|
|
473
475
|
|
|
474
476
|
log.timeEnd(status);
|