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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as TraceEngine from '@paulirish/trace_engine';
|
|
8
|
+
|
|
9
|
+
import * as Lantern from '../lantern.js';
|
|
10
|
+
import {polyfillDOMRect} from '../../polyfill-dom-rect.js';
|
|
11
|
+
|
|
12
|
+
polyfillDOMRect();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {TraceEngine.Types.TraceEvents.TraceEventData[]} traceEvents
|
|
16
|
+
*/
|
|
17
|
+
async function runTraceEngine(traceEvents) {
|
|
18
|
+
const processor = TraceEngine.Processor.TraceProcessor.createWithAllHandlers();
|
|
19
|
+
await processor.parse(traceEvents);
|
|
20
|
+
if (!processor.traceParsedData) throw new Error('No data');
|
|
21
|
+
return processor.traceParsedData;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {{trace: Lantern.Trace, settings?: Lantern.Simulation.Settings, URL?: Lantern.Simulation.URL}} opts
|
|
26
|
+
*/
|
|
27
|
+
async function getComputationDataFromFixture({trace, settings, URL}) {
|
|
28
|
+
settings = settings ?? /** @type {Lantern.Simulation.Settings} */({});
|
|
29
|
+
if (!settings.throttlingMethod) settings.throttlingMethod = 'simulate';
|
|
30
|
+
const traceEngineData = await runTraceEngine(
|
|
31
|
+
/** @type {TraceEngine.Types.TraceEvents.TraceEventData[]} */ (trace.traceEvents)
|
|
32
|
+
);
|
|
33
|
+
const requests =
|
|
34
|
+
Lantern.TraceEngineComputationData.createNetworkRequests(trace, traceEngineData);
|
|
35
|
+
const networkAnalysis = Lantern.Simulation.NetworkAnalyzer.analyze(requests);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
simulator: Lantern.Simulation.Simulator.createSimulator({...settings, networkAnalysis}),
|
|
39
|
+
graph: Lantern.TraceEngineComputationData.createGraph(requests, trace, traceEngineData, URL),
|
|
40
|
+
processedNavigation:
|
|
41
|
+
Lantern.TraceEngineComputationData.createProcessedNavigation(traceEngineData),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
runTraceEngine,
|
|
47
|
+
getComputationDataFromFixture,
|
|
48
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export type Node = import('../
|
|
2
|
-
/** @typedef {import('../
|
|
3
|
-
export class SpeedIndex extends Metric {
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
3
|
+
export class SpeedIndex extends Lantern.Metric {
|
|
4
4
|
/**
|
|
5
5
|
* @param {Node} dependencyGraph
|
|
6
6
|
* @return {Node}
|
|
@@ -11,12 +11,6 @@ export class SpeedIndex extends Metric {
|
|
|
11
11
|
* @return {Node}
|
|
12
12
|
*/
|
|
13
13
|
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
14
|
-
/**
|
|
15
|
-
* @param {LH.Gatherer.Simulation.Result} simulationResult
|
|
16
|
-
* @param {import('../metric.js').Extras} extras
|
|
17
|
-
* @return {LH.Gatherer.Simulation.Result}
|
|
18
|
-
*/
|
|
19
|
-
static getEstimateFromSimulation(simulationResult: LH.Gatherer.Simulation.Result, extras: import('../metric.js').Extras): LH.Gatherer.Simulation.Result;
|
|
20
14
|
/**
|
|
21
15
|
* Approximate speed index using layout events from the simulated node timings.
|
|
22
16
|
* The layout-based speed index is the weighted average of the endTime of CPU nodes that contained
|
|
@@ -28,11 +22,11 @@ export class SpeedIndex extends Metric {
|
|
|
28
22
|
* different methods. Read more in the evaluation doc.
|
|
29
23
|
*
|
|
30
24
|
* @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#
|
|
31
|
-
* @param {
|
|
25
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
32
26
|
* @param {number} fcpTimeInMs
|
|
33
27
|
* @return {number}
|
|
34
28
|
*/
|
|
35
|
-
static computeLayoutBasedSpeedIndex(nodeTimings:
|
|
29
|
+
static computeLayoutBasedSpeedIndex(nodeTimings: Lantern.Simulation.Result['nodeTimings'], fcpTimeInMs: number): number;
|
|
36
30
|
}
|
|
37
|
-
import
|
|
38
|
-
//# sourceMappingURL=
|
|
31
|
+
import * as Lantern from '../lantern.js';
|
|
32
|
+
//# sourceMappingURL=SpeedIndex.d.ts.map
|
|
@@ -4,17 +4,15 @@
|
|
|
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
9
|
const mobileSlow4GRtt = 150;
|
|
12
10
|
|
|
13
|
-
/** @typedef {import('../
|
|
11
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
14
12
|
|
|
15
|
-
class SpeedIndex extends Metric {
|
|
13
|
+
class SpeedIndex extends Lantern.Metric {
|
|
16
14
|
/**
|
|
17
|
-
* @return {
|
|
15
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
18
16
|
*/
|
|
19
17
|
static get COEFFICIENTS() {
|
|
20
18
|
return {
|
|
@@ -28,7 +26,7 @@ class SpeedIndex extends Metric {
|
|
|
28
26
|
|
|
29
27
|
/**
|
|
30
28
|
* @param {number} rttMs
|
|
31
|
-
* @return {
|
|
29
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
32
30
|
*/
|
|
33
31
|
static getScaledCoefficients(rttMs) { // eslint-disable-line no-unused-vars
|
|
34
32
|
// We want to scale our default coefficients based on the speed of the connection.
|
|
@@ -70,17 +68,17 @@ class SpeedIndex extends Metric {
|
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
/**
|
|
73
|
-
* @param {
|
|
74
|
-
* @param {import('../
|
|
75
|
-
* @return {
|
|
71
|
+
* @param {Lantern.Simulation.Result} simulationResult
|
|
72
|
+
* @param {import('../Metric.js').Extras} extras
|
|
73
|
+
* @return {Lantern.Simulation.Result}
|
|
76
74
|
*/
|
|
77
75
|
static getEstimateFromSimulation(simulationResult, extras) {
|
|
78
76
|
if (!extras.fcpResult) throw new Error('missing fcpResult');
|
|
79
|
-
if (
|
|
77
|
+
if (extras.observedSpeedIndex === undefined) throw new Error('missing observedSpeedIndex');
|
|
80
78
|
|
|
81
79
|
const fcpTimeInMs = extras.fcpResult.pessimisticEstimate.timeInMs;
|
|
82
80
|
const estimate = extras.optimistic
|
|
83
|
-
? extras.
|
|
81
|
+
? extras.observedSpeedIndex
|
|
84
82
|
: SpeedIndex.computeLayoutBasedSpeedIndex(simulationResult.nodeTimings, fcpTimeInMs);
|
|
85
83
|
return {
|
|
86
84
|
timeInMs: estimate,
|
|
@@ -90,8 +88,8 @@ class SpeedIndex extends Metric {
|
|
|
90
88
|
|
|
91
89
|
/**
|
|
92
90
|
* @param {Lantern.Simulation.MetricComputationDataInput} data
|
|
93
|
-
* @param {Omit<import('../
|
|
94
|
-
* @return {Promise<
|
|
91
|
+
* @param {Omit<import('../Metric.js').Extras, 'optimistic'>=} extras
|
|
92
|
+
* @return {Promise<Lantern.Metrics.Result>}
|
|
95
93
|
*/
|
|
96
94
|
static async compute(data, extras) {
|
|
97
95
|
const fcpResult = extras?.fcpResult;
|
|
@@ -115,7 +113,7 @@ class SpeedIndex extends Metric {
|
|
|
115
113
|
* different methods. Read more in the evaluation doc.
|
|
116
114
|
*
|
|
117
115
|
* @see https://docs.google.com/document/d/1qJWXwxoyVLVadezIp_Tgdk867G3tDNkkVRvUJSH3K1E/edit#
|
|
118
|
-
* @param {
|
|
116
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
119
117
|
* @param {number} fcpTimeInMs
|
|
120
118
|
* @return {number}
|
|
121
119
|
*/
|
|
@@ -123,7 +121,7 @@ class SpeedIndex extends Metric {
|
|
|
123
121
|
/** @type {Array<{time: number, weight: number}>} */
|
|
124
122
|
const layoutWeights = [];
|
|
125
123
|
for (const [node, timing] of nodeTimings.entries()) {
|
|
126
|
-
if (node.type !== BaseNode.TYPES.CPU) continue;
|
|
124
|
+
if (node.type !== Lantern.BaseNode.TYPES.CPU) continue;
|
|
127
125
|
|
|
128
126
|
if (node.childEvents.some(x => x.name === 'Layout')) {
|
|
129
127
|
const timingWeight = Math.max(Math.log2(timing.endTime - timing.startTime), 0);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
8
|
+
import {readJson} from '../../../test/test-utils.js';
|
|
9
|
+
import {getComputationDataFromFixture} from './MetricTestUtils.js';
|
|
10
|
+
|
|
11
|
+
const {SpeedIndex, FirstContentfulPaint} = Lantern.Metrics;
|
|
12
|
+
|
|
13
|
+
const trace = readJson('../../../test/fixtures/artifacts/progressive-app/trace.json', import.meta);
|
|
14
|
+
|
|
15
|
+
const defaultThrottling = Lantern.Simulation.Constants.throttling.mobileSlow4G;
|
|
16
|
+
|
|
17
|
+
describe('Metrics: Lantern Speed Index', () => {
|
|
18
|
+
it('should compute predicted value', async () => {
|
|
19
|
+
const data = await getComputationDataFromFixture({trace});
|
|
20
|
+
// TODO: observedSpeedIndex is from the Speedline library, and is used for optimistic
|
|
21
|
+
// mode. At the moment callers must pass the result into Lantern.
|
|
22
|
+
const observedSpeedIndex = 379.04474997520487;
|
|
23
|
+
const result = await SpeedIndex.compute(data, {
|
|
24
|
+
fcpResult: await FirstContentfulPaint.compute(data),
|
|
25
|
+
observedSpeedIndex,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect({
|
|
29
|
+
timing: Math.round(result.timing),
|
|
30
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
31
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs)}).
|
|
32
|
+
toMatchInlineSnapshot(`
|
|
33
|
+
Object {
|
|
34
|
+
"optimistic": 379,
|
|
35
|
+
"pessimistic": 1122,
|
|
36
|
+
"timing": 1107,
|
|
37
|
+
}
|
|
38
|
+
`);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should compute predicted value for different settings', async () => {
|
|
42
|
+
const settings = {throttlingMethod: 'simulate', throttling: {...defaultThrottling, rttMs: 300}};
|
|
43
|
+
const data = await getComputationDataFromFixture({trace, settings});
|
|
44
|
+
const observedSpeedIndex = 379.04474997520487;
|
|
45
|
+
const result = await SpeedIndex.compute(data, {
|
|
46
|
+
fcpResult: await FirstContentfulPaint.compute(data),
|
|
47
|
+
observedSpeedIndex,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect({
|
|
51
|
+
timing: Math.round(result.timing),
|
|
52
|
+
optimistic: Math.round(result.optimisticEstimate.timeInMs),
|
|
53
|
+
pessimistic: Math.round(result.pessimisticEstimate.timeInMs)}).
|
|
54
|
+
toMatchInlineSnapshot(`
|
|
55
|
+
Object {
|
|
56
|
+
"optimistic": 379,
|
|
57
|
+
"pessimistic": 2022,
|
|
58
|
+
"timing": 2007,
|
|
59
|
+
}
|
|
60
|
+
`);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should not scale coefficients at default', async () => {
|
|
64
|
+
const result = SpeedIndex.getScaledCoefficients(defaultThrottling.rttMs);
|
|
65
|
+
expect(result).toEqual(SpeedIndex.COEFFICIENTS);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should scale coefficients back', async () => {
|
|
69
|
+
const result = SpeedIndex.getScaledCoefficients(5);
|
|
70
|
+
expect(result).toEqual({intercept: 0, pessimistic: 0.5, optimistic: 0.5});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should scale coefficients forward', async () => {
|
|
74
|
+
const result = SpeedIndex.getScaledCoefficients(300);
|
|
75
|
+
expect(result).toMatchInlineSnapshot(`
|
|
76
|
+
Object {
|
|
77
|
+
"intercept": 0,
|
|
78
|
+
"optimistic": 2.525,
|
|
79
|
+
"pessimistic": 0.275,
|
|
80
|
+
}
|
|
81
|
+
`);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type Node = import('../BaseNode.js').Node;
|
|
2
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
3
|
+
export class TotalBlockingTime 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} minDurationMs
|
|
17
|
+
*/
|
|
18
|
+
static getTopLevelEvents(nodeTimings: Lantern.Simulation.Result['nodeTimings'], minDurationMs: number): {
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
duration: number;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
import * as Lantern from '../lantern.js';
|
|
25
|
+
//# sourceMappingURL=TotalBlockingTime.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 {BaseNode} from '../base-node.js';
|
|
10
|
-
import {BLOCKING_TIME_THRESHOLD, calculateSumOfBlockingTime} from '../../../computed/metrics/tbt-utils.js';
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
11
8
|
|
|
12
|
-
/** @typedef {import('../
|
|
9
|
+
/** @typedef {import('../BaseNode.js').Node} Node */
|
|
13
10
|
|
|
14
|
-
class TotalBlockingTime extends Metric {
|
|
11
|
+
class TotalBlockingTime extends Lantern.Metric {
|
|
15
12
|
/**
|
|
16
|
-
* @return {
|
|
13
|
+
* @return {Lantern.Simulation.MetricCoefficients}
|
|
17
14
|
*/
|
|
18
15
|
static get COEFFICIENTS() {
|
|
19
16
|
return {
|
|
@@ -40,9 +37,9 @@ class TotalBlockingTime extends Metric {
|
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
/**
|
|
43
|
-
* @param {
|
|
44
|
-
* @param {import('../
|
|
45
|
-
* @return {
|
|
40
|
+
* @param {Lantern.Simulation.Result} simulation
|
|
41
|
+
* @param {import('../Metric.js').Extras} extras
|
|
42
|
+
* @return {Lantern.Simulation.Result}
|
|
46
43
|
*/
|
|
47
44
|
static getEstimateFromSimulation(simulation, extras) {
|
|
48
45
|
if (!extras.fcpResult) throw new Error('missing fcpResult');
|
|
@@ -64,7 +61,7 @@ class TotalBlockingTime extends Metric {
|
|
|
64
61
|
? extras.interactiveResult.optimisticEstimate.timeInMs
|
|
65
62
|
: extras.interactiveResult.pessimisticEstimate.timeInMs;
|
|
66
63
|
|
|
67
|
-
const minDurationMs = BLOCKING_TIME_THRESHOLD;
|
|
64
|
+
const minDurationMs = Lantern.TBTUtils.BLOCKING_TIME_THRESHOLD;
|
|
68
65
|
|
|
69
66
|
const events = TotalBlockingTime.getTopLevelEvents(
|
|
70
67
|
simulation.nodeTimings,
|
|
@@ -72,7 +69,7 @@ class TotalBlockingTime extends Metric {
|
|
|
72
69
|
);
|
|
73
70
|
|
|
74
71
|
return {
|
|
75
|
-
timeInMs: calculateSumOfBlockingTime(
|
|
72
|
+
timeInMs: Lantern.TBTUtils.calculateSumOfBlockingTime(
|
|
76
73
|
events,
|
|
77
74
|
fcpTimeInMs,
|
|
78
75
|
interactiveTimeMs
|
|
@@ -83,8 +80,8 @@ class TotalBlockingTime extends Metric {
|
|
|
83
80
|
|
|
84
81
|
/**
|
|
85
82
|
* @param {Lantern.Simulation.MetricComputationDataInput} data
|
|
86
|
-
* @param {Omit<import('../
|
|
87
|
-
* @return {Promise<
|
|
83
|
+
* @param {Omit<import('../Metric.js').Extras, 'optimistic'>=} extras
|
|
84
|
+
* @return {Promise<Lantern.Metrics.Result>}
|
|
88
85
|
*/
|
|
89
86
|
static async compute(data, extras) {
|
|
90
87
|
const fcpResult = extras?.fcpResult;
|
|
@@ -101,7 +98,7 @@ class TotalBlockingTime extends Metric {
|
|
|
101
98
|
}
|
|
102
99
|
|
|
103
100
|
/**
|
|
104
|
-
* @param {
|
|
101
|
+
* @param {Lantern.Simulation.Result['nodeTimings']} nodeTimings
|
|
105
102
|
* @param {number} minDurationMs
|
|
106
103
|
*/
|
|
107
104
|
static getTopLevelEvents(nodeTimings, minDurationMs) {
|
|
@@ -110,7 +107,7 @@ class TotalBlockingTime extends Metric {
|
|
|
110
107
|
const events = [];
|
|
111
108
|
|
|
112
109
|
for (const [node, timing] of nodeTimings.entries()) {
|
|
113
|
-
if (node.type !== BaseNode.TYPES.CPU) continue;
|
|
110
|
+
if (node.type !== Lantern.BaseNode.TYPES.CPU) continue;
|
|
114
111
|
// Filtering out events below minimum duration.
|
|
115
112
|
if (timing.duration < minDurationMs) continue;
|
|
116
113
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Metrics: Lantern FCP should compute predicted value 1`] = `
|
|
4
|
+
Object {
|
|
5
|
+
"optimistic": 1107,
|
|
6
|
+
"optimisticNodeTimings": 4,
|
|
7
|
+
"pessimistic": 1107,
|
|
8
|
+
"pessimisticNodeTimings": 4,
|
|
9
|
+
"timing": 1107,
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Metrics: Lantern TTI should compute predicted value 1`] = `
|
|
4
|
+
Object {
|
|
5
|
+
"optimistic": 1107,
|
|
6
|
+
"pessimistic": 1134,
|
|
7
|
+
"timing": 1122,
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
exports[`Metrics: Lantern TTI should compute predicted value on iframes with substantial layout 1`] = `
|
|
12
|
+
Object {
|
|
13
|
+
"optimistic": 2372,
|
|
14
|
+
"pessimistic": 2386,
|
|
15
|
+
"timing": 2379,
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { FirstContentfulPaint } from "./FirstContentfulPaint.js";
|
|
2
|
+
export { Interactive } from "./Interactive.js";
|
|
3
|
+
export { LargestContentfulPaint } from "./LargestContentfulPaint.js";
|
|
4
|
+
export { MaxPotentialFID } from "./MaxPotentialFID.js";
|
|
5
|
+
export { SpeedIndex } from "./SpeedIndex.js";
|
|
6
|
+
export { TotalBlockingTime } from "./TotalBlockingTime.js";
|
|
7
|
+
export type Result<T = any> = Lantern.MetricResult<T>;
|
|
8
|
+
import * as Lantern from '../types/lantern.js';
|
|
9
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as Lantern from '../types/lantern.js';
|
|
8
|
+
|
|
9
|
+
export {FirstContentfulPaint} from './FirstContentfulPaint.js';
|
|
10
|
+
export {Interactive} from './Interactive.js';
|
|
11
|
+
export {LargestContentfulPaint} from './LargestContentfulPaint.js';
|
|
12
|
+
export {MaxPotentialFID} from './MaxPotentialFID.js';
|
|
13
|
+
export {SpeedIndex} from './SpeedIndex.js';
|
|
14
|
+
export {TotalBlockingTime} from './TotalBlockingTime.js';
|
|
15
|
+
|
|
16
|
+
/** @template [T=any] @typedef {Lantern.MetricResult<T>} Result */
|
|
@@ -4,12 +4,12 @@ export class ConnectionPool {
|
|
|
4
4
|
* @param {Required<Lantern.Simulation.Options>} options
|
|
5
5
|
*/
|
|
6
6
|
constructor(records: Lantern.NetworkRequest[], options: Required<Lantern.Simulation.Options>);
|
|
7
|
-
_options: Required<
|
|
7
|
+
_options: Required<import("../types/lantern.js").Simulation.Options>;
|
|
8
8
|
_records: Lantern.NetworkRequest<any>[];
|
|
9
9
|
/** @type {Map<string, TcpConnection[]>} */
|
|
10
10
|
_connectionsByOrigin: Map<string, TcpConnection[]>;
|
|
11
11
|
/** @type {Map<Lantern.NetworkRequest, TcpConnection>} */
|
|
12
|
-
|
|
12
|
+
_connectionsByRequest: Map<Lantern.NetworkRequest, TcpConnection>;
|
|
13
13
|
_connectionsInUse: Set<any>;
|
|
14
14
|
_connectionReusedByRequestId: Map<string, boolean>;
|
|
15
15
|
/**
|
|
@@ -20,29 +20,29 @@ export class ConnectionPool {
|
|
|
20
20
|
/**
|
|
21
21
|
* @param {Array<TcpConnection>} connections
|
|
22
22
|
*/
|
|
23
|
-
_findAvailableConnectionWithLargestCongestionWindow(connections: Array<TcpConnection>): TcpConnection | null;
|
|
23
|
+
_findAvailableConnectionWithLargestCongestionWindow(connections: Array<TcpConnection>): Lantern.Simulation.TcpConnection | null;
|
|
24
24
|
/**
|
|
25
|
-
* This method finds an available connection to the origin specified by the network
|
|
25
|
+
* This method finds an available connection to the origin specified by the network request or null
|
|
26
26
|
* if no connection was available. If returned, connection will not be available for other network
|
|
27
27
|
* records until release is called.
|
|
28
28
|
*
|
|
29
|
-
* @param {Lantern.NetworkRequest}
|
|
29
|
+
* @param {Lantern.NetworkRequest} request
|
|
30
30
|
* @return {?TcpConnection}
|
|
31
31
|
*/
|
|
32
|
-
acquire(
|
|
32
|
+
acquire(request: Lantern.NetworkRequest): TcpConnection | null;
|
|
33
33
|
/**
|
|
34
|
-
* Return the connection currently being used to fetch a
|
|
35
|
-
* currently being used for this
|
|
34
|
+
* Return the connection currently being used to fetch a request. If no connection
|
|
35
|
+
* currently being used for this request, an error will be thrown.
|
|
36
36
|
*
|
|
37
|
-
* @param {Lantern.NetworkRequest}
|
|
37
|
+
* @param {Lantern.NetworkRequest} request
|
|
38
38
|
* @return {TcpConnection}
|
|
39
39
|
*/
|
|
40
|
-
|
|
40
|
+
acquireActiveConnectionFromRequest(request: Lantern.NetworkRequest): TcpConnection;
|
|
41
41
|
/**
|
|
42
|
-
* @param {Lantern.NetworkRequest}
|
|
42
|
+
* @param {Lantern.NetworkRequest} request
|
|
43
43
|
*/
|
|
44
|
-
release(
|
|
44
|
+
release(request: Lantern.NetworkRequest): void;
|
|
45
45
|
}
|
|
46
|
-
import * as Lantern from '../
|
|
47
|
-
import { TcpConnection } from './
|
|
48
|
-
//# sourceMappingURL=
|
|
46
|
+
import * as Lantern from '../lantern.js';
|
|
47
|
+
import { TcpConnection } from './TcpConnection.js';
|
|
48
|
+
//# sourceMappingURL=ConnectionPool.d.ts.map
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Lantern from '../
|
|
8
|
-
import {NetworkAnalyzer} from './
|
|
9
|
-
import {TcpConnection} from './
|
|
7
|
+
import * as Lantern from '../lantern.js';
|
|
8
|
+
import {NetworkAnalyzer} from './NetworkAnalyzer.js';
|
|
9
|
+
import {TcpConnection} from './TcpConnection.js';
|
|
10
10
|
|
|
11
11
|
const DEFAULT_SERVER_RESPONSE_TIME = 30;
|
|
12
12
|
const TLS_SCHEMES = ['https', 'wss'];
|
|
@@ -27,7 +27,7 @@ export class ConnectionPool {
|
|
|
27
27
|
/** @type {Map<string, TcpConnection[]>} */
|
|
28
28
|
this._connectionsByOrigin = new Map();
|
|
29
29
|
/** @type {Map<Lantern.NetworkRequest, TcpConnection>} */
|
|
30
|
-
this.
|
|
30
|
+
this._connectionsByRequest = new Map();
|
|
31
31
|
this._connectionsInUse = new Set();
|
|
32
32
|
this._connectionReusedByRequestId = NetworkAnalyzer.estimateIfConnectionWasReused(records, {
|
|
33
33
|
forceCoarseEstimates: true,
|
|
@@ -49,16 +49,16 @@ export class ConnectionPool {
|
|
|
49
49
|
const serverResponseTimeByOrigin = this._options.serverResponseTimeByOrigin;
|
|
50
50
|
|
|
51
51
|
const recordsByOrigin = NetworkAnalyzer.groupByOrigin(this._records);
|
|
52
|
-
for (const [origin,
|
|
52
|
+
for (const [origin, requests] of recordsByOrigin.entries()) {
|
|
53
53
|
const connections = [];
|
|
54
54
|
const additionalRtt = additionalRttByOrigin.get(origin) || 0;
|
|
55
55
|
const responseTime = serverResponseTimeByOrigin.get(origin) || DEFAULT_SERVER_RESPONSE_TIME;
|
|
56
56
|
|
|
57
|
-
for (const
|
|
58
|
-
if (connectionReused.get(
|
|
57
|
+
for (const request of requests) {
|
|
58
|
+
if (connectionReused.get(request.requestId)) continue;
|
|
59
59
|
|
|
60
|
-
const isTLS = TLS_SCHEMES.includes(
|
|
61
|
-
const isH2 =
|
|
60
|
+
const isTLS = TLS_SCHEMES.includes(request.parsedURL.scheme);
|
|
61
|
+
const isH2 = request.protocol === 'h2';
|
|
62
62
|
const connection = new TcpConnection(
|
|
63
63
|
this._options.rtt + additionalRtt,
|
|
64
64
|
this._options.throughput,
|
|
@@ -106,47 +106,47 @@ export class ConnectionPool {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* This method finds an available connection to the origin specified by the network
|
|
109
|
+
* This method finds an available connection to the origin specified by the network request or null
|
|
110
110
|
* if no connection was available. If returned, connection will not be available for other network
|
|
111
111
|
* records until release is called.
|
|
112
112
|
*
|
|
113
|
-
* @param {Lantern.NetworkRequest}
|
|
113
|
+
* @param {Lantern.NetworkRequest} request
|
|
114
114
|
* @return {?TcpConnection}
|
|
115
115
|
*/
|
|
116
|
-
acquire(
|
|
117
|
-
if (this.
|
|
116
|
+
acquire(request) {
|
|
117
|
+
if (this._connectionsByRequest.has(request)) throw new Error('Record already has a connection');
|
|
118
118
|
|
|
119
|
-
const origin =
|
|
119
|
+
const origin = request.parsedURL.securityOrigin;
|
|
120
120
|
const connections = this._connectionsByOrigin.get(origin) || [];
|
|
121
121
|
const connectionToUse = this._findAvailableConnectionWithLargestCongestionWindow(connections);
|
|
122
122
|
|
|
123
123
|
if (!connectionToUse) return null;
|
|
124
124
|
|
|
125
125
|
this._connectionsInUse.add(connectionToUse);
|
|
126
|
-
this.
|
|
126
|
+
this._connectionsByRequest.set(request, connectionToUse);
|
|
127
127
|
return connectionToUse;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
* Return the connection currently being used to fetch a
|
|
132
|
-
* currently being used for this
|
|
131
|
+
* Return the connection currently being used to fetch a request. If no connection
|
|
132
|
+
* currently being used for this request, an error will be thrown.
|
|
133
133
|
*
|
|
134
|
-
* @param {Lantern.NetworkRequest}
|
|
134
|
+
* @param {Lantern.NetworkRequest} request
|
|
135
135
|
* @return {TcpConnection}
|
|
136
136
|
*/
|
|
137
|
-
|
|
138
|
-
const activeConnection = this.
|
|
139
|
-
if (!activeConnection) throw new Error('Could not find an active connection for
|
|
137
|
+
acquireActiveConnectionFromRequest(request) {
|
|
138
|
+
const activeConnection = this._connectionsByRequest.get(request);
|
|
139
|
+
if (!activeConnection) throw new Error('Could not find an active connection for request');
|
|
140
140
|
|
|
141
141
|
return activeConnection;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
* @param {Lantern.NetworkRequest}
|
|
145
|
+
* @param {Lantern.NetworkRequest} request
|
|
146
146
|
*/
|
|
147
|
-
release(
|
|
148
|
-
const connection = this.
|
|
149
|
-
this.
|
|
147
|
+
release(request) {
|
|
148
|
+
const connection = this._connectionsByRequest.get(request);
|
|
149
|
+
this._connectionsByRequest.delete(request);
|
|
150
150
|
this._connectionsInUse.delete(connection);
|
|
151
151
|
}
|
|
152
152
|
}
|