lighthouse 11.7.0-dev.20240418 → 11.7.0-dev.20240419

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.
@@ -3,7 +3,7 @@
3
3
  exports[`getAssertionReport works (multiple failing) 1`] = `
4
4
  "X difference at cumulative-layout-shift audit.details.items.length
5
5
  expected: []
6
- found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.13570762803819444,\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444},\\"newEngineResultDiffered\\":false}]
6
+ found: [{\\"cumulativeLayoutShiftMainFrame\\":0.09957584751767748,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.09957584751767748,\\"cumulativeLayoutShiftMainFrame\\":0.09957584751767748},\\"newEngineResultDiffered\\":false}]
7
7
 
8
8
 
9
9
  X difference at cumulative-layout-shift audit.details.blah
@@ -15,11 +15,11 @@ exports[`getAssertionReport works (multiple failing) 1`] = `
15
15
  \\"id\\": \\"cumulative-layout-shift\\",
16
16
  \\"title\\": \\"Cumulative Layout Shift\\",
17
17
  \\"description\\": \\"Cumulative Layout Shift measures the movement of visible elements within the viewport. [Learn more about the Cumulative Layout Shift metric](https://web.dev/articles/cls).\\",
18
- \\"score\\": 0.8,
18
+ \\"score\\": 0.9,
19
19
  \\"scoreDisplayMode\\": \\"numeric\\",
20
- \\"numericValue\\": 0.13570762803819444,
20
+ \\"numericValue\\": 0.09957584751767748,
21
21
  \\"numericUnit\\": \\"unitless\\",
22
- \\"displayValue\\": \\"0.136\\",
22
+ \\"displayValue\\": \\"0.1\\",
23
23
  \\"scoringOptions\\": {
24
24
  \\"p10\\": 0.1,
25
25
  \\"median\\": 0.25
@@ -28,10 +28,10 @@ exports[`getAssertionReport works (multiple failing) 1`] = `
28
28
  \\"type\\": \\"debugdata\\",
29
29
  \\"items\\": [
30
30
  {
31
- \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444,
31
+ \\"cumulativeLayoutShiftMainFrame\\": 0.09957584751767748,
32
32
  \\"newEngineResult\\": {
33
- \\"cumulativeLayoutShift\\": 0.13570762803819444,
34
- \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
33
+ \\"cumulativeLayoutShift\\": 0.09957584751767748,
34
+ \\"cumulativeLayoutShiftMainFrame\\": 0.09957584751767748
35
35
  },
36
36
  \\"newEngineResultDiffered\\": false
37
37
  }
@@ -43,18 +43,18 @@ exports[`getAssertionReport works (multiple failing) 1`] = `
43
43
  exports[`getAssertionReport works (trivial failing) 1`] = `
44
44
  "X difference at cumulative-layout-shift audit.details.items.length
45
45
  expected: []
46
- found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.13570762803819444,\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444},\\"newEngineResultDiffered\\":false}]
46
+ found: [{\\"cumulativeLayoutShiftMainFrame\\":0.09957584751767748,\\"newEngineResult\\":{\\"cumulativeLayoutShift\\":0.09957584751767748,\\"cumulativeLayoutShiftMainFrame\\":0.09957584751767748},\\"newEngineResultDiffered\\":false}]
47
47
 
48
48
  found result:
49
49
  {
50
50
  \\"id\\": \\"cumulative-layout-shift\\",
51
51
  \\"title\\": \\"Cumulative Layout Shift\\",
52
52
  \\"description\\": \\"Cumulative Layout Shift measures the movement of visible elements within the viewport. [Learn more about the Cumulative Layout Shift metric](https://web.dev/articles/cls).\\",
53
- \\"score\\": 0.8,
53
+ \\"score\\": 0.9,
54
54
  \\"scoreDisplayMode\\": \\"numeric\\",
55
- \\"numericValue\\": 0.13570762803819444,
55
+ \\"numericValue\\": 0.09957584751767748,
56
56
  \\"numericUnit\\": \\"unitless\\",
57
- \\"displayValue\\": \\"0.136\\",
57
+ \\"displayValue\\": \\"0.1\\",
58
58
  \\"scoringOptions\\": {
59
59
  \\"p10\\": 0.1,
60
60
  \\"median\\": 0.25
@@ -63,10 +63,10 @@ exports[`getAssertionReport works (trivial failing) 1`] = `
63
63
  \\"type\\": \\"debugdata\\",
64
64
  \\"items\\": [
65
65
  {
66
- \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444,
66
+ \\"cumulativeLayoutShiftMainFrame\\": 0.09957584751767748,
67
67
  \\"newEngineResult\\": {
68
- \\"cumulativeLayoutShift\\": 0.13570762803819444,
69
- \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444
68
+ \\"cumulativeLayoutShift\\": 0.09957584751767748,
69
+ \\"cumulativeLayoutShiftMainFrame\\": 0.09957584751767748
70
70
  },
71
71
  \\"newEngineResultDiffered\\": false
72
72
  }
@@ -78,11 +78,9 @@ class UsesHTTP2Audit extends Audit {
78
78
  options = Object.assign({label: ''}, options);
79
79
  const beforeLabel = `${this.meta.id}-${options.label}-before`;
80
80
  const afterLabel = `${this.meta.id}-${options.label}-after`;
81
- const flexibleOrdering = true;
82
81
 
83
82
  const urlsToChange = new Set(results.map(result => result.url));
84
- const simulationBefore =
85
- simulator.simulate(graph, {label: beforeLabel, flexibleOrdering});
83
+ const simulationBefore = simulator.simulate(graph, {label: beforeLabel});
86
84
 
87
85
  // Update all the protocols to reflect implementing our recommendations
88
86
  /** @type {Map<string, string>} */
@@ -95,7 +93,7 @@ class UsesHTTP2Audit extends Audit {
95
93
  node.request.protocol = 'h2';
96
94
  });
97
95
 
98
- const simulationAfter = simulator.simulate(graph, {label: afterLabel, flexibleOrdering});
96
+ const simulationAfter = simulator.simulate(graph, {label: afterLabel});
99
97
 
100
98
  // Restore the original protocol after we've done our simulation
101
99
  graph.traverse(node => {
@@ -194,8 +194,8 @@ class PrioritizeLcpImage extends Audit {
194
194
  modifiedLCPNode.removeAllDependencies();
195
195
  modifiedLCPNode.addDependency(mainDocumentNode);
196
196
 
197
- const simulationBeforeChanges = simulator.simulate(graph, {flexibleOrdering: true});
198
- const simulationAfterChanges = simulator.simulate(modifiedGraph, {flexibleOrdering: true});
197
+ const simulationBeforeChanges = simulator.simulate(graph);
198
+ const simulationAfterChanges = simulator.simulate(modifiedGraph);
199
199
  const lcpTimingsBefore = simulationBeforeChanges.nodeTimings.get(lcpNode);
200
200
  if (!lcpTimingsBefore) throw new Error('Impossible - node timings should never be undefined');
201
201
  const lcpTimingsAfter = simulationAfterChanges.nodeTimings.get(modifiedLCPNode);
@@ -143,9 +143,9 @@ class UsesRelPreloadAudit extends Audit {
143
143
  return {wastedMs: 0, results: []};
144
144
  }
145
145
 
146
- // Preload changes the ordering of requests, simulate the original graph with flexible ordering
146
+ // Preload changes the ordering of requests, simulate the original graph
147
147
  // to have a reasonable baseline for comparison.
148
- const simulationBeforeChanges = simulator.simulate(graph, {flexibleOrdering: true});
148
+ const simulationBeforeChanges = simulator.simulate(graph);
149
149
  const modifiedGraph = graph.cloneWithRelationships();
150
150
 
151
151
  /** @type {Array<LH.Gatherer.Simulation.GraphNetworkNode>} */
@@ -174,8 +174,8 @@ class UsesRelPreloadAudit extends Audit {
174
174
  node.addDependency(mainDocumentNode);
175
175
  }
176
176
 
177
- // Once we've modified the dependencies, simulate the new graph with flexible ordering.
178
- const simulationAfterChanges = simulator.simulate(modifiedGraph, {flexibleOrdering: true});
177
+ // Once we've modified the dependencies, simulate the new graph.
178
+ const simulationAfterChanges = simulator.simulate(modifiedGraph);
179
179
  const originalNodesByRecord = Array.from(simulationBeforeChanges.nodeTimings.keys())
180
180
  // @ts-expect-error we don't care if all nodes without a record collect on `undefined`
181
181
  .reduce((map, node) => map.set(node.record, node), new Map());
@@ -101,19 +101,15 @@ class Metric {
101
101
  const optimisticGraph = this.getOptimisticGraph(graph, processedNavigation);
102
102
  const pessimisticGraph = this.getPessimisticGraph(graph, processedNavigation);
103
103
 
104
- /** @type {{flexibleOrdering?: boolean, label?: string}} */
105
104
  let simulateOptions = {label: `optimistic${metricName}`};
106
105
  const optimisticSimulation = simulator.simulate(optimisticGraph, simulateOptions);
107
106
 
108
- simulateOptions = {label: `optimisticFlex${metricName}`, flexibleOrdering: true};
109
- const optimisticFlexSimulation = simulator.simulate(optimisticGraph, simulateOptions);
110
-
111
107
  simulateOptions = {label: `pessimistic${metricName}`};
112
108
  const pessimisticSimulation = simulator.simulate(pessimisticGraph, simulateOptions);
113
109
 
114
110
  const optimisticEstimate = this.getEstimateFromSimulation(
115
- optimisticSimulation.timeInMs < optimisticFlexSimulation.timeInMs ?
116
- optimisticSimulation : optimisticFlexSimulation, {...extras, optimistic: true}
111
+ optimisticSimulation,
112
+ {...extras, optimistic: true}
117
113
  );
118
114
 
119
115
  const pessimisticEstimate = this.getEstimateFromSimulation(
@@ -21,8 +21,8 @@ class Interactive extends Metric {
21
21
  static get COEFFICIENTS() {
22
22
  return {
23
23
  intercept: 0,
24
- optimistic: 0.5,
25
- pessimistic: 0.5,
24
+ optimistic: 0.45,
25
+ pessimistic: 0.55,
26
26
  };
27
27
  }
28
28
 
@@ -18,12 +18,11 @@ class SpeedIndex extends Metric {
18
18
  */
19
19
  static get COEFFICIENTS() {
20
20
  return {
21
- // Negative intercept is OK because estimate is Math.max(FCP, Speed Index) and
22
- // the optimistic estimate is based on the real observed speed index rather than a real
23
- // lantern graph.
24
- intercept: -250,
21
+ // Note that the optimistic estimate is based on the real observed speed index rather than a
22
+ // real lantern graph (and the final estimate will be Math.max(FCP, Speed Index)).
23
+ intercept: 0,
25
24
  optimistic: 1.4,
26
- pessimistic: 0.65,
25
+ pessimistic: 0.4,
27
26
  };
28
27
  }
29
28
 
@@ -19,27 +19,17 @@ export class ConnectionPool {
19
19
  _initializeConnections(): void;
20
20
  /**
21
21
  * @param {Array<TcpConnection>} connections
22
- * @param {{ignoreConnectionReused?: boolean, observedConnectionWasReused: boolean}} options
23
22
  */
24
- _findAvailableConnectionWithLargestCongestionWindow(connections: Array<TcpConnection>, options: {
25
- ignoreConnectionReused?: boolean | undefined;
26
- observedConnectionWasReused: boolean;
27
- }): TcpConnection | null;
23
+ _findAvailableConnectionWithLargestCongestionWindow(connections: Array<TcpConnection>): TcpConnection | null;
28
24
  /**
29
25
  * This method finds an available connection to the origin specified by the network record or null
30
26
  * if no connection was available. If returned, connection will not be available for other network
31
27
  * records until release is called.
32
28
  *
33
- * If ignoreConnectionReused is true, acquire will consider all connections not in use as available.
34
- * Otherwise, only connections that have matching "warmth" are considered available.
35
- *
36
29
  * @param {Lantern.NetworkRequest} record
37
- * @param {{ignoreConnectionReused?: boolean}} options
38
30
  * @return {?TcpConnection}
39
31
  */
40
- acquire(record: Lantern.NetworkRequest, options?: {
41
- ignoreConnectionReused?: boolean;
42
- }): TcpConnection | null;
32
+ acquire(record: Lantern.NetworkRequest): TcpConnection | null;
43
33
  /**
44
34
  * Return the connection currently being used to fetch a record. If no connection
45
35
  * currently being used for this record, an error will be thrown.
@@ -85,24 +85,13 @@ export class ConnectionPool {
85
85
 
86
86
  /**
87
87
  * @param {Array<TcpConnection>} connections
88
- * @param {{ignoreConnectionReused?: boolean, observedConnectionWasReused: boolean}} options
89
88
  */
90
- _findAvailableConnectionWithLargestCongestionWindow(connections, options) {
91
- const {ignoreConnectionReused, observedConnectionWasReused} = options;
92
-
89
+ _findAvailableConnectionWithLargestCongestionWindow(connections) {
93
90
  /** @type {TcpConnection|null} */
94
91
  let maxConnection = null;
95
92
  for (let i = 0; i < connections.length; i++) {
96
93
  const connection = connections[i];
97
94
 
98
- // Normally, we want to make sure the connection warmth matches the state of the record
99
- // we're acquiring for. Do this check first since it's the common case and cheaper than our
100
- // "in use" check below.
101
- // Use the _warmed property instead of the getter because this is a surprisingly hot code path.
102
- if (!ignoreConnectionReused && connection._warmed !== observedConnectionWasReused) {
103
- continue;
104
- }
105
-
106
95
  // Connections that are in use are never available.
107
96
  if (this._connectionsInUse.has(connection)) {
108
97
  continue;
@@ -121,23 +110,15 @@ export class ConnectionPool {
121
110
  * if no connection was available. If returned, connection will not be available for other network
122
111
  * records until release is called.
123
112
  *
124
- * If ignoreConnectionReused is true, acquire will consider all connections not in use as available.
125
- * Otherwise, only connections that have matching "warmth" are considered available.
126
- *
127
113
  * @param {Lantern.NetworkRequest} record
128
- * @param {{ignoreConnectionReused?: boolean}} options
129
114
  * @return {?TcpConnection}
130
115
  */
131
- acquire(record, options = {}) {
116
+ acquire(record) {
132
117
  if (this._connectionsByRecord.has(record)) throw new Error('Record already has a connection');
133
118
 
134
119
  const origin = record.parsedURL.securityOrigin;
135
- const observedConnectionWasReused = !!this._connectionReusedByRequestId.get(record.requestId);
136
120
  const connections = this._connectionsByOrigin.get(origin) || [];
137
- const connectionToUse = this._findAvailableConnectionWithLargestCongestionWindow(connections, {
138
- ignoreConnectionReused: options.ignoreConnectionReused,
139
- observedConnectionWasReused,
140
- });
121
+ const connectionToUse = this._findAvailableConnectionWithLargestCongestionWindow(connections);
141
122
 
142
123
  if (!connectionToUse) return null;
143
124
 
@@ -29,7 +29,6 @@ export class Simulator<T = any> {
29
29
  _layoutTaskMultiplier: number;
30
30
  /** @type {Array<Node>} */
31
31
  _cachedNodeListByStartPosition: Array<Node>;
32
- _flexibleOrdering: boolean;
33
32
  _nodeTimings: SimulatorTimingMap;
34
33
  /** @type {Map<string, number>} */
35
34
  _numberInProgressByType: Map<string, number>;
@@ -131,17 +130,16 @@ export class Simulator<T = any> {
131
130
  * Estimates the time taken to process all of the graph's nodes, returns the overall time along with
132
131
  * each node annotated by start/end times.
133
132
  *
134
- * If flexibleOrdering is set, simulator/connection pool are allowed to deviate from what was
133
+ * Simulator/connection pool are allowed to deviate from what was
135
134
  * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not
136
135
  * wait around for a warm connection to be available if the original record was fetched on a warm
137
136
  * connection).
138
137
  *
139
138
  * @param {Node} graph
140
- * @param {{flexibleOrdering?: boolean, label?: string}=} options
139
+ * @param {{label?: string}=} options
141
140
  * @return {Lantern.Simulation.Result<T>}
142
141
  */
143
142
  simulate(graph: Node, options?: {
144
- flexibleOrdering?: boolean;
145
143
  label?: string;
146
144
  } | undefined): Lantern.Simulation.Result<T>;
147
145
  /**
@@ -80,7 +80,6 @@ class Simulator {
80
80
  this._cachedNodeListByStartPosition = [];
81
81
 
82
82
  // Properties reset on every `.simulate` call but duplicated here for type checking
83
- this._flexibleOrdering = false;
84
83
  this._nodeTimings = new SimulatorTimingMap();
85
84
  /** @type {Map<string, number>} */
86
85
  this._numberInProgressByType = new Map();
@@ -197,9 +196,7 @@ class Simulator {
197
196
  * @return {?TcpConnection}
198
197
  */
199
198
  _acquireConnection(record) {
200
- return this._connectionPool.acquire(record, {
201
- ignoreConnectionReused: this._flexibleOrdering,
202
- });
199
+ return this._connectionPool.acquire(record);
203
200
  }
204
201
 
205
202
  /**
@@ -425,13 +422,13 @@ class Simulator {
425
422
  * Estimates the time taken to process all of the graph's nodes, returns the overall time along with
426
423
  * each node annotated by start/end times.
427
424
  *
428
- * If flexibleOrdering is set, simulator/connection pool are allowed to deviate from what was
425
+ * Simulator/connection pool are allowed to deviate from what was
429
426
  * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not
430
427
  * wait around for a warm connection to be available if the original record was fetched on a warm
431
428
  * connection).
432
429
  *
433
430
  * @param {Node} graph
434
- * @param {{flexibleOrdering?: boolean, label?: string}=} options
431
+ * @param {{label?: string}=} options
435
432
  * @return {Lantern.Simulation.Result<T>}
436
433
  */
437
434
  simulate(graph, options) {
@@ -441,11 +438,9 @@ class Simulator {
441
438
 
442
439
  options = Object.assign({
443
440
  label: undefined,
444
- flexibleOrdering: false,
445
441
  }, options);
446
442
 
447
443
  // initialize the necessary data containers
448
- this._flexibleOrdering = !!options.flexibleOrdering;
449
444
  this._dns = new DNSCache({rtt: this._rtt});
450
445
  this._initializeConnectionPool(graph);
451
446
  this._initializeAuxiliaryData();
@@ -470,11 +465,9 @@ class Simulator {
470
465
  }
471
466
 
472
467
  if (!nodesInProgress.size) {
473
- // interplay between fromDiskCache and connectionReused can be incorrect
474
- // proceed with flexibleOrdering if we can, otherwise give up
475
- if (this._flexibleOrdering) throw new Error('Failed to start a node');
476
- this._flexibleOrdering = true;
477
- continue;
468
+ // Interplay between fromDiskCache and connectionReused can be incorrect,
469
+ // have to give up.
470
+ throw new Error('Failed to start a node');
478
471
  }
479
472
 
480
473
  // set the available throughput for all connections based on # inflight
@@ -255,7 +255,6 @@ export default {
255
255
  'unlabeled',
256
256
  // These node timings should be nearly identical to the ones produced for Interactive
257
257
  'optimisticSpeedIndex',
258
- 'optimisticFlexSpeedIndex',
259
258
  'pessimisticSpeedIndex',
260
259
  ],
261
260
  convertNodeTimingsToTrace,