lighthouse 11.6.0 → 11.7.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/cli/test/smokehouse/core-tests.js +2 -2
- package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +2 -2
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +7 -7
- package/core/audits/byte-efficiency/render-blocking-resources.d.ts +4 -3
- package/core/audits/byte-efficiency/render-blocking-resources.js +6 -6
- package/core/audits/dobetterweb/uses-http2.d.ts +3 -3
- package/core/audits/dobetterweb/uses-http2.js +4 -4
- package/core/audits/installable-manifest.d.ts +2 -0
- package/core/audits/installable-manifest.js +2 -0
- package/core/audits/metrics/interaction-to-next-paint.js +1 -3
- package/core/audits/prioritize-lcp-image.d.ts +1 -1
- package/core/audits/work-during-interaction.js +0 -8
- package/core/computed/document-urls.js +1 -1
- package/core/computed/load-simulator.d.ts +2 -2
- package/core/computed/load-simulator.js +3 -2
- package/core/computed/main-resource.js +1 -1
- package/core/computed/metrics/lantern-first-contentful-paint.d.ts +18 -6
- package/core/computed/metrics/lantern-first-contentful-paint.js +4 -4
- package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +14 -2
- package/core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
- package/core/computed/metrics/lantern-interactive.d.ts +8 -6
- package/core/computed/metrics/lantern-interactive.js +3 -3
- package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +14 -2
- package/core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
- package/core/computed/metrics/lantern-max-potential-fid.d.ts +8 -2
- package/core/computed/metrics/lantern-max-potential-fid.js +3 -3
- package/core/computed/metrics/lantern-metric.d.ts +4 -63
- package/core/computed/metrics/lantern-metric.js +6 -124
- package/core/computed/metrics/lantern-speed-index.d.ts +8 -2
- package/core/computed/metrics/lantern-speed-index.js +3 -3
- package/core/computed/metrics/lantern-total-blocking-time.d.ts +8 -2
- package/core/computed/metrics/lantern-total-blocking-time.js +3 -3
- package/core/computed/metrics/responsiveness.d.ts +5 -13
- package/core/computed/metrics/responsiveness.js +10 -14
- package/core/computed/network-analysis.js +1 -1
- package/core/computed/page-dependency-graph.d.ts +4 -57
- package/core/computed/page-dependency-graph.js +4 -451
- package/core/config/config-helpers.js +1 -1
- package/core/gather/driver/execution-context.d.ts +2 -1
- package/core/gather/driver/execution-context.js +9 -9
- package/core/gather/driver/wait-for-condition.js +4 -2
- package/core/gather/gatherers/accessibility.js +2 -1
- package/core/gather/gatherers/css-usage.d.ts +1 -9
- package/core/gather/gatherers/css-usage.js +23 -25
- package/core/gather/gatherers/devtools-log.d.ts +4 -0
- package/core/gather/gatherers/devtools-log.js +7 -0
- package/core/gather/gatherers/full-page-screenshot.d.ts +4 -0
- package/core/gather/gatherers/full-page-screenshot.js +31 -35
- package/core/gather/gatherers/root-causes.js +1 -3
- package/core/gather/gatherers/trace-elements.js +1 -1
- package/core/gather/gatherers/trace.d.ts +1 -0
- package/core/gather/gatherers/trace.js +4 -0
- package/core/gather/navigation-runner.js +49 -62
- package/core/gather/session.js +5 -0
- package/core/gather/snapshot-runner.js +25 -25
- package/core/gather/timespan-runner.js +24 -25
- package/core/lib/asset-saver.js +1 -1
- package/core/lib/emulation.js +0 -3
- package/core/lib/{dependency-graph → lantern}/base-node.d.ts +12 -8
- package/core/lib/{dependency-graph → lantern}/base-node.js +8 -3
- package/core/lib/{dependency-graph → lantern}/cpu-node.d.ts +5 -1
- package/core/lib/{dependency-graph → lantern}/cpu-node.js +4 -0
- package/core/lib/lantern/lantern.d.ts +8 -0
- package/core/lib/lantern/lantern.js +31 -0
- package/core/lib/lantern/metric.d.ts +71 -0
- package/core/lib/lantern/metric.js +143 -0
- package/core/lib/{dependency-graph → lantern}/network-node.d.ts +17 -10
- package/core/lib/lantern/network-node.js +114 -0
- package/core/lib/lantern/page-dependency-graph.d.ts +58 -0
- package/core/lib/lantern/page-dependency-graph.js +463 -0
- package/core/lib/{dependency-graph → lantern}/simulator/connection-pool.d.ts +14 -14
- package/core/lib/{dependency-graph → lantern}/simulator/connection-pool.js +7 -7
- package/core/lib/{dependency-graph → lantern}/simulator/dns-cache.d.ts +5 -5
- package/core/lib/{dependency-graph → lantern}/simulator/dns-cache.js +3 -3
- package/core/lib/{dependency-graph → lantern}/simulator/network-analyzer.d.ts +36 -32
- package/core/lib/{dependency-graph → lantern}/simulator/network-analyzer.js +21 -17
- package/core/lib/{dependency-graph → lantern}/simulator/simulator.d.ts +18 -15
- package/core/lib/{dependency-graph → lantern}/simulator/simulator.js +18 -15
- package/core/lib/lantern/types/lantern.d.ts +129 -0
- package/core/lib/lantern/types/lantern.js +7 -0
- package/core/lib/lantern-trace-saver.d.ts +4 -4
- package/core/lib/lantern-trace-saver.js +6 -4
- package/core/lib/navigation-error.js +1 -1
- package/core/lib/network-recorder.js +2 -2
- package/core/lib/network-request.d.ts +6 -0
- package/core/lib/network-request.js +12 -0
- package/package.json +4 -5
- package/shared/localization/locales/ar-XB.json +1 -1
- package/shared/localization/locales/ar.json +1 -1
- package/shared/localization/locales/bg.json +1 -1
- package/shared/localization/locales/ca.json +1 -1
- package/shared/localization/locales/cs.json +1 -1
- package/shared/localization/locales/da.json +2 -2
- package/shared/localization/locales/de.json +1 -1
- package/shared/localization/locales/el.json +1 -1
- package/shared/localization/locales/en-GB.json +1 -1
- package/shared/localization/locales/en-US.json +3 -0
- package/shared/localization/locales/en-XA.json +1 -1
- package/shared/localization/locales/en-XL.json +3 -0
- package/shared/localization/locales/es-419.json +1 -1
- package/shared/localization/locales/es.json +1 -1
- package/shared/localization/locales/fi.json +1 -1
- package/shared/localization/locales/fil.json +1 -1
- package/shared/localization/locales/he.json +1 -1
- package/shared/localization/locales/hi.json +1 -1
- package/shared/localization/locales/hr.json +1 -1
- package/shared/localization/locales/hu.json +1 -1
- package/shared/localization/locales/id.json +1 -1
- package/shared/localization/locales/it.json +1 -1
- package/shared/localization/locales/ko.json +1 -1
- package/shared/localization/locales/lt.json +1 -1
- package/shared/localization/locales/nl.json +1 -1
- package/shared/localization/locales/no.json +1 -1
- package/shared/localization/locales/pl.json +1 -1
- package/shared/localization/locales/pt-PT.json +1 -1
- package/shared/localization/locales/pt.json +1 -1
- package/shared/localization/locales/ro.json +1 -1
- package/shared/localization/locales/sk.json +1 -1
- package/shared/localization/locales/sl.json +1 -1
- package/shared/localization/locales/sr-Latn.json +1 -1
- package/shared/localization/locales/sr.json +1 -1
- package/shared/localization/locales/sv.json +1 -1
- package/shared/localization/locales/ta.json +1 -1
- package/shared/localization/locales/te.json +1 -1
- package/shared/localization/locales/th.json +4 -4
- package/shared/localization/locales/tr.json +1 -1
- package/shared/localization/locales/uk.json +1 -1
- package/shared/localization/locales/vi.json +1 -1
- package/shared/localization/locales/zh-HK.json +1 -1
- package/shared/localization/locales/zh-TW.json +1 -1
- package/shared/localization/locales/zh.json +1 -1
- package/third-party/chromium-synchronization/installability-errors-test.js +1 -1
- package/tsconfig.json +7 -5
- package/types/artifacts.d.ts +1 -1
- package/types/gatherer.d.ts +8 -35
- package/types/lhr/lhr.d.ts +1 -1
- package/core/lib/dependency-graph/network-node.js +0 -99
- /package/core/lib/{dependency-graph → lantern}/simulator/simulator-timing-map.d.ts +0 -0
- /package/core/lib/{dependency-graph → lantern}/simulator/simulator-timing-map.js +0 -0
- /package/core/lib/{dependency-graph → lantern}/simulator/tcp-connection.d.ts +0 -0
- /package/core/lib/{dependency-graph → lantern}/simulator/tcp-connection.js +0 -0
|
@@ -12,6 +12,10 @@ declare class DevtoolsLog extends BaseGatherer {
|
|
|
12
12
|
* @param {LH.Gatherer.Context} passContext
|
|
13
13
|
*/
|
|
14
14
|
stopSensitiveInstrumentation({ driver }: LH.Gatherer.Context): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* @return {LH.Artifacts['DevtoolsLog']}
|
|
17
|
+
*/
|
|
18
|
+
getDebugData(): LH.Artifacts['DevtoolsLog'];
|
|
15
19
|
/**
|
|
16
20
|
* @return {Promise<LH.Artifacts['DevtoolsLog']>}
|
|
17
21
|
*/
|
|
@@ -49,6 +49,13 @@ class DevtoolsLog extends BaseGatherer {
|
|
|
49
49
|
driver.targetManager.off('protocolevent', this._onProtocolMessage);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @return {LH.Artifacts['DevtoolsLog']}
|
|
54
|
+
*/
|
|
55
|
+
getDebugData() {
|
|
56
|
+
return this._messageLog.messages;
|
|
57
|
+
}
|
|
58
|
+
|
|
52
59
|
/**
|
|
53
60
|
* @return {Promise<LH.Artifacts['DevtoolsLog']>}
|
|
54
61
|
*/
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export default FullPageScreenshot;
|
|
2
2
|
declare class FullPageScreenshot extends BaseGatherer {
|
|
3
|
+
/**
|
|
4
|
+
* @param {LH.Gatherer.Context} context
|
|
5
|
+
*/
|
|
6
|
+
waitForNetworkIdle(context: LH.Gatherer.Context): import("../driver/wait-for-condition.js").CancellableWait<void>;
|
|
3
7
|
/**
|
|
4
8
|
* @param {LH.Gatherer.Context} context
|
|
5
9
|
* @param {{height: number, width: number, mobile: boolean}} deviceMetrics
|
|
@@ -13,7 +13,10 @@ import {waitForNetworkIdle} from '../driver/wait-for-condition.js';
|
|
|
13
13
|
// JPEG quality setting
|
|
14
14
|
// Exploration and examples of reports using different quality settings: https://docs.google.com/document/d/1ZSffucIca9XDW2eEwfoevrk-OTl7WQFeMf0CgeJAA8M/edit#
|
|
15
15
|
// Note: this analysis was done for JPEG, but now we use WEBP.
|
|
16
|
-
const FULL_PAGE_SCREENSHOT_QUALITY = 30;
|
|
16
|
+
const FULL_PAGE_SCREENSHOT_QUALITY = process.env.LH_FPS_TEST ? 100 : 30;
|
|
17
|
+
// webp currently cant do lossless encoding, so to help tests switch to png
|
|
18
|
+
// Remove when this is resolved: https://bugs.chromium.org/p/chromium/issues/detail?id=1469183
|
|
19
|
+
const FULL_PAGE_SCREENSHOT_FORMAT = process.env.LH_FPS_TEST ? 'png' : 'webp';
|
|
17
20
|
|
|
18
21
|
// https://developers.google.com/speed/webp/faq#what_is_the_maximum_size_a_webp_image_can_be
|
|
19
22
|
const MAX_WEBP_SIZE = 16383;
|
|
@@ -44,17 +47,6 @@ function getObservedDeviceMetrics() {
|
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
/**
|
|
48
|
-
* The screenshot dimensions are sized to `window.outerHeight` / `window.outerWidth`,
|
|
49
|
-
* however the bounding boxes of the elements are relative to `window.innerHeight` / `window.innerWidth`.
|
|
50
|
-
*/
|
|
51
|
-
function getScreenshotAreaSize() {
|
|
52
|
-
return {
|
|
53
|
-
width: window.innerWidth,
|
|
54
|
-
height: window.innerHeight,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
50
|
function waitForDoubleRaf() {
|
|
59
51
|
return new Promise((resolve) => {
|
|
60
52
|
requestAnimationFrame(() => requestAnimationFrame(resolve));
|
|
@@ -69,6 +61,21 @@ class FullPageScreenshot extends BaseGatherer {
|
|
|
69
61
|
supportedModes: ['snapshot', 'timespan', 'navigation'],
|
|
70
62
|
};
|
|
71
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @param {LH.Gatherer.Context} context
|
|
66
|
+
*/
|
|
67
|
+
waitForNetworkIdle(context) {
|
|
68
|
+
const session = context.driver.defaultSession;
|
|
69
|
+
const networkMonitor = context.driver.networkMonitor;
|
|
70
|
+
return waitForNetworkIdle(session, networkMonitor, {
|
|
71
|
+
pretendDCLAlreadyFired: true,
|
|
72
|
+
networkQuietThresholdMs: 1000,
|
|
73
|
+
busyEvent: 'network-critical-busy',
|
|
74
|
+
idleEvent: 'network-critical-idle',
|
|
75
|
+
isIdle: recorder => recorder.isCriticalIdle(),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
72
79
|
/**
|
|
73
80
|
* @param {LH.Gatherer.Context} context
|
|
74
81
|
* @param {{height: number, width: number, mobile: boolean}} deviceMetrics
|
|
@@ -86,15 +93,7 @@ class FullPageScreenshot extends BaseGatherer {
|
|
|
86
93
|
);
|
|
87
94
|
const height = Math.min(fullHeight, MAX_WEBP_SIZE);
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
const networkMonitor = context.driver.networkMonitor;
|
|
91
|
-
const waitForNetworkIdleResult = waitForNetworkIdle(session, networkMonitor, {
|
|
92
|
-
pretendDCLAlreadyFired: true,
|
|
93
|
-
networkQuietThresholdMs: 1000,
|
|
94
|
-
busyEvent: 'network-critical-busy',
|
|
95
|
-
idleEvent: 'network-critical-idle',
|
|
96
|
-
isIdle: recorder => recorder.isCriticalIdle(),
|
|
97
|
-
});
|
|
96
|
+
const waitForNetworkIdleResult = this.waitForNetworkIdle(context);
|
|
98
97
|
|
|
99
98
|
await session.sendCommand('Emulation.setDeviceMetricsOverride', {
|
|
100
99
|
mobile: deviceMetrics.mobile,
|
|
@@ -120,22 +119,19 @@ class FullPageScreenshot extends BaseGatherer {
|
|
|
120
119
|
* @return {Promise<LH.Result.FullPageScreenshot['screenshot']>}
|
|
121
120
|
*/
|
|
122
121
|
async _takeScreenshot(context) {
|
|
123
|
-
const result = await
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
args: [],
|
|
132
|
-
useIsolation: true,
|
|
133
|
-
});
|
|
122
|
+
const [metrics, result] = await Promise.all([
|
|
123
|
+
context.driver.defaultSession.sendCommand('Page.getLayoutMetrics'),
|
|
124
|
+
context.driver.defaultSession.sendCommand('Page.captureScreenshot', {
|
|
125
|
+
format: FULL_PAGE_SCREENSHOT_FORMAT,
|
|
126
|
+
quality: FULL_PAGE_SCREENSHOT_QUALITY,
|
|
127
|
+
}),
|
|
128
|
+
]);
|
|
129
|
+
const data = `data:image/${FULL_PAGE_SCREENSHOT_FORMAT};base64,` + result.data;
|
|
134
130
|
|
|
135
131
|
return {
|
|
136
132
|
data,
|
|
137
|
-
width:
|
|
138
|
-
height:
|
|
133
|
+
width: metrics.cssVisualViewport.clientWidth,
|
|
134
|
+
height: metrics.cssVisualViewport.clientHeight,
|
|
139
135
|
};
|
|
140
136
|
}
|
|
141
137
|
|
|
@@ -159,7 +155,7 @@ class FullPageScreenshot extends BaseGatherer {
|
|
|
159
155
|
for (const [node, id] of lhIdToElements.entries()) {
|
|
160
156
|
// @ts-expect-error - getBoundingClientRect put into scope via stringification
|
|
161
157
|
const rect = getBoundingClientRect(node);
|
|
162
|
-
nodes[id] = rect;
|
|
158
|
+
nodes[id] = {id: node.id, ...rect};
|
|
163
159
|
}
|
|
164
160
|
|
|
165
161
|
return nodes;
|
|
@@ -124,9 +124,7 @@ class RootCauses extends BaseGatherer {
|
|
|
124
124
|
rootCauses.layoutShifts[layoutShiftEvents.indexOf(event)] = r;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
// ...but we don't give gatherers their own session so this stomps on others.
|
|
129
|
-
// await driver.defaultSession.sendCommand('DOM.disable');
|
|
127
|
+
await driver.defaultSession.sendCommand('DOM.disable');
|
|
130
128
|
await driver.defaultSession.sendCommand('CSS.disable');
|
|
131
129
|
|
|
132
130
|
return rootCauses;
|
|
@@ -155,7 +155,7 @@ class TraceElements extends BaseGatherer {
|
|
|
155
155
|
const {settings} = context;
|
|
156
156
|
try {
|
|
157
157
|
const responsivenessEvent = await Responsiveness.request({trace, settings}, context);
|
|
158
|
-
if (!responsivenessEvent
|
|
158
|
+
if (!responsivenessEvent) return;
|
|
159
159
|
return {nodeId: responsivenessEvent.args.data.nodeId};
|
|
160
160
|
} catch {
|
|
161
161
|
// Don't let responsiveness errors sink the rest of the gatherer.
|
|
@@ -17,6 +17,7 @@ declare class Trace extends BaseGatherer {
|
|
|
17
17
|
* @param {LH.Gatherer.Context} passContext
|
|
18
18
|
*/
|
|
19
19
|
stopSensitiveInstrumentation({ driver }: LH.Gatherer.Context): Promise<void>;
|
|
20
|
+
getDebugData(): import("../../index.js").Trace;
|
|
20
21
|
getArtifact(): import("../../index.js").Trace;
|
|
21
22
|
}
|
|
22
23
|
import BaseGatherer from '../base-gatherer.js';
|
|
@@ -110,31 +110,19 @@ async function _navigate(navigationContext) {
|
|
|
110
110
|
* @return {Promise<{devtoolsLog?: LH.DevtoolsLog, records?: Array<LH.Artifacts.NetworkRequest>, trace?: LH.Trace}>}
|
|
111
111
|
*/
|
|
112
112
|
async function _collectDebugData(navigationContext, phaseState) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
*/
|
|
125
|
-
defn => Boolean(defn)
|
|
126
|
-
);
|
|
127
|
-
if (!artifactDefinitions.length) return {};
|
|
128
|
-
|
|
129
|
-
await collectPhaseArtifacts({...phaseState, phase: 'getArtifact', artifactDefinitions});
|
|
130
|
-
const getArtifactState = phaseState.artifactState.getArtifact;
|
|
131
|
-
|
|
132
|
-
const devtoolsLogArtifactId = devtoolsLogArtifactDefn?.id;
|
|
133
|
-
const devtoolsLog = devtoolsLogArtifactId && (await getArtifactState[devtoolsLogArtifactId]);
|
|
134
|
-
const records = devtoolsLog && (await NetworkRecords.request(devtoolsLog, navigationContext));
|
|
113
|
+
let devtoolsLog;
|
|
114
|
+
let trace;
|
|
115
|
+
|
|
116
|
+
for (const definition of phaseState.artifactDefinitions) {
|
|
117
|
+
const {instance} = definition.gatherer;
|
|
118
|
+
if (instance instanceof DevtoolsLog) {
|
|
119
|
+
devtoolsLog = instance.getDebugData();
|
|
120
|
+
} else if (instance instanceof Trace) {
|
|
121
|
+
trace = instance.getDebugData();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
135
124
|
|
|
136
|
-
const
|
|
137
|
-
const trace = traceArtifactId && (await getArtifactState[traceArtifactId]);
|
|
125
|
+
const records = devtoolsLog && (await NetworkRecords.request(devtoolsLog, navigationContext));
|
|
138
126
|
|
|
139
127
|
return {devtoolsLog, records, trace};
|
|
140
128
|
}
|
|
@@ -277,44 +265,43 @@ async function navigationGather(page, requestor, options = {}) {
|
|
|
277
265
|
const isCallback = typeof requestor === 'function';
|
|
278
266
|
|
|
279
267
|
const runnerOptions = {resolvedConfig, computedCache};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
);
|
|
268
|
+
|
|
269
|
+
const gatherFn = async () => {
|
|
270
|
+
const normalizedRequestor = isCallback ? requestor : UrlUtils.normalizeUrl(requestor);
|
|
271
|
+
|
|
272
|
+
/** @type {LH.Puppeteer.Browser|undefined} */
|
|
273
|
+
let lhBrowser = undefined;
|
|
274
|
+
/** @type {LH.Puppeteer.Page|undefined} */
|
|
275
|
+
let lhPage = undefined;
|
|
276
|
+
|
|
277
|
+
// For navigation mode, we shouldn't connect to a browser in audit mode,
|
|
278
|
+
// therefore we connect to the browser in the gatherFn callback.
|
|
279
|
+
if (!page) {
|
|
280
|
+
const {hostname = DEFAULT_HOSTNAME, port = DEFAULT_PORT} = flags;
|
|
281
|
+
lhBrowser = await puppeteer.connect({browserURL: `http://${hostname}:${port}`, defaultViewport: null});
|
|
282
|
+
lhPage = await lhBrowser.newPage();
|
|
283
|
+
page = lhPage;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const driver = new Driver(page);
|
|
287
|
+
const context = {
|
|
288
|
+
driver,
|
|
289
|
+
lhBrowser,
|
|
290
|
+
lhPage,
|
|
291
|
+
page,
|
|
292
|
+
resolvedConfig,
|
|
293
|
+
requestor: normalizedRequestor,
|
|
294
|
+
computedCache,
|
|
295
|
+
};
|
|
296
|
+
const {baseArtifacts} = await _setup(context);
|
|
297
|
+
|
|
298
|
+
const artifacts = await _navigation({...context, baseArtifacts});
|
|
299
|
+
|
|
300
|
+
await _cleanup(context);
|
|
301
|
+
|
|
302
|
+
return finalizeArtifacts(baseArtifacts, artifacts);
|
|
303
|
+
};
|
|
304
|
+
const artifacts = await Runner.gather(gatherFn, runnerOptions);
|
|
318
305
|
return {artifacts, runnerOptions};
|
|
319
306
|
}
|
|
320
307
|
|
package/core/gather/session.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import EventEmitter from 'events';
|
|
8
8
|
|
|
9
|
+
import log from 'lighthouse-logger';
|
|
10
|
+
|
|
9
11
|
import {LighthouseError} from '../lib/lh-error.js';
|
|
10
12
|
|
|
11
13
|
// Controls how long to wait for a response after sending a DevTools protocol command.
|
|
@@ -107,6 +109,9 @@ class ProtocolSession extends CrdpEventEmitter {
|
|
|
107
109
|
const resultPromise = this._cdpSession.send(method, ...params, {
|
|
108
110
|
// Add 50ms to the Puppeteer timeout to ensure the Lighthouse timeout finishes first.
|
|
109
111
|
timeout: timeoutMs + PPTR_BUFFER,
|
|
112
|
+
}).catch((error) => {
|
|
113
|
+
log.formatProtocol('method <= browser ERR', {method}, 'error');
|
|
114
|
+
throw LighthouseError.fromProtocolMessage(method, error);
|
|
110
115
|
});
|
|
111
116
|
const resultWithTimeoutPromise = Promise.race([resultPromise, timeoutPromise]);
|
|
112
117
|
|
|
@@ -30,35 +30,35 @@ async function snapshotGather(page, options = {}) {
|
|
|
30
30
|
const url = await driver.url();
|
|
31
31
|
|
|
32
32
|
const runnerOptions = {resolvedConfig, computedCache};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
|
|
34
|
+
const gatherFn = async () => {
|
|
35
|
+
const baseArtifacts =
|
|
36
36
|
await getBaseArtifacts(resolvedConfig, driver, {gatherMode: 'snapshot'});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
baseArtifacts.URL = {
|
|
38
|
+
finalDisplayedUrl: url,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const artifactDefinitions = resolvedConfig.artifacts || [];
|
|
42
|
+
const artifactState = getEmptyArtifactState();
|
|
43
|
+
await collectPhaseArtifacts({
|
|
44
|
+
phase: 'getArtifact',
|
|
45
|
+
gatherMode: 'snapshot',
|
|
46
|
+
driver,
|
|
47
|
+
page,
|
|
48
|
+
baseArtifacts,
|
|
49
|
+
artifactDefinitions,
|
|
50
|
+
artifactState,
|
|
51
|
+
computedCache,
|
|
52
|
+
settings: resolvedConfig.settings,
|
|
53
|
+
});
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
const artifactState = getEmptyArtifactState();
|
|
43
|
-
await collectPhaseArtifacts({
|
|
44
|
-
phase: 'getArtifact',
|
|
45
|
-
gatherMode: 'snapshot',
|
|
46
|
-
driver,
|
|
47
|
-
page,
|
|
48
|
-
baseArtifacts,
|
|
49
|
-
artifactDefinitions,
|
|
50
|
-
artifactState,
|
|
51
|
-
computedCache,
|
|
52
|
-
settings: resolvedConfig.settings,
|
|
53
|
-
});
|
|
55
|
+
await driver.disconnect();
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
const artifacts = await awaitArtifacts(artifactState);
|
|
58
|
+
return finalizeArtifacts(baseArtifacts, artifacts);
|
|
59
|
+
};
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
return finalizeArtifacts(baseArtifacts, artifacts);
|
|
59
|
-
},
|
|
60
|
-
runnerOptions
|
|
61
|
-
);
|
|
61
|
+
const artifacts = await Runner.gather(gatherFn, runnerOptions);
|
|
62
62
|
return {artifacts, runnerOptions};
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -72,31 +72,30 @@ async function startTimespanGather(page, options = {}) {
|
|
|
72
72
|
const finalDisplayedUrl = await driver.url();
|
|
73
73
|
|
|
74
74
|
const runnerOptions = {resolvedConfig, computedCache};
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
);
|
|
75
|
+
const gatherFn = async () => {
|
|
76
|
+
baseArtifacts.URL = {finalDisplayedUrl};
|
|
77
|
+
|
|
78
|
+
await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseOptions});
|
|
79
|
+
await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseOptions});
|
|
80
|
+
|
|
81
|
+
// bf-cache-failures can emit `Page.frameNavigated` at the end of the run.
|
|
82
|
+
// This can cause us to issue protocol commands after the target closes.
|
|
83
|
+
// We should disable our `Page.frameNavigated` handlers before that.
|
|
84
|
+
await disableAsyncStacks();
|
|
85
|
+
|
|
86
|
+
driver.defaultSession.off('Page.frameNavigated', onFrameNavigated);
|
|
87
|
+
if (pageNavigationDetected) {
|
|
88
|
+
baseArtifacts.LighthouseRunWarnings.push(str_(UIStrings.warningNavigationDetected));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await collectPhaseArtifacts({phase: 'getArtifact', ...phaseOptions});
|
|
92
|
+
await driver.disconnect();
|
|
93
|
+
|
|
94
|
+
const artifacts = await awaitArtifacts(artifactState);
|
|
95
|
+
return finalizeArtifacts(baseArtifacts, artifacts);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const artifacts = await Runner.gather(gatherFn, runnerOptions);
|
|
100
99
|
return {artifacts, runnerOptions};
|
|
101
100
|
},
|
|
102
101
|
};
|
package/core/lib/asset-saver.js
CHANGED
|
@@ -11,7 +11,7 @@ import url from 'url';
|
|
|
11
11
|
|
|
12
12
|
import log from 'lighthouse-logger';
|
|
13
13
|
|
|
14
|
-
import {Simulator} from './
|
|
14
|
+
import {Simulator} from './lantern/simulator/simulator.js';
|
|
15
15
|
import lanternTraceSaver from './lantern-trace-saver.js';
|
|
16
16
|
import {MetricTraceEvents} from './traces/metric-trace-events.js';
|
|
17
17
|
import {NetworkAnalysis} from '../computed/network-analysis.js';
|
package/core/lib/emulation.js
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {lighthouseVersion} from '../../shared/root.js';
|
|
8
|
-
|
|
9
7
|
const NO_THROTTLING_METRICS = {
|
|
10
8
|
latency: 0,
|
|
11
9
|
downloadThroughput: 0,
|
|
@@ -29,7 +27,6 @@ function parseUseragentIntoMetadata(userAgent, formFactor) {
|
|
|
29
27
|
const brands = [
|
|
30
28
|
{brand: 'Chromium', version},
|
|
31
29
|
{brand: 'Google Chrome', version},
|
|
32
|
-
{brand: 'Lighthouse', version: lighthouseVersion},
|
|
33
30
|
];
|
|
34
31
|
|
|
35
32
|
const motoGPowerDetails = {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A union of all types derived from BaseNode, allowing type check discrimination
|
|
3
3
|
* based on `node.type`. If a new node type is created, it should be added here.
|
|
4
4
|
*/
|
|
5
|
-
export type Node = import('./cpu-node.js').CPUNode | import('./network-node.js').NetworkNode
|
|
5
|
+
export type Node<T = any> = import('./cpu-node.js').CPUNode<T> | import('./network-node.js').NetworkNode<T>;
|
|
6
6
|
/**
|
|
7
7
|
* @license
|
|
8
8
|
* Copyright 2017 Google LLC
|
|
@@ -11,7 +11,8 @@ export type Node = import('./cpu-node.js').CPUNode | import('./network-node.js')
|
|
|
11
11
|
/**
|
|
12
12
|
* A union of all types derived from BaseNode, allowing type check discrimination
|
|
13
13
|
* based on `node.type`. If a new node type is created, it should be added here.
|
|
14
|
-
* @
|
|
14
|
+
* @template [T=any]
|
|
15
|
+
* @typedef {import('./cpu-node.js').CPUNode<T> | import('./network-node.js').NetworkNode<T>} Node
|
|
15
16
|
*/
|
|
16
17
|
/**
|
|
17
18
|
* @fileoverview This class encapsulates logic for handling resources and tasks used to model the
|
|
@@ -25,7 +26,10 @@ export type Node = import('./cpu-node.js').CPUNode | import('./network-node.js')
|
|
|
25
26
|
* This allows particular optimizations in this class so that we do no need to check for cycles as
|
|
26
27
|
* these methods are called and we can always start traversal at the root node.
|
|
27
28
|
*/
|
|
28
|
-
|
|
29
|
+
/**
|
|
30
|
+
* @template [T=any]
|
|
31
|
+
*/
|
|
32
|
+
export class BaseNode<T = any> {
|
|
29
33
|
/**
|
|
30
34
|
* Returns whether the given node has a cycle in its dependent graph by performing a DFS.
|
|
31
35
|
* @param {Node} node
|
|
@@ -134,17 +138,17 @@ export class BaseNode {
|
|
|
134
138
|
*
|
|
135
139
|
* The `getNextNodes` function takes a visited node and returns which nodes to
|
|
136
140
|
* visit next. It defaults to returning the node's dependents.
|
|
137
|
-
* @param {(node: Node
|
|
138
|
-
* @param {function(Node): Node[]} [getNextNodes]
|
|
141
|
+
* @param {(node: Node<T>, traversalPath: Node<T>[]) => void} callback
|
|
142
|
+
* @param {function(Node<T>): Node<T>[]} [getNextNodes]
|
|
139
143
|
*/
|
|
140
|
-
traverse(callback: (node: Node
|
|
144
|
+
traverse(callback: (node: Node<T>, traversalPath: Node<T>[]) => void, getNextNodes?: ((arg0: Node<T>) => Node<T>[]) | undefined): void;
|
|
141
145
|
/**
|
|
142
146
|
* @see BaseNode.traverse
|
|
143
147
|
* @param {function(Node): Node[]} [getNextNodes]
|
|
144
148
|
*/
|
|
145
149
|
traverseGenerator(getNextNodes?: ((arg0: Node) => Node[]) | undefined): Generator<{
|
|
146
|
-
node: Node
|
|
147
|
-
traversalPath: Node[];
|
|
150
|
+
node: Node<any>;
|
|
151
|
+
traversalPath: Node<any>[];
|
|
148
152
|
}, void, unknown>;
|
|
149
153
|
/**
|
|
150
154
|
* @param {Node} node
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* A union of all types derived from BaseNode, allowing type check discrimination
|
|
9
9
|
* based on `node.type`. If a new node type is created, it should be added here.
|
|
10
|
-
* @
|
|
10
|
+
* @template [T=any]
|
|
11
|
+
* @typedef {import('./cpu-node.js').CPUNode<T> | import('./network-node.js').NetworkNode<T>} Node
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -22,6 +23,10 @@
|
|
|
22
23
|
* This allows particular optimizations in this class so that we do no need to check for cycles as
|
|
23
24
|
* these methods are called and we can always start traversal at the root node.
|
|
24
25
|
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @template [T=any]
|
|
29
|
+
*/
|
|
25
30
|
class BaseNode {
|
|
26
31
|
/**
|
|
27
32
|
* @param {string} id
|
|
@@ -256,8 +261,8 @@ class BaseNode {
|
|
|
256
261
|
*
|
|
257
262
|
* The `getNextNodes` function takes a visited node and returns which nodes to
|
|
258
263
|
* visit next. It defaults to returning the node's dependents.
|
|
259
|
-
* @param {(node: Node
|
|
260
|
-
* @param {function(Node): Node[]} [getNextNodes]
|
|
264
|
+
* @param {(node: Node<T>, traversalPath: Node<T>[]) => void} callback
|
|
265
|
+
* @param {function(Node<T>): Node<T>[]} [getNextNodes]
|
|
261
266
|
*/
|
|
262
267
|
traverse(callback, getNextNodes) {
|
|
263
268
|
for (const {node, traversalPath} of this.traverseGenerator(getNextNodes)) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/** @type {LH.Util.SelfMap<LH.Crdp.Network.ResourceType>} */
|
|
7
|
+
export const NetworkRequestTypes: LH.Util.SelfMap<LH.Crdp.Network.ResourceType>;
|
|
8
|
+
//# sourceMappingURL=lantern.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** @type {LH.Util.SelfMap<LH.Crdp.Network.ResourceType>} */
|
|
8
|
+
const NetworkRequestTypes = {
|
|
9
|
+
XHR: 'XHR',
|
|
10
|
+
Fetch: 'Fetch',
|
|
11
|
+
EventSource: 'EventSource',
|
|
12
|
+
Script: 'Script',
|
|
13
|
+
Stylesheet: 'Stylesheet',
|
|
14
|
+
Image: 'Image',
|
|
15
|
+
Media: 'Media',
|
|
16
|
+
Font: 'Font',
|
|
17
|
+
Document: 'Document',
|
|
18
|
+
TextTrack: 'TextTrack',
|
|
19
|
+
WebSocket: 'WebSocket',
|
|
20
|
+
Other: 'Other',
|
|
21
|
+
Manifest: 'Manifest',
|
|
22
|
+
SignedExchange: 'SignedExchange',
|
|
23
|
+
Ping: 'Ping',
|
|
24
|
+
Preflight: 'Preflight',
|
|
25
|
+
CSPViolationReport: 'CSPViolationReport',
|
|
26
|
+
Prefetch: 'Prefetch',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
NetworkRequestTypes,
|
|
31
|
+
};
|