lighthouse 11.4.0-dev.20231218 → 11.4.0-dev.20231220
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 +14 -4
- package/core/audits/byte-efficiency/render-blocking-resources.d.ts +5 -4
- package/core/audits/byte-efficiency/render-blocking-resources.js +15 -9
- package/core/computed/metrics/cumulative-layout-shift.d.ts +20 -1
- package/core/computed/metrics/cumulative-layout-shift.js +74 -4
- package/core/gather/gatherers/dobetterweb/response-compression.js +1 -12
- package/core/gather/gatherers/trace.js +3 -3
- package/core/gather/navigation-runner.js +1 -1
- package/core/lib/network-request.js +10 -2
- package/core/lib/polyfill-dom-rect.d.ts +2 -0
- package/core/lib/polyfill-dom-rect.js +111 -0
- package/core/lib/trace-engine.d.ts +4 -0
- package/core/lib/trace-engine.js +16 -0
- package/package.json +2 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`getAssertionReport works (multiple failing) 1`] = `
|
|
4
4
|
"X difference at cumulative-layout-shift audit.details.items.length
|
|
5
5
|
expected: []
|
|
6
|
-
found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444}]
|
|
6
|
+
found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.13570762803819444,\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444},\\"newEngineResultDiffered\\":false}]
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
X difference at cumulative-layout-shift audit.details.blah
|
|
@@ -28,7 +28,12 @@ exports[`getAssertionReport works (multiple failing) 1`] = `
|
|
|
28
28
|
\\"type\\": \\"debugdata\\",
|
|
29
29
|
\\"items\\": [
|
|
30
30
|
{
|
|
31
|
-
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
|
|
31
|
+
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444,
|
|
32
|
+
\\"newEngineResult\\": {
|
|
33
|
+
\\"cumulativeLayoutShift\\": 0.13570762803819444,
|
|
34
|
+
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
|
|
35
|
+
},
|
|
36
|
+
\\"newEngineResultDiffered\\": false
|
|
32
37
|
}
|
|
33
38
|
]
|
|
34
39
|
}
|
|
@@ -38,7 +43,7 @@ exports[`getAssertionReport works (multiple failing) 1`] = `
|
|
|
38
43
|
exports[`getAssertionReport works (trivial failing) 1`] = `
|
|
39
44
|
"X difference at cumulative-layout-shift audit.details.items.length
|
|
40
45
|
expected: []
|
|
41
|
-
found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444}]
|
|
46
|
+
found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.13570762803819444,\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444},\\"newEngineResultDiffered\\":false}]
|
|
42
47
|
|
|
43
48
|
found result:
|
|
44
49
|
{
|
|
@@ -58,7 +63,12 @@ exports[`getAssertionReport works (trivial failing) 1`] = `
|
|
|
58
63
|
\\"type\\": \\"debugdata\\",
|
|
59
64
|
\\"items\\": [
|
|
60
65
|
{
|
|
61
|
-
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
|
|
66
|
+
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444,
|
|
67
|
+
\\"newEngineResult\\": {
|
|
68
|
+
\\"cumulativeLayoutShift\\": 0.13570762803819444,
|
|
69
|
+
\\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
|
|
70
|
+
},
|
|
71
|
+
\\"newEngineResultDiffered\\": false
|
|
62
72
|
}
|
|
63
73
|
]
|
|
64
74
|
}
|
|
@@ -6,15 +6,16 @@ declare class RenderBlockingResources extends Audit {
|
|
|
6
6
|
/**
|
|
7
7
|
* @param {LH.Artifacts} artifacts
|
|
8
8
|
* @param {LH.Audit.Context} context
|
|
9
|
-
* @return {Promise<{
|
|
9
|
+
* @return {Promise<{fcpWastedMs: number, lcpWastedMs: number, results: Array<{url: string, totalBytes: number, wastedMs: number}>}>}
|
|
10
10
|
*/
|
|
11
11
|
static computeResults(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<{
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
fcpWastedMs: number;
|
|
13
|
+
lcpWastedMs: number;
|
|
14
|
+
results: Array<{
|
|
14
15
|
url: string;
|
|
15
16
|
totalBytes: number;
|
|
16
17
|
wastedMs: number;
|
|
17
|
-
}
|
|
18
|
+
}>;
|
|
18
19
|
}>;
|
|
19
20
|
/**
|
|
20
21
|
* Estimates how much faster this page would reach FCP if we inlined all the used CSS from the
|
|
@@ -17,6 +17,8 @@ import {NetworkRequest} from '../../lib/network-request.js';
|
|
|
17
17
|
import {ProcessedNavigation} from '../../computed/processed-navigation.js';
|
|
18
18
|
import {LoadSimulator} from '../../computed/load-simulator.js';
|
|
19
19
|
import {FirstContentfulPaint} from '../../computed/metrics/first-contentful-paint.js';
|
|
20
|
+
import {LCPImageRecord} from '../../computed/lcp-image-record.js';
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
/** @typedef {import('../../lib/dependency-graph/simulator/simulator').Simulator} Simulator */
|
|
22
24
|
/** @typedef {import('../../lib/dependency-graph/base-node.js').Node} Node */
|
|
@@ -125,7 +127,7 @@ class RenderBlockingResources extends Audit {
|
|
|
125
127
|
/**
|
|
126
128
|
* @param {LH.Artifacts} artifacts
|
|
127
129
|
* @param {LH.Audit.Context} context
|
|
128
|
-
* @return {Promise<{
|
|
130
|
+
* @return {Promise<{fcpWastedMs: number, lcpWastedMs: number, results: Array<{url: string, totalBytes: number, wastedMs: number}>}>}
|
|
129
131
|
*/
|
|
130
132
|
static async computeResults(artifacts, context) {
|
|
131
133
|
const gatherContext = artifacts.GatherContext;
|
|
@@ -179,10 +181,10 @@ class RenderBlockingResources extends Audit {
|
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
if (!results.length) {
|
|
182
|
-
return {results,
|
|
184
|
+
return {results, fcpWastedMs: 0, lcpWastedMs: 0};
|
|
183
185
|
}
|
|
184
186
|
|
|
185
|
-
const
|
|
187
|
+
const fcpWastedMs = RenderBlockingResources.estimateSavingsWithGraphs(
|
|
186
188
|
simulator,
|
|
187
189
|
fcpSimulation.optimisticGraph,
|
|
188
190
|
deferredNodeIds,
|
|
@@ -190,7 +192,10 @@ class RenderBlockingResources extends Audit {
|
|
|
190
192
|
artifacts.Stacks
|
|
191
193
|
);
|
|
192
194
|
|
|
193
|
-
|
|
195
|
+
const lcpRecord = await LCPImageRecord.request(metricComputationData, context);
|
|
196
|
+
|
|
197
|
+
// In most cases if the LCP is an image, render blocking resources don't affect LCP. For these cases we should reduce its impact.
|
|
198
|
+
return {results, fcpWastedMs, lcpWastedMs: lcpRecord ? 0 : fcpWastedMs};
|
|
194
199
|
}
|
|
195
200
|
|
|
196
201
|
/**
|
|
@@ -276,11 +281,12 @@ class RenderBlockingResources extends Audit {
|
|
|
276
281
|
* @return {Promise<LH.Audit.Product>}
|
|
277
282
|
*/
|
|
278
283
|
static async audit(artifacts, context) {
|
|
279
|
-
const {results,
|
|
284
|
+
const {results, fcpWastedMs, lcpWastedMs} =
|
|
285
|
+
await RenderBlockingResources.computeResults(artifacts, context);
|
|
280
286
|
|
|
281
287
|
let displayValue;
|
|
282
288
|
if (results.length > 0) {
|
|
283
|
-
displayValue = str_(i18n.UIStrings.displayValueMsSavings, {wastedMs});
|
|
289
|
+
displayValue = str_(i18n.UIStrings.displayValueMsSavings, {wastedMs: fcpWastedMs});
|
|
284
290
|
}
|
|
285
291
|
|
|
286
292
|
/** @type {LH.Audit.Details.Opportunity['headings']} */
|
|
@@ -291,15 +297,15 @@ class RenderBlockingResources extends Audit {
|
|
|
291
297
|
];
|
|
292
298
|
|
|
293
299
|
const details = Audit.makeOpportunityDetails(headings, results,
|
|
294
|
-
{overallSavingsMs:
|
|
300
|
+
{overallSavingsMs: fcpWastedMs});
|
|
295
301
|
|
|
296
302
|
return {
|
|
297
303
|
displayValue,
|
|
298
304
|
score: results.length ? 0 : 1,
|
|
299
|
-
numericValue:
|
|
305
|
+
numericValue: fcpWastedMs,
|
|
300
306
|
numericUnit: 'millisecond',
|
|
301
307
|
details,
|
|
302
|
-
metricSavings: {FCP:
|
|
308
|
+
metricSavings: {FCP: fcpWastedMs, LCP: lcpWastedMs},
|
|
303
309
|
};
|
|
304
310
|
}
|
|
305
311
|
}
|
|
@@ -4,6 +4,7 @@ export type LayoutShiftEvent = {
|
|
|
4
4
|
isMainFrame: boolean;
|
|
5
5
|
weightedScore: number;
|
|
6
6
|
impactedNodes?: LH.Artifacts.TraceImpactedNode[];
|
|
7
|
+
event: LH.TraceEvent;
|
|
7
8
|
};
|
|
8
9
|
declare const CumulativeLayoutShiftComputed: typeof CumulativeLayoutShift & {
|
|
9
10
|
request: (dependencies: import("../../index.js").Trace, context: import("../../../types/utility-types.js").default.ImmutableObject<{
|
|
@@ -12,6 +13,11 @@ declare const CumulativeLayoutShiftComputed: typeof CumulativeLayoutShift & {
|
|
|
12
13
|
cumulativeLayoutShift: number;
|
|
13
14
|
cumulativeLayoutShiftMainFrame: number;
|
|
14
15
|
impactByNodeId: Map<number, number>;
|
|
16
|
+
newEngineResult?: {
|
|
17
|
+
cumulativeLayoutShift: number;
|
|
18
|
+
cumulativeLayoutShiftMainFrame: number;
|
|
19
|
+
} | undefined;
|
|
20
|
+
newEngineResultDiffered: boolean;
|
|
15
21
|
}>;
|
|
16
22
|
};
|
|
17
23
|
declare class CumulativeLayoutShift {
|
|
@@ -43,15 +49,28 @@ declare class CumulativeLayoutShift {
|
|
|
43
49
|
* @return {number}
|
|
44
50
|
*/
|
|
45
51
|
static calculate(layoutShiftEvents: Array<LayoutShiftEvent>): number;
|
|
52
|
+
/**
|
|
53
|
+
* @param {LayoutShiftEvent[]} allFrameShiftEvents
|
|
54
|
+
* @param {LayoutShiftEvent[]} mainFrameShiftEvents
|
|
55
|
+
*/
|
|
56
|
+
static computeWithSharedTraceEngine(allFrameShiftEvents: LayoutShiftEvent[], mainFrameShiftEvents: LayoutShiftEvent[]): Promise<{
|
|
57
|
+
cumulativeLayoutShift: any;
|
|
58
|
+
cumulativeLayoutShiftMainFrame: any;
|
|
59
|
+
}>;
|
|
46
60
|
/**
|
|
47
61
|
* @param {LH.Trace} trace
|
|
48
62
|
* @param {LH.Artifacts.ComputedContext} context
|
|
49
|
-
* @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number, impactByNodeId: Map<number, number
|
|
63
|
+
* @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number, impactByNodeId: Map<number, number>, newEngineResult?: {cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number}, newEngineResultDiffered: boolean}>}
|
|
50
64
|
*/
|
|
51
65
|
static compute_(trace: LH.Trace, context: LH.Artifacts.ComputedContext): Promise<{
|
|
52
66
|
cumulativeLayoutShift: number;
|
|
53
67
|
cumulativeLayoutShiftMainFrame: number;
|
|
54
68
|
impactByNodeId: Map<number, number>;
|
|
69
|
+
newEngineResult?: {
|
|
70
|
+
cumulativeLayoutShift: number;
|
|
71
|
+
cumulativeLayoutShiftMainFrame: number;
|
|
72
|
+
} | undefined;
|
|
73
|
+
newEngineResultDiffered: boolean;
|
|
55
74
|
}>;
|
|
56
75
|
}
|
|
57
76
|
import { ProcessedTrace } from '../processed-trace.js';
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
import {makeComputedArtifact} from '../computed-artifact.js';
|
|
8
8
|
import {ProcessedTrace} from '../processed-trace.js';
|
|
9
9
|
import * as RectHelpers from '../../lib/rect-helpers.js';
|
|
10
|
+
import * as TraceEngine from '../../lib/trace-engine.js';
|
|
11
|
+
import {Sentry} from '../../lib/sentry.js';
|
|
10
12
|
|
|
11
|
-
/** @typedef {{ts: number, isMainFrame: boolean, weightedScore: number, impactedNodes?: LH.Artifacts.TraceImpactedNode[]}} LayoutShiftEvent */
|
|
13
|
+
/** @typedef {{ts: number, isMainFrame: boolean, weightedScore: number, impactedNodes?: LH.Artifacts.TraceImpactedNode[], event: LH.TraceEvent}} LayoutShiftEvent */
|
|
12
14
|
|
|
13
15
|
const RECENT_INPUT_WINDOW = 500;
|
|
14
16
|
|
|
@@ -67,6 +69,7 @@ class CumulativeLayoutShift {
|
|
|
67
69
|
isMainFrame: event.args.data.is_main_frame,
|
|
68
70
|
weightedScore: event.args.data.weighted_score_delta,
|
|
69
71
|
impactedNodes: event.args.data.impacted_nodes,
|
|
72
|
+
event,
|
|
70
73
|
});
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -145,10 +148,29 @@ class CumulativeLayoutShift {
|
|
|
145
148
|
return maxScore;
|
|
146
149
|
}
|
|
147
150
|
|
|
151
|
+
/**
|
|
152
|
+
* @param {LayoutShiftEvent[]} allFrameShiftEvents
|
|
153
|
+
* @param {LayoutShiftEvent[]} mainFrameShiftEvents
|
|
154
|
+
*/
|
|
155
|
+
static async computeWithSharedTraceEngine(allFrameShiftEvents, mainFrameShiftEvents) {
|
|
156
|
+
/** @param {LH.TraceEvent[]} events */
|
|
157
|
+
const run = async (events) => {
|
|
158
|
+
const processor = new TraceEngine.TraceProcessor({
|
|
159
|
+
LayoutShifts: TraceEngine.TraceHandlers.LayoutShifts,
|
|
160
|
+
Screenshots: TraceEngine.TraceHandlers.Screenshots,
|
|
161
|
+
});
|
|
162
|
+
await processor.parse(events);
|
|
163
|
+
return processor.data.LayoutShifts.sessionMaxScore;
|
|
164
|
+
};
|
|
165
|
+
const cumulativeLayoutShift = await run(allFrameShiftEvents.map(e => e.event));
|
|
166
|
+
const cumulativeLayoutShiftMainFrame = await run(mainFrameShiftEvents.map(e => e.event));
|
|
167
|
+
return {cumulativeLayoutShift, cumulativeLayoutShiftMainFrame};
|
|
168
|
+
}
|
|
169
|
+
|
|
148
170
|
/**
|
|
149
171
|
* @param {LH.Trace} trace
|
|
150
172
|
* @param {LH.Artifacts.ComputedContext} context
|
|
151
|
-
* @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number, impactByNodeId: Map<number, number
|
|
173
|
+
* @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number, impactByNodeId: Map<number, number>, newEngineResult?: {cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number}, newEngineResultDiffered: boolean}>}
|
|
152
174
|
*/
|
|
153
175
|
static async compute_(trace, context) {
|
|
154
176
|
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
@@ -157,11 +179,59 @@ class CumulativeLayoutShift {
|
|
|
157
179
|
CumulativeLayoutShift.getLayoutShiftEvents(processedTrace);
|
|
158
180
|
const impactByNodeId = CumulativeLayoutShift.getImpactByNodeId(allFrameShiftEvents);
|
|
159
181
|
const mainFrameShiftEvents = allFrameShiftEvents.filter(e => e.isMainFrame);
|
|
182
|
+
const cumulativeLayoutShift = CumulativeLayoutShift.calculate(allFrameShiftEvents);
|
|
183
|
+
const cumulativeLayoutShiftMainFrame = CumulativeLayoutShift.calculate(mainFrameShiftEvents);
|
|
184
|
+
|
|
185
|
+
// Run with the new trace engine, and only throw an error if we are running our unit tests.
|
|
186
|
+
// Otherwise, simply report any differences or errors to Sentry.
|
|
187
|
+
// TODO: TraceEngine always drops `had_recent_input` events, but Lighthouse is more lenient.
|
|
188
|
+
// See comment in `getLayoutShiftEvents`. We need to upstream this.
|
|
189
|
+
let newEngineResult;
|
|
190
|
+
let newEngineResultDiffered = false;
|
|
191
|
+
let tryNewTraceEngine = true;
|
|
192
|
+
if (allFrameShiftEvents.some(e => e.event.args.data?.had_recent_input)) {
|
|
193
|
+
tryNewTraceEngine = false;
|
|
194
|
+
}
|
|
195
|
+
if (tryNewTraceEngine) {
|
|
196
|
+
try {
|
|
197
|
+
newEngineResult =
|
|
198
|
+
await this.computeWithSharedTraceEngine(allFrameShiftEvents, mainFrameShiftEvents);
|
|
199
|
+
newEngineResultDiffered =
|
|
200
|
+
newEngineResult.cumulativeLayoutShift !== cumulativeLayoutShift ||
|
|
201
|
+
newEngineResult.cumulativeLayoutShiftMainFrame !== cumulativeLayoutShiftMainFrame;
|
|
202
|
+
if (newEngineResultDiffered) {
|
|
203
|
+
newEngineResultDiffered = true;
|
|
204
|
+
const expected = JSON.stringify({cumulativeLayoutShift, cumulativeLayoutShiftMainFrame});
|
|
205
|
+
const got = JSON.stringify(newEngineResult);
|
|
206
|
+
throw new Error(`new trace engine differed. expected: ${expected}, got: ${got}`);
|
|
207
|
+
}
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.error(err);
|
|
210
|
+
newEngineResultDiffered = true;
|
|
211
|
+
|
|
212
|
+
const error = new Error('Error when using new trace engine', {cause: err});
|
|
213
|
+
// @ts-expect-error Check for running from tests.
|
|
214
|
+
if (global.expect) {
|
|
215
|
+
throw error;
|
|
216
|
+
} else {
|
|
217
|
+
Sentry.captureException(error, {
|
|
218
|
+
tags: {computed: 'new-trace-engine'},
|
|
219
|
+
level: 'error',
|
|
220
|
+
extra: {
|
|
221
|
+
// Not sure if Sentry handles `cause`, so just in case add the info in a second place.
|
|
222
|
+
errorMsg: err.toString(),
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
160
228
|
|
|
161
229
|
return {
|
|
162
|
-
cumulativeLayoutShift
|
|
163
|
-
cumulativeLayoutShiftMainFrame
|
|
230
|
+
cumulativeLayoutShift,
|
|
231
|
+
cumulativeLayoutShiftMainFrame,
|
|
164
232
|
impactByNodeId,
|
|
233
|
+
newEngineResult,
|
|
234
|
+
newEngineResultDiffered,
|
|
165
235
|
};
|
|
166
236
|
}
|
|
167
237
|
}
|
|
@@ -23,12 +23,6 @@ import {fetchResponseBodyFromCache} from '../../driver/network.js';
|
|
|
23
23
|
import {NetworkRecords} from '../../../computed/network-records.js';
|
|
24
24
|
|
|
25
25
|
const CHROME_EXTENSION_PROTOCOL = 'chrome-extension:';
|
|
26
|
-
const compressionHeaders = [
|
|
27
|
-
'content-encoding',
|
|
28
|
-
'x-original-content-encoding',
|
|
29
|
-
'x-content-encoding-over-network',
|
|
30
|
-
];
|
|
31
|
-
const compressionTypes = ['gzip', 'br', 'deflate'];
|
|
32
26
|
const binaryMimeTypes = ['image', 'audio', 'video'];
|
|
33
27
|
/** @type {LH.Crdp.Network.ResourceType[]} */
|
|
34
28
|
const textResourceTypes = [
|
|
@@ -71,12 +65,7 @@ class ResponseCompression extends BaseGatherer {
|
|
|
71
65
|
return;
|
|
72
66
|
}
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
compressionHeaders.includes(header.name.toLowerCase()) &&
|
|
76
|
-
compressionTypes.includes(header.value)
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
if (!isContentEncoded) {
|
|
68
|
+
if (!NetworkRequest.isContentEncoded(record)) {
|
|
80
69
|
unoptimizedResponses.push({
|
|
81
70
|
requestId: record.requestId,
|
|
82
71
|
url: record.url,
|
|
@@ -56,9 +56,9 @@ class Trace extends BaseGatherer {
|
|
|
56
56
|
'disabled-by-default-devtools.timeline.frame',
|
|
57
57
|
'latencyInfo',
|
|
58
58
|
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
|
|
59
|
+
// Not used by Lighthouse (yet) but included for users that want JS samples when looking at
|
|
60
|
+
// a trace collected by Lighthouse (e.g. "View Trace" workflow in DevTools)
|
|
61
|
+
'disabled-by-default-v8.cpu_profiler',
|
|
62
62
|
];
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -616,8 +616,16 @@ class NetworkRequest {
|
|
|
616
616
|
static isContentEncoded(record) {
|
|
617
617
|
// FYI: older devtools logs (like our test fixtures) seems to be lower case, while modern logs
|
|
618
618
|
// are Cased-Like-This.
|
|
619
|
-
const
|
|
620
|
-
|
|
619
|
+
const patterns = global.isLightrider ? [
|
|
620
|
+
/^x-original-content-encoding$/i,
|
|
621
|
+
] : [
|
|
622
|
+
/^content-encoding$/i,
|
|
623
|
+
/^x-content-encoding-over-network$/i,
|
|
624
|
+
];
|
|
625
|
+
const compressionTypes = ['gzip', 'br', 'deflate'];
|
|
626
|
+
return record.responseHeaders.some(header =>
|
|
627
|
+
patterns.some(p => header.name.match(p)) && compressionTypes.includes(header.value)
|
|
628
|
+
);
|
|
621
629
|
}
|
|
622
630
|
|
|
623
631
|
/**
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
function polyfillDOMRect() {
|
|
5
|
+
// devtools assumes clientside :(
|
|
6
|
+
|
|
7
|
+
// Everything else in here is the DOMRect polyfill
|
|
8
|
+
// https://raw.githubusercontent.com/JakeChampion/polyfill-library/master/polyfills/DOMRect/polyfill.js
|
|
9
|
+
|
|
10
|
+
(function (global) {
|
|
11
|
+
function number(v) {
|
|
12
|
+
return v === undefined ? 0 : Number(v);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function different(u, v) {
|
|
16
|
+
return u !== v && !(isNaN(u) && isNaN(v));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DOMRect(xArg, yArg, wArg, hArg) {
|
|
20
|
+
let x, y, width, height, left, right, top, bottom;
|
|
21
|
+
|
|
22
|
+
x = number(xArg);
|
|
23
|
+
y = number(yArg);
|
|
24
|
+
width = number(wArg);
|
|
25
|
+
height = number(hArg);
|
|
26
|
+
|
|
27
|
+
Object.defineProperties(this, {
|
|
28
|
+
x: {
|
|
29
|
+
get: function () { return x; },
|
|
30
|
+
set: function (newX) {
|
|
31
|
+
if (different(x, newX)) {
|
|
32
|
+
x = newX;
|
|
33
|
+
left = right = undefined;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
enumerable: true
|
|
37
|
+
},
|
|
38
|
+
y: {
|
|
39
|
+
get: function () { return y; },
|
|
40
|
+
set: function (newY) {
|
|
41
|
+
if (different(y, newY)) {
|
|
42
|
+
y = newY;
|
|
43
|
+
top = bottom = undefined;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
enumerable: true
|
|
47
|
+
},
|
|
48
|
+
width: {
|
|
49
|
+
get: function () { return width; },
|
|
50
|
+
set: function (newWidth) {
|
|
51
|
+
if (different(width, newWidth)) {
|
|
52
|
+
width = newWidth;
|
|
53
|
+
left = right = undefined;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
enumerable: true
|
|
57
|
+
},
|
|
58
|
+
height: {
|
|
59
|
+
get: function () { return height; },
|
|
60
|
+
set: function (newHeight) {
|
|
61
|
+
if (different(height, newHeight)) {
|
|
62
|
+
height = newHeight;
|
|
63
|
+
top = bottom = undefined;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
enumerable: true
|
|
67
|
+
},
|
|
68
|
+
left: {
|
|
69
|
+
get: function () {
|
|
70
|
+
if (left === undefined) {
|
|
71
|
+
left = x + Math.min(0, width);
|
|
72
|
+
}
|
|
73
|
+
return left;
|
|
74
|
+
},
|
|
75
|
+
enumerable: true
|
|
76
|
+
},
|
|
77
|
+
right: {
|
|
78
|
+
get: function () {
|
|
79
|
+
if (right === undefined) {
|
|
80
|
+
right = x + Math.max(0, width);
|
|
81
|
+
}
|
|
82
|
+
return right;
|
|
83
|
+
},
|
|
84
|
+
enumerable: true
|
|
85
|
+
},
|
|
86
|
+
top: {
|
|
87
|
+
get: function () {
|
|
88
|
+
if (top === undefined) {
|
|
89
|
+
top = y + Math.min(0, height);
|
|
90
|
+
}
|
|
91
|
+
return top;
|
|
92
|
+
},
|
|
93
|
+
enumerable: true
|
|
94
|
+
},
|
|
95
|
+
bottom: {
|
|
96
|
+
get: function () {
|
|
97
|
+
if (bottom === undefined) {
|
|
98
|
+
bottom = y + Math.max(0, height);
|
|
99
|
+
}
|
|
100
|
+
return bottom;
|
|
101
|
+
},
|
|
102
|
+
enumerable: true
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
globalThis.DOMRect = DOMRect;
|
|
108
|
+
})(globalThis);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {polyfillDOMRect};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @ts-expect-error missing types
|
|
2
|
+
import * as TraceEngine from '@paulirish/trace_engine';
|
|
3
|
+
|
|
4
|
+
import {polyfillDOMRect} from './polyfill-dom-rect.js';
|
|
5
|
+
|
|
6
|
+
polyfillDOMRect();
|
|
7
|
+
|
|
8
|
+
const TraceProcessor = TraceEngine.Processor.TraceProcessor;
|
|
9
|
+
const TraceHandlers = TraceEngine.Handlers.ModelHandlers;
|
|
10
|
+
const RootCauses = TraceEngine.RootCauses.RootCauses.RootCauses;
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
TraceProcessor,
|
|
14
|
+
TraceHandlers,
|
|
15
|
+
RootCauses,
|
|
16
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lighthouse",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "11.4.0-dev.
|
|
4
|
+
"version": "11.4.0-dev.20231220",
|
|
5
5
|
"description": "Automated auditing, performance metrics, and best practices for the web.",
|
|
6
6
|
"main": "./core/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -180,6 +180,7 @@
|
|
|
180
180
|
"webtreemap-cdt": "^3.2.1"
|
|
181
181
|
},
|
|
182
182
|
"dependencies": {
|
|
183
|
+
"@paulirish/trace_engine": "^0.0.7",
|
|
183
184
|
"@sentry/node": "^6.17.4",
|
|
184
185
|
"axe-core": "^4.8.1",
|
|
185
186
|
"chrome-launcher": "^1.1.0",
|