lighthouse 12.0.0 → 12.1.0-dev.20240619
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/run.js +5 -38
- package/cli/test/smokehouse/lighthouse-runners/bundle.js +1 -1
- package/cli/test/smokehouse/smokehouse.js +11 -1
- package/core/audits/accessibility/aria-allowed-role.js +7 -9
- package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +2 -2
- package/core/audits/byte-efficiency/byte-efficiency-audit.js +3 -3
- package/core/audits/byte-efficiency/offscreen-images.js +1 -1
- package/core/audits/byte-efficiency/render-blocking-resources.d.ts +3 -3
- package/core/audits/byte-efficiency/render-blocking-resources.js +10 -10
- package/core/audits/dobetterweb/uses-http2.d.ts +2 -2
- package/core/audits/dobetterweb/uses-http2.js +5 -5
- package/core/audits/long-tasks.d.ts +7 -6
- package/core/audits/long-tasks.js +5 -4
- package/core/audits/metrics/first-meaningful-paint.d.ts +1 -17
- package/core/audits/metrics/first-meaningful-paint.js +5 -47
- package/core/audits/metrics/interactive.d.ts +1 -1
- package/core/audits/metrics/interactive.js +1 -1
- package/core/audits/predictive-perf.js +0 -6
- package/core/audits/prioritize-lcp-image.d.ts +1 -1
- package/core/audits/prioritize-lcp-image.js +2 -2
- package/core/audits/redirects.js +2 -3
- package/core/audits/third-party-facades.js +1 -1
- package/core/audits/third-party-summary.js +1 -1
- package/core/audits/uses-rel-preconnect.js +2 -2
- package/core/audits/uses-rel-preload.js +9 -9
- package/core/computed/critical-request-chains.js +3 -3
- package/core/computed/document-urls.js +3 -2
- package/core/computed/load-simulator.d.ts +4 -4
- package/core/computed/load-simulator.js +3 -54
- package/core/computed/main-resource.js +3 -2
- package/core/computed/metrics/interactive.d.ts +6 -0
- package/core/computed/metrics/interactive.js +2 -2
- package/core/computed/metrics/lantern-first-contentful-paint.d.ts +4 -4
- package/core/computed/metrics/lantern-first-contentful-paint.js +3 -3
- package/core/computed/metrics/lantern-interactive.d.ts +4 -4
- package/core/computed/metrics/lantern-interactive.js +6 -6
- package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +4 -4
- package/core/computed/metrics/lantern-largest-contentful-paint.js +3 -3
- package/core/computed/metrics/lantern-max-potential-fid.d.ts +4 -4
- package/core/computed/metrics/lantern-max-potential-fid.js +3 -3
- package/core/computed/metrics/lantern-metric.d.ts +21 -2
- package/core/computed/metrics/lantern-metric.js +39 -4
- package/core/computed/metrics/lantern-speed-index.d.ts +4 -4
- package/core/computed/metrics/lantern-speed-index.js +4 -4
- package/core/computed/metrics/lantern-total-blocking-time.d.ts +4 -4
- package/core/computed/metrics/lantern-total-blocking-time.js +3 -3
- package/core/computed/metrics/timing-summary.js +0 -6
- package/core/computed/metrics/total-blocking-time.js +3 -1
- package/core/computed/navigation-insights.d.ts +2 -20
- package/core/computed/network-analysis.d.ts +0 -5
- package/core/computed/network-analysis.js +2 -42
- package/core/computed/page-dependency-graph.d.ts +5 -3
- package/core/computed/page-dependency-graph.js +17 -7
- package/core/computed/processed-navigation.d.ts +1 -1
- package/core/computed/tbt-impact-tasks.js +4 -2
- package/core/computed/trace-engine-result.d.ts +0 -11
- package/core/computed/trace-engine-result.js +5 -19
- package/core/config/constants.d.ts +28 -53
- package/core/config/constants.js +2 -43
- package/core/gather/driver/navigation.js +1 -1
- package/core/gather/driver/network-monitor.d.ts +2 -1
- package/core/gather/driver/network-monitor.js +4 -4
- package/core/gather/driver/target-manager.d.ts +1 -1
- package/core/gather/driver.d.ts +0 -12
- package/core/gather/driver.js +1 -26
- package/core/gather/gatherers/inspector-issues.js +1 -0
- package/core/gather/gatherers/root-causes.js +0 -1
- package/core/gather/session.d.ts +5 -3
- package/core/gather/session.js +22 -1
- package/core/lib/asset-saver.d.ts +13 -9
- package/core/lib/asset-saver.js +77 -30
- package/core/lib/bf-cache-strings.js +2 -2
- package/core/lib/lantern/{base-node.d.ts → BaseNode.d.ts} +7 -9
- package/core/lib/lantern/{base-node.js → BaseNode.js} +6 -6
- package/core/lib/lantern/BaseNode.test.js +385 -0
- package/core/lib/lantern/CpuNode.d.ts +43 -0
- package/core/lib/lantern/{cpu-node.js → CpuNode.js} +8 -9
- package/core/lib/lantern/{lantern-error.d.ts → LanternError.d.ts} +1 -1
- package/core/lib/lantern/{metric.d.ts → Metric.d.ts} +23 -25
- package/core/lib/lantern/{metric.js → Metric.js} +14 -16
- package/core/lib/lantern/{network-node.d.ts → NetworkNode.d.ts} +6 -7
- package/core/lib/lantern/{network-node.js → NetworkNode.js} +7 -9
- package/core/lib/lantern/PageDependencyGraph.d.ts +82 -0
- package/core/lib/lantern/{page-dependency-graph.js → PageDependencyGraph.js} +185 -50
- package/core/lib/lantern/PageDependencyGraph.test.js +654 -0
- package/core/{computed/metrics/tbt-utils.d.ts → lib/lantern/TBTUtils.d.ts} +1 -1
- package/core/lib/lantern/TBTUtils.test.d.ts +2 -0
- package/core/lib/lantern/TBTUtils.test.js +130 -0
- package/core/lib/lantern/TraceEngineComputationData.d.ts +25 -0
- package/core/lib/lantern/TraceEngineComputationData.js +466 -0
- package/core/lib/lantern/lantern.d.ts +19 -7
- package/core/lib/lantern/lantern.js +21 -1
- package/core/lib/lantern/metrics/{first-contentful-paint.d.ts → FirstContentfulPaint.d.ts} +11 -11
- package/core/lib/lantern/metrics/{first-contentful-paint.js → FirstContentfulPaint.js} +11 -13
- package/core/lib/lantern/metrics/FirstContentfulPaint.test.js +54 -0
- package/core/lib/lantern/metrics/Interactive.d.ts +20 -0
- package/core/lib/lantern/metrics/{interactive.js → Interactive.js} +23 -26
- package/core/lib/lantern/metrics/Interactive.test.js +56 -0
- package/core/lib/lantern/metrics/LargestContentfulPaint.d.ts +19 -0
- package/core/lib/lantern/metrics/{largest-contentful-paint.js → LargestContentfulPaint.js} +16 -19
- package/core/lib/lantern/metrics/LargestContentfulPaint.test.js +42 -0
- package/core/lib/lantern/metrics/MaxPotentialFID.d.ts +24 -0
- package/core/lib/lantern/metrics/{max-potential-fid.js → MaxPotentialFID.js} +12 -13
- package/core/lib/lantern/metrics/MetricTestUtils.d.ts +19 -0
- package/core/lib/lantern/metrics/MetricTestUtils.js +48 -0
- package/core/lib/lantern/metrics/{speed-index.d.ts → SpeedIndex.d.ts} +7 -13
- package/core/lib/lantern/metrics/{speed-index.js → SpeedIndex.js} +14 -16
- package/core/lib/lantern/metrics/SpeedIndex.test.js +83 -0
- package/core/lib/lantern/metrics/TotalBlockingTime.d.ts +25 -0
- package/core/lib/lantern/metrics/{total-blocking-time.js → TotalBlockingTime.js} +13 -16
- package/core/lib/lantern/metrics/__snapshots__/FirstContentfulPaint.test.js.snap +11 -0
- package/core/lib/lantern/metrics/__snapshots__/Interactive.test.js.snap +17 -0
- package/core/lib/lantern/metrics/metrics.d.ts +9 -0
- package/core/lib/lantern/metrics/metrics.js +16 -0
- package/core/lib/lantern/{simulator/connection-pool.d.ts → simulation/ConnectionPool.d.ts} +15 -15
- package/core/lib/lantern/{simulator/connection-pool.js → simulation/ConnectionPool.js} +25 -25
- package/core/lib/lantern/simulation/ConnectionPool.test.js +195 -0
- package/core/lib/lantern/simulation/Constants.d.ts +52 -0
- package/core/lib/lantern/simulation/Constants.js +48 -0
- package/core/lib/lantern/{simulator/dns-cache.d.ts → simulation/DNSCache.d.ts} +3 -3
- package/core/lib/lantern/{simulator/dns-cache.js → simulation/DNSCache.js} +2 -2
- package/core/lib/lantern/simulation/DNSCache.test.js +72 -0
- package/core/lib/lantern/{simulator/network-analyzer.d.ts → simulation/NetworkAnalyzer.d.ts} +34 -21
- package/core/lib/lantern/{simulator/network-analyzer.js → simulation/NetworkAnalyzer.js} +106 -57
- package/core/lib/lantern/simulation/NetworkAnalyzer.test.js +475 -0
- package/core/lib/lantern/{simulator/simulator-timing-map.d.ts → simulation/SimulationTimingMap.d.ts} +7 -7
- package/core/lib/lantern/{simulator/simulator-timing-map.js → simulation/SimulationTimingMap.js} +5 -6
- package/core/lib/lantern/{simulator/simulator.d.ts → simulation/Simulator.d.ts} +21 -19
- package/core/lib/lantern/{simulator/simulator.js → simulation/Simulator.js} +100 -45
- package/core/lib/lantern/simulation/Simulator.test.js +434 -0
- package/core/lib/lantern/simulation/TCPConnection.test.d.ts +2 -0
- package/core/lib/lantern/simulation/TCPConnection.test.js +374 -0
- package/core/lib/lantern/{simulator/tcp-connection.d.ts → simulation/TcpConnection.d.ts} +2 -2
- package/core/lib/lantern/{simulator/tcp-connection.js → simulation/TcpConnection.js} +1 -1
- package/core/lib/lantern/simulation/simulation.d.ts +21 -0
- package/core/lib/lantern/simulation/simulation.js +28 -0
- package/core/lib/lantern/types/lantern.d.ts +145 -20
- package/core/lib/lantern-trace-saver.d.ts +4 -4
- package/core/lib/lantern-trace-saver.js +4 -4
- package/core/lib/navigation-error.js +3 -3
- package/core/lib/network-recorder.js +2 -2
- package/core/lib/network-request.d.ts +29 -3
- package/core/lib/network-request.js +20 -13
- package/core/lib/tracehouse/trace-processor.d.ts +0 -2
- package/core/lib/tracehouse/trace-processor.js +1 -31
- package/core/lib/traces/metric-trace-events.js +0 -5
- package/dist/report/bundle.esm.js +1 -1
- package/dist/report/flow.js +1 -1
- package/dist/report/standalone.js +1 -1
- package/package.json +14 -13
- package/report/renderer/performance-category-renderer.js +1 -1
- package/shared/localization/locales/ar-XB.json +43 -4
- package/shared/localization/locales/ar.json +43 -4
- package/shared/localization/locales/bg.json +43 -4
- package/shared/localization/locales/ca.json +44 -5
- package/shared/localization/locales/cs.json +43 -4
- package/shared/localization/locales/da.json +43 -4
- package/shared/localization/locales/de.json +43 -4
- package/shared/localization/locales/el.json +43 -4
- package/shared/localization/locales/en-GB.json +42 -3
- package/shared/localization/locales/en-US.json +4 -4
- package/shared/localization/locales/en-XA.json +43 -4
- package/shared/localization/locales/en-XL.json +4 -4
- package/shared/localization/locales/es-419.json +43 -4
- package/shared/localization/locales/es.json +42 -3
- package/shared/localization/locales/fi.json +43 -4
- package/shared/localization/locales/fil.json +42 -3
- package/shared/localization/locales/fr.json +42 -3
- package/shared/localization/locales/he.json +48 -9
- package/shared/localization/locales/hi.json +43 -4
- package/shared/localization/locales/hr.json +43 -4
- package/shared/localization/locales/hu.json +42 -3
- package/shared/localization/locales/id.json +42 -3
- package/shared/localization/locales/it.json +43 -4
- package/shared/localization/locales/ja.json +42 -3
- package/shared/localization/locales/ko.json +43 -4
- package/shared/localization/locales/lt.json +42 -3
- package/shared/localization/locales/lv.json +43 -4
- package/shared/localization/locales/nl.json +44 -5
- package/shared/localization/locales/no.json +42 -3
- package/shared/localization/locales/pl.json +43 -4
- package/shared/localization/locales/pt-PT.json +43 -4
- package/shared/localization/locales/pt.json +43 -4
- package/shared/localization/locales/ro.json +43 -4
- package/shared/localization/locales/ru.json +43 -4
- package/shared/localization/locales/sk.json +43 -4
- package/shared/localization/locales/sl.json +42 -3
- package/shared/localization/locales/sr-Latn.json +43 -4
- package/shared/localization/locales/sr.json +43 -4
- package/shared/localization/locales/sv.json +42 -3
- package/shared/localization/locales/ta.json +42 -3
- package/shared/localization/locales/te.json +43 -4
- package/shared/localization/locales/th.json +44 -5
- package/shared/localization/locales/tr.json +43 -4
- package/shared/localization/locales/uk.json +43 -4
- package/shared/localization/locales/vi.json +43 -4
- package/shared/localization/locales/zh-HK.json +43 -4
- package/shared/localization/locales/zh-TW.json +43 -4
- package/shared/localization/locales/zh.json +43 -4
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +1 -0
- package/tsconfig-all.json +1 -0
- package/tsconfig.json +11 -7
- package/types/artifacts.d.ts +23 -25
- package/types/gatherer.d.ts +2 -3
- package/types/lhr/lhr.d.ts +2 -0
- package/core/computed/metrics/first-meaningful-paint.d.ts +0 -21
- package/core/computed/metrics/first-meaningful-paint.js +0 -44
- package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +0 -25
- package/core/computed/metrics/lantern-first-meaningful-paint.js +0 -43
- package/core/lib/lantern/cpu-node.d.ts +0 -44
- package/core/lib/lantern/metrics/first-meaningful-paint.d.ts +0 -6
- package/core/lib/lantern/metrics/first-meaningful-paint.js +0 -64
- package/core/lib/lantern/metrics/interactive.d.ts +0 -26
- package/core/lib/lantern/metrics/largest-contentful-paint.d.ts +0 -19
- package/core/lib/lantern/metrics/max-potential-fid.d.ts +0 -30
- package/core/lib/lantern/metrics/total-blocking-time.d.ts +0 -31
- package/core/lib/lantern/page-dependency-graph.d.ts +0 -58
- /package/core/lib/lantern/{lantern-error.js → LanternError.js} +0 -0
- /package/core/{computed/metrics/tbt-utils.js → lib/lantern/TBTUtils.js} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export type Node = import('../
|
|
2
|
-
export type NetworkNode<T> = import('../
|
|
3
|
-
export type CpuNode = import('../
|
|
4
|
-
/** @typedef {import('../
|
|
5
|
-
/** @template T @typedef {import('../
|
|
6
|
-
/** @typedef {import('../
|
|
7
|
-
export class FirstContentfulPaint extends Metric {
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
export type NetworkNode<T> = import('../NetworkNode.js').NetworkNode<T>;
|
|
3
|
+
export type CpuNode = import('../CpuNode.js').CPUNode;
|
|
4
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
5
|
+
/** @template T @typedef {import('../NetworkNode.js').NetworkNode<T>} NetworkNode */
|
|
6
|
+
/** @typedef {import('../CpuNode.js').CPUNode} CpuNode */
|
|
7
|
+
export class FirstContentfulPaint extends Lantern.Metric {
|
|
8
8
|
/**
|
|
9
9
|
* @template T
|
|
10
10
|
* @typedef FirstPaintBasedGraphOpts
|
|
@@ -37,7 +37,7 @@ export class FirstContentfulPaint extends Metric {
|
|
|
37
37
|
* The function that determines
|
|
38
38
|
* which resources should be considered *possibly* render-blocking.
|
|
39
39
|
*/
|
|
40
|
-
treatNodeAsRenderBlocking: (arg0:
|
|
40
|
+
treatNodeAsRenderBlocking: (arg0: Lantern.NetworkNode<T>) => boolean;
|
|
41
41
|
/**
|
|
42
42
|
* The function that
|
|
43
43
|
* determines which CPU nodes should also be included in our blocking node IDs set,
|
|
@@ -66,7 +66,7 @@ export class FirstContentfulPaint extends Metric {
|
|
|
66
66
|
* The function that determines
|
|
67
67
|
* which resources should be considered *possibly* render-blocking.
|
|
68
68
|
*/
|
|
69
|
-
treatNodeAsRenderBlocking: (arg0:
|
|
69
|
+
treatNodeAsRenderBlocking: (arg0: Lantern.NetworkNode<T_1>) => boolean;
|
|
70
70
|
/**
|
|
71
71
|
* The function that
|
|
72
72
|
* determines which CPU nodes should also be included in our blocking node IDs set,
|
|
@@ -75,5 +75,5 @@ export class FirstContentfulPaint extends Metric {
|
|
|
75
75
|
additionalCpuNodesToTreatAsRenderBlocking?: ((arg0: CpuNode) => boolean) | undefined;
|
|
76
76
|
}): Node;
|
|
77
77
|
}
|
|
78
|
-
import
|
|
79
|
-
//# sourceMappingURL=
|
|
78
|
+
import * as Lantern from '../lantern.js';
|
|
79
|
+
//# sourceMappingURL=FirstContentfulPaint.d.ts.map
|
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Lantern from '../
|
|
8
|
-
import {Metric} from '../metric.js';
|
|
9
|
-
import {BaseNode} from '../base-node.js';
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
10
8
|
|
|
11
|
-
/** @typedef {import('../
|
|
12
|
-
/** @template T @typedef {import('../
|
|
13
|
-
/** @typedef {import('../
|
|
9
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
10
|
+
/** @template T @typedef {import('../NetworkNode.js').NetworkNode<T>} NetworkNode */
|
|
11
|
+
/** @typedef {import('../CpuNode.js').CPUNode} CpuNode */
|
|
14
12
|
|
|
15
|
-
class FirstContentfulPaint extends Metric {
|
|
13
|
+
class FirstContentfulPaint extends Lantern.Metric {
|
|
16
14
|
/**
|
|
17
15
|
* @return {Lantern.Simulation.MetricCoefficients}
|
|
18
16
|
*/
|
|
@@ -57,7 +55,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
57
55
|
/** @type {Array<CpuNode>} */
|
|
58
56
|
const cpuNodes = [];
|
|
59
57
|
graph.traverse(node => {
|
|
60
|
-
if (node.type === BaseNode.TYPES.CPU) {
|
|
58
|
+
if (node.type === Lantern.BaseNode.TYPES.CPU) {
|
|
61
59
|
// A task is *possibly* render blocking if it *started* before cutoffTimestamp.
|
|
62
60
|
// We use startTime here because the paint event can be *inside* the task that was render blocking.
|
|
63
61
|
if (node.startTime <= cutoffTimestamp) cpuNodes.push(node);
|
|
@@ -75,7 +73,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
75
73
|
cpuNodes.sort((a, b) => a.startTime - b.startTime);
|
|
76
74
|
|
|
77
75
|
// A script is *possibly* render blocking if it finished loading before cutoffTimestamp.
|
|
78
|
-
const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {
|
|
76
|
+
const possiblyRenderBlockingScriptUrls = Lantern.Metric.getScriptUrls(graph, node => {
|
|
79
77
|
// The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,
|
|
80
78
|
// but here it only receives scripts to evaluate. It's a no-op in this case, but it will
|
|
81
79
|
// matter below in the getFirstPaintBasedGraph clone operation.
|
|
@@ -147,13 +145,13 @@ class FirstContentfulPaint extends Metric {
|
|
|
147
145
|
const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;
|
|
148
146
|
|
|
149
147
|
return dependencyGraph.cloneWithRelationships(node => {
|
|
150
|
-
if (node.type === BaseNode.TYPES.NETWORK) {
|
|
148
|
+
if (node.type === Lantern.BaseNode.TYPES.NETWORK) {
|
|
151
149
|
// Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)
|
|
152
150
|
// endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.
|
|
153
151
|
const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;
|
|
154
152
|
if (endedAfterPaint && !node.isMainDocument()) return false;
|
|
155
153
|
|
|
156
|
-
const url = node.
|
|
154
|
+
const url = node.request.url;
|
|
157
155
|
// If the URL definitely wasn't render-blocking then we filter it out.
|
|
158
156
|
if (definitelyNotRenderBlockingScriptUrls.has(url)) {
|
|
159
157
|
return false;
|
|
@@ -170,7 +168,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
170
168
|
|
|
171
169
|
/**
|
|
172
170
|
* @param {Node} dependencyGraph
|
|
173
|
-
* @param {
|
|
171
|
+
* @param {Lantern.Simulation.ProcessedNavigation} processedNavigation
|
|
174
172
|
* @return {Node}
|
|
175
173
|
*/
|
|
176
174
|
static getOptimisticGraph(dependencyGraph, processedNavigation) {
|
|
@@ -186,7 +184,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
186
184
|
|
|
187
185
|
/**
|
|
188
186
|
* @param {Node} dependencyGraph
|
|
189
|
-
* @param {
|
|
187
|
+
* @param {Lantern.Simulation.ProcessedNavigation} processedNavigation
|
|
190
188
|
* @return {Node}
|
|
191
189
|
*/
|
|
192
190
|
static getPessimisticGraph(dependencyGraph, processedNavigation) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import assert from 'assert/strict';
|
|
8
|
+
|
|
9
|
+
import * as Lantern from '../lantern.js';
|
|
10
|
+
import {readJson} from '../../../test/test-utils.js';
|
|
11
|
+
import {getComputationDataFromFixture} from './MetricTestUtils.js';
|
|
12
|
+
|
|
13
|
+
const {FirstContentfulPaint} = Lantern.Metrics;
|
|
14
|
+
|
|
15
|
+
const trace = readJson('../../../test/fixtures/artifacts/progressive-app/trace.json', import.meta);
|
|
16
|
+
|
|
17
|
+
describe('Metrics: Lantern FCP', () => {
|
|
18
|
+
it('should compute predicted value', async () => {
|
|
19
|
+
const data = await getComputationDataFromFixture({trace});
|
|
20
|
+
const result = await FirstContentfulPaint.compute(data);
|
|
21
|
+
|
|
22
|
+
expect({
|
|
23
|
+
timing: Math.round(result.timing),
|
|
24
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
25
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs),
|
|
26
|
+
optimisticNodeTimings: result.optimisticEstimate.nodeTimings.size,
|
|
27
|
+
pessimisticNodeTimings: result.pessimisticEstimate.nodeTimings.size,
|
|
28
|
+
}).toMatchSnapshot();
|
|
29
|
+
assert.ok(result.optimisticGraph, 'should have created optimistic graph');
|
|
30
|
+
assert.ok(result.pessimisticGraph, 'should have created pessimistic graph');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should handle negative request networkEndTime', async () => {
|
|
34
|
+
const data = await getComputationDataFromFixture({trace});
|
|
35
|
+
data.graph.request.networkEndTime = -1;
|
|
36
|
+
const result = await FirstContentfulPaint.compute(data);
|
|
37
|
+
|
|
38
|
+
const optimisticNodes = [];
|
|
39
|
+
result.optimisticGraph.traverse(node => {
|
|
40
|
+
if (node.type === 'network') {
|
|
41
|
+
optimisticNodes.push(node);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
expect(optimisticNodes.map(node => node.request.url)).toEqual(['https://squoosh.app/']);
|
|
45
|
+
|
|
46
|
+
const pessimisticNodes = [];
|
|
47
|
+
result.pessimisticGraph.traverse(node => {
|
|
48
|
+
if (node.type === 'network') {
|
|
49
|
+
pessimisticNodes.push(node);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
expect(pessimisticNodes.map(node => node.request.url)).toEqual(['https://squoosh.app/']);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
export class Interactive extends Lantern.Metric {
|
|
3
|
+
/**
|
|
4
|
+
* @param {Node} dependencyGraph
|
|
5
|
+
* @return {Node}
|
|
6
|
+
*/
|
|
7
|
+
static getOptimisticGraph(dependencyGraph: Node): Node;
|
|
8
|
+
/**
|
|
9
|
+
* @param {Node} dependencyGraph
|
|
10
|
+
* @return {Node}
|
|
11
|
+
*/
|
|
12
|
+
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
13
|
+
/**
|
|
14
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
15
|
+
* @return {number}
|
|
16
|
+
*/
|
|
17
|
+
static getLastLongTaskEndTime(nodeTimings: Lantern.Simulation.Result['nodeTimings'], duration?: number): number;
|
|
18
|
+
}
|
|
19
|
+
import * as Lantern from '../lantern.js';
|
|
20
|
+
//# sourceMappingURL=Interactive.d.ts.map
|
|
@@ -4,19 +4,16 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Lantern from '../
|
|
8
|
-
import {Metric} from '../metric.js';
|
|
9
|
-
import {BaseNode} from '../base-node.js';
|
|
10
|
-
import {NetworkRequestTypes} from '../lantern.js';
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
11
8
|
|
|
12
|
-
/** @typedef {import('../
|
|
9
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
13
10
|
|
|
14
11
|
// Any CPU task of 20 ms or more will end up being a critical long task on mobile
|
|
15
12
|
const CRITICAL_LONG_TASK_THRESHOLD = 20;
|
|
16
13
|
|
|
17
|
-
class Interactive extends Metric {
|
|
14
|
+
class Interactive extends Lantern.Metric {
|
|
18
15
|
/**
|
|
19
|
-
* @return {
|
|
16
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
20
17
|
*/
|
|
21
18
|
static get COEFFICIENTS() {
|
|
22
19
|
return {
|
|
@@ -36,18 +33,18 @@ class Interactive extends Metric {
|
|
|
36
33
|
|
|
37
34
|
return dependencyGraph.cloneWithRelationships(node => {
|
|
38
35
|
// Include everything that might be a long task
|
|
39
|
-
if (node.type === BaseNode.TYPES.CPU) {
|
|
36
|
+
if (node.type === Lantern.BaseNode.TYPES.CPU) {
|
|
40
37
|
return node.duration > minimumCpuTaskDuration;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
// Include all scripts and high priority requests, exclude all images
|
|
44
|
-
const isImage = node.
|
|
45
|
-
const isScript = node.
|
|
41
|
+
const isImage = node.request.resourceType === Lantern.NetworkRequestTypes.Image;
|
|
42
|
+
const isScript = node.request.resourceType === Lantern.NetworkRequestTypes.Script;
|
|
46
43
|
return (
|
|
47
44
|
!isImage &&
|
|
48
45
|
(isScript ||
|
|
49
|
-
node.
|
|
50
|
-
node.
|
|
46
|
+
node.request.priority === 'High' ||
|
|
47
|
+
node.request.priority === 'VeryHigh')
|
|
51
48
|
);
|
|
52
49
|
});
|
|
53
50
|
}
|
|
@@ -61,17 +58,17 @@ class Interactive extends Metric {
|
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
/**
|
|
64
|
-
* @param {
|
|
65
|
-
* @param {import('../
|
|
66
|
-
* @return {
|
|
61
|
+
* @param {Lantern.Simulation.Result} simulationResult
|
|
62
|
+
* @param {import('../Metric.js').Extras} extras
|
|
63
|
+
* @return {Lantern.Simulation.Result}
|
|
67
64
|
*/
|
|
68
65
|
static getEstimateFromSimulation(simulationResult, extras) {
|
|
69
|
-
if (!extras.
|
|
66
|
+
if (!extras.lcpResult) throw new Error('missing lcpResult');
|
|
70
67
|
|
|
71
68
|
const lastTaskAt = Interactive.getLastLongTaskEndTime(simulationResult.nodeTimings);
|
|
72
69
|
const minimumTime = extras.optimistic
|
|
73
|
-
? extras.
|
|
74
|
-
: extras.
|
|
70
|
+
? extras.lcpResult.optimisticEstimate.timeInMs
|
|
71
|
+
: extras.lcpResult.pessimisticEstimate.timeInMs;
|
|
75
72
|
return {
|
|
76
73
|
timeInMs: Math.max(minimumTime, lastTaskAt),
|
|
77
74
|
nodeTimings: simulationResult.nodeTimings,
|
|
@@ -80,28 +77,28 @@ class Interactive extends Metric {
|
|
|
80
77
|
|
|
81
78
|
/**
|
|
82
79
|
* @param {Lantern.Simulation.MetricComputationDataInput} data
|
|
83
|
-
* @param {Omit<import('../
|
|
84
|
-
* @return {Promise<
|
|
80
|
+
* @param {Omit<import('../Metric.js').Extras, 'optimistic'>=} extras
|
|
81
|
+
* @return {Promise<Lantern.Metrics.Result>}
|
|
85
82
|
*/
|
|
86
83
|
static async compute(data, extras) {
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
throw new Error('
|
|
84
|
+
const lcpResult = extras?.lcpResult;
|
|
85
|
+
if (!lcpResult) {
|
|
86
|
+
throw new Error('LCP is required to calculate the Interactive metric');
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
const metricResult = await super.compute(data, extras);
|
|
93
|
-
metricResult.timing = Math.max(metricResult.timing,
|
|
90
|
+
metricResult.timing = Math.max(metricResult.timing, lcpResult.timing);
|
|
94
91
|
return metricResult;
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
/**
|
|
98
|
-
* @param {
|
|
95
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
99
96
|
* @return {number}
|
|
100
97
|
*/
|
|
101
98
|
static getLastLongTaskEndTime(nodeTimings, duration = 50) {
|
|
102
99
|
return Array.from(nodeTimings.entries())
|
|
103
100
|
.filter(([node, timing]) => {
|
|
104
|
-
if (node.type !== BaseNode.TYPES.CPU) return false;
|
|
101
|
+
if (node.type !== Lantern.BaseNode.TYPES.CPU) return false;
|
|
105
102
|
return timing.duration > duration;
|
|
106
103
|
})
|
|
107
104
|
.map(([_, timing]) => timing.endTime)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import assert from 'assert/strict';
|
|
8
|
+
|
|
9
|
+
import * as Lantern from '../lantern.js';
|
|
10
|
+
import {getComputationDataFromFixture} from './MetricTestUtils.js';
|
|
11
|
+
import {readJson} from '../../../test/test-utils.js';
|
|
12
|
+
|
|
13
|
+
const {Interactive, FirstContentfulPaint, LargestContentfulPaint} = Lantern.Metrics;
|
|
14
|
+
|
|
15
|
+
const trace = readJson('../../../test/fixtures/artifacts/progressive-app/trace.json', import.meta);
|
|
16
|
+
const iframeTrace = readJson('../../../test/fixtures/artifacts/iframe/trace.json', import.meta);
|
|
17
|
+
|
|
18
|
+
describe('Metrics: Lantern TTI', () => {
|
|
19
|
+
it('should compute predicted value', async () => {
|
|
20
|
+
const data = await getComputationDataFromFixture({trace});
|
|
21
|
+
const result = await Interactive.compute(data, {
|
|
22
|
+
lcpResult: await LargestContentfulPaint.compute(data, {
|
|
23
|
+
fcpResult: await FirstContentfulPaint.compute(data),
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect({
|
|
28
|
+
timing: Math.round(result.timing),
|
|
29
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
30
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs),
|
|
31
|
+
}).toMatchSnapshot();
|
|
32
|
+
assert.equal(result.optimisticEstimate.nodeTimings.size, 14);
|
|
33
|
+
assert.equal(result.pessimisticEstimate.nodeTimings.size, 31);
|
|
34
|
+
assert.ok(result.optimisticGraph, 'should have created optimistic graph');
|
|
35
|
+
assert.ok(result.pessimisticGraph, 'should have created pessimistic graph');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should compute predicted value on iframes with substantial layout', async () => {
|
|
39
|
+
const data = await getComputationDataFromFixture({
|
|
40
|
+
trace: iframeTrace,
|
|
41
|
+
});
|
|
42
|
+
const result = await Interactive.compute(data, {
|
|
43
|
+
lcpResult: await LargestContentfulPaint.compute(data, {
|
|
44
|
+
fcpResult: await FirstContentfulPaint.compute(data),
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
expect({
|
|
49
|
+
timing: Math.round(result.timing),
|
|
50
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
51
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs),
|
|
52
|
+
}).toMatchSnapshot();
|
|
53
|
+
assert.ok(result.optimisticGraph, 'should have created optimistic graph');
|
|
54
|
+
assert.ok(result.pessimisticGraph, 'should have created pessimistic graph');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
3
|
+
export class LargestContentfulPaint extends Lantern.Metric {
|
|
4
|
+
/**
|
|
5
|
+
* Low priority image nodes are usually offscreen and very unlikely to be the
|
|
6
|
+
* resource that is required for LCP. Our LCP graphs include everything except for these images.
|
|
7
|
+
*
|
|
8
|
+
* @param {Node} node
|
|
9
|
+
* @return {boolean}
|
|
10
|
+
*/
|
|
11
|
+
static isNotLowPriorityImageNode(node: Node): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* @param {Lantern.Simulation.Result} simulationResult
|
|
14
|
+
* @return {Lantern.Simulation.Result}
|
|
15
|
+
*/
|
|
16
|
+
static getEstimateFromSimulation(simulationResult: Lantern.Simulation.Result): Lantern.Simulation.Result;
|
|
17
|
+
}
|
|
18
|
+
import * as Lantern from '../lantern.js';
|
|
19
|
+
//# sourceMappingURL=LargestContentfulPaint.d.ts.map
|
|
@@ -4,16 +4,13 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Lantern from '../
|
|
8
|
-
import {Metric} from '../metric.js';
|
|
9
|
-
import {FirstContentfulPaint} from './first-contentful-paint.js';
|
|
10
|
-
import {LanternError} from '../lantern-error.js';
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
11
8
|
|
|
12
|
-
/** @typedef {import('../
|
|
9
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
13
10
|
|
|
14
|
-
class LargestContentfulPaint extends Metric {
|
|
11
|
+
class LargestContentfulPaint extends Lantern.Metric {
|
|
15
12
|
/**
|
|
16
|
-
* @return {
|
|
13
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
17
14
|
*/
|
|
18
15
|
static get COEFFICIENTS() {
|
|
19
16
|
return {
|
|
@@ -32,23 +29,23 @@ class LargestContentfulPaint extends Metric {
|
|
|
32
29
|
*/
|
|
33
30
|
static isNotLowPriorityImageNode(node) {
|
|
34
31
|
if (node.type !== 'network') return true;
|
|
35
|
-
const isImage = node.
|
|
36
|
-
const isLowPriority = node.
|
|
32
|
+
const isImage = node.request.resourceType === 'Image';
|
|
33
|
+
const isLowPriority = node.request.priority === 'Low' || node.request.priority === 'VeryLow';
|
|
37
34
|
return !isImage || !isLowPriority;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
/**
|
|
41
38
|
* @param {Node} dependencyGraph
|
|
42
|
-
* @param {
|
|
39
|
+
* @param {Lantern.Simulation.ProcessedNavigation} processedNavigation
|
|
43
40
|
* @return {Node}
|
|
44
41
|
*/
|
|
45
42
|
static getOptimisticGraph(dependencyGraph, processedNavigation) {
|
|
46
43
|
const lcp = processedNavigation.timestamps.largestContentfulPaint;
|
|
47
44
|
if (!lcp) {
|
|
48
|
-
throw new
|
|
45
|
+
throw new Lantern.Error('NO_LCP');
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
48
|
+
return Lantern.Metrics.FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
52
49
|
cutoffTimestamp: lcp,
|
|
53
50
|
treatNodeAsRenderBlocking: LargestContentfulPaint.isNotLowPriorityImageNode,
|
|
54
51
|
});
|
|
@@ -56,16 +53,16 @@ class LargestContentfulPaint extends Metric {
|
|
|
56
53
|
|
|
57
54
|
/**
|
|
58
55
|
* @param {Node} dependencyGraph
|
|
59
|
-
* @param {
|
|
56
|
+
* @param {Lantern.Simulation.ProcessedNavigation} processedNavigation
|
|
60
57
|
* @return {Node}
|
|
61
58
|
*/
|
|
62
59
|
static getPessimisticGraph(dependencyGraph, processedNavigation) {
|
|
63
60
|
const lcp = processedNavigation.timestamps.largestContentfulPaint;
|
|
64
61
|
if (!lcp) {
|
|
65
|
-
throw new
|
|
62
|
+
throw new Lantern.Error('NO_LCP');
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
65
|
+
return Lantern.Metrics.FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
69
66
|
cutoffTimestamp: lcp,
|
|
70
67
|
treatNodeAsRenderBlocking: _ => true,
|
|
71
68
|
// For pessimistic LCP we'll include *all* layout nodes
|
|
@@ -74,8 +71,8 @@ class LargestContentfulPaint extends Metric {
|
|
|
74
71
|
}
|
|
75
72
|
|
|
76
73
|
/**
|
|
77
|
-
* @param {
|
|
78
|
-
* @return {
|
|
74
|
+
* @param {Lantern.Simulation.Result} simulationResult
|
|
75
|
+
* @return {Lantern.Simulation.Result}
|
|
79
76
|
*/
|
|
80
77
|
static getEstimateFromSimulation(simulationResult) {
|
|
81
78
|
const nodeTimesNotOffscreenImages = Array.from(simulationResult.nodeTimings.entries())
|
|
@@ -90,8 +87,8 @@ class LargestContentfulPaint extends Metric {
|
|
|
90
87
|
|
|
91
88
|
/**
|
|
92
89
|
* @param {Lantern.Simulation.MetricComputationDataInput} data
|
|
93
|
-
* @param {Omit<import('../
|
|
94
|
-
* @return {Promise<
|
|
90
|
+
* @param {Omit<import('../Metric.js').Extras, 'optimistic'>=} extras
|
|
91
|
+
* @return {Promise<Lantern.Metrics.Result>}
|
|
95
92
|
*/
|
|
96
93
|
static async compute(data, extras) {
|
|
97
94
|
const fcpResult = extras?.fcpResult;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import assert from 'assert/strict';
|
|
8
|
+
|
|
9
|
+
import * as Lantern from '../lantern.js';
|
|
10
|
+
import {getComputationDataFromFixture} from './MetricTestUtils.js';
|
|
11
|
+
import {readJson} from '../../../test/test-utils.js';
|
|
12
|
+
|
|
13
|
+
const {FirstContentfulPaint, LargestContentfulPaint} = Lantern.Metrics;
|
|
14
|
+
|
|
15
|
+
const trace = readJson('../../../test/fixtures/artifacts/paul/trace.json', import.meta);
|
|
16
|
+
|
|
17
|
+
describe('Metrics: Lantern LCP', () => {
|
|
18
|
+
it('should compute predicted value', async () => {
|
|
19
|
+
const data = await getComputationDataFromFixture({trace});
|
|
20
|
+
const result = await LargestContentfulPaint.compute(data, {
|
|
21
|
+
fcpResult: await FirstContentfulPaint.compute(data),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect({
|
|
25
|
+
timing: Math.round(result.timing),
|
|
26
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
27
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs),
|
|
28
|
+
optimisticNodeTimings: result.optimisticEstimate.nodeTimings.size,
|
|
29
|
+
pessimisticNodeTimings: result.pessimisticEstimate.nodeTimings.size}).
|
|
30
|
+
toMatchInlineSnapshot(`
|
|
31
|
+
Object {
|
|
32
|
+
"optimistic": 1457,
|
|
33
|
+
"optimisticNodeTimings": 8,
|
|
34
|
+
"pessimistic": 1616,
|
|
35
|
+
"pessimisticNodeTimings": 9,
|
|
36
|
+
"timing": 1536,
|
|
37
|
+
}
|
|
38
|
+
`);
|
|
39
|
+
assert.ok(result.optimisticGraph, 'should have created optimistic graph');
|
|
40
|
+
assert.ok(result.pessimisticGraph, 'should have created pessimistic graph');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
3
|
+
export class MaxPotentialFID extends Lantern.Metric {
|
|
4
|
+
/**
|
|
5
|
+
* @param {Node} dependencyGraph
|
|
6
|
+
* @return {Node}
|
|
7
|
+
*/
|
|
8
|
+
static getOptimisticGraph(dependencyGraph: Node): Node;
|
|
9
|
+
/**
|
|
10
|
+
* @param {Node} dependencyGraph
|
|
11
|
+
* @return {Node}
|
|
12
|
+
*/
|
|
13
|
+
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
14
|
+
/**
|
|
15
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
16
|
+
* @param {number} fcpTimeInMs
|
|
17
|
+
* @return {Array<{duration: number}>}
|
|
18
|
+
*/
|
|
19
|
+
static getTimingsAfterFCP(nodeTimings: Lantern.Simulation.Result['nodeTimings'], fcpTimeInMs: number): Array<{
|
|
20
|
+
duration: number;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
import * as Lantern from '../lantern.js';
|
|
24
|
+
//# sourceMappingURL=MaxPotentialFID.d.ts.map
|
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Lantern from '../
|
|
8
|
-
import {Metric} from '../metric.js';
|
|
9
|
-
import {BaseNode} from '../base-node.js';
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
10
8
|
|
|
11
|
-
/** @typedef {import('../
|
|
9
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
12
10
|
|
|
13
|
-
class MaxPotentialFID extends Metric {
|
|
11
|
+
class MaxPotentialFID extends Lantern.Metric {
|
|
14
12
|
/**
|
|
15
|
-
* @return {
|
|
13
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
16
14
|
*/
|
|
17
15
|
static get COEFFICIENTS() {
|
|
18
16
|
return {
|
|
@@ -39,9 +37,9 @@ class MaxPotentialFID extends Metric {
|
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
/**
|
|
42
|
-
* @param {
|
|
43
|
-
* @param {import('../
|
|
44
|
-
* @return {
|
|
40
|
+
* @param {Lantern.Simulation.Result} simulation
|
|
41
|
+
* @param {import('../Metric.js').Extras} extras
|
|
42
|
+
* @return {Lantern.Simulation.Result}
|
|
45
43
|
*/
|
|
46
44
|
static getEstimateFromSimulation(simulation, extras) {
|
|
47
45
|
if (!extras.fcpResult) throw new Error('missing fcpResult');
|
|
@@ -65,8 +63,8 @@ class MaxPotentialFID extends Metric {
|
|
|
65
63
|
|
|
66
64
|
/**
|
|
67
65
|
* @param {Lantern.Simulation.MetricComputationDataInput} data
|
|
68
|
-
* @param {Omit<import('../
|
|
69
|
-
* @return {Promise<
|
|
66
|
+
* @param {Omit<import('../Metric.js').Extras, 'optimistic'>=} extras
|
|
67
|
+
* @return {Promise<Lantern.Metrics.Result>}
|
|
70
68
|
*/
|
|
71
69
|
static compute(data, extras) {
|
|
72
70
|
const fcpResult = extras?.fcpResult;
|
|
@@ -78,13 +76,14 @@ class MaxPotentialFID extends Metric {
|
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
/**
|
|
81
|
-
* @param {
|
|
79
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
82
80
|
* @param {number} fcpTimeInMs
|
|
83
81
|
* @return {Array<{duration: number}>}
|
|
84
82
|
*/
|
|
85
83
|
static getTimingsAfterFCP(nodeTimings, fcpTimeInMs) {
|
|
86
84
|
return Array.from(nodeTimings.entries())
|
|
87
|
-
.filter(([node, timing]) =>
|
|
85
|
+
.filter(([node, timing]) =>
|
|
86
|
+
node.type === Lantern.BaseNode.TYPES.CPU && timing.endTime > fcpTimeInMs)
|
|
88
87
|
.map(([_, timing]) => timing);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {TraceEngine.Types.TraceEvents.TraceEventData[]} traceEvents
|
|
3
|
+
*/
|
|
4
|
+
export function runTraceEngine(traceEvents: TraceEngine.Types.TraceEvents.TraceEventData[]): Promise<TraceEngine.Handlers.Types.EnabledHandlerDataWithMeta<typeof TraceEngine.Handlers.ModelHandlers>>;
|
|
5
|
+
/**
|
|
6
|
+
* @param {{trace: Lantern.Trace, settings?: Lantern.Simulation.Settings, URL?: Lantern.Simulation.URL}} opts
|
|
7
|
+
*/
|
|
8
|
+
export function getComputationDataFromFixture({ trace, settings, URL }: {
|
|
9
|
+
trace: Lantern.Trace;
|
|
10
|
+
settings?: Lantern.Simulation.Settings;
|
|
11
|
+
URL?: Lantern.Simulation.URL;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
simulator: Lantern.Simulation.Simulator<any>;
|
|
14
|
+
graph: import("../PageDependencyGraph.js").Node;
|
|
15
|
+
processedNavigation: import("../types/lantern.js").Simulation.ProcessedNavigation;
|
|
16
|
+
}>;
|
|
17
|
+
import * as TraceEngine from '@paulirish/trace_engine';
|
|
18
|
+
import * as Lantern from '../lantern.js';
|
|
19
|
+
//# sourceMappingURL=MetricTestUtils.d.ts.map
|