lighthouse 10.1.1-dev.20230430 → 10.1.1-dev.20230502

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.
@@ -63,6 +63,7 @@ class NetworkRequests extends Audit {
63
63
 
64
64
  return {
65
65
  url: UrlUtils.elideDataURI(record.url),
66
+ sessionTargetType: record.sessionTargetType,
66
67
  protocol: record.protocol,
67
68
  rendererStartTime: normalizeTime(record.rendererStartTime),
68
69
  networkRequestTime: normalizeTime(record.networkRequestTime),
@@ -34,7 +34,7 @@ class PredictivePerf extends Audit {
34
34
  'a cellular connection on a mobile device.',
35
35
  scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
36
36
  supportedModes: ['navigation'],
37
- requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext'],
37
+ requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
38
38
  };
39
39
  }
40
40
 
@@ -45,9 +45,10 @@ export class TargetManager extends TargetManager_base {
45
45
  /**
46
46
  * Returns a listener for all protocol events from session, and augments the
47
47
  * event with the sessionId.
48
+ * @param {LH.Protocol.TargetType} targetType
48
49
  * @param {string} sessionId
49
50
  */
50
- _getProtocolEventListener(sessionId: string): <EventName extends keyof import("puppeteer-core").ProtocolMapping.Events>(method: EventName, params: import("../../../types/protocol.js").default.RawEventMessageRecord[EventName]["params"]) => void;
51
+ _getProtocolEventListener(targetType: LH.Protocol.TargetType, sessionId: string): <EventName extends keyof import("puppeteer-core").ProtocolMapping.Events>(method: EventName, params: import("../../../types/protocol.js").default.RawEventMessageRecord[EventName]["params"]) => void;
51
52
  /**
52
53
  * @return {Promise<void>}
53
54
  */
@@ -119,7 +119,7 @@ class TargetManager extends ProtocolEventEmitter {
119
119
  const targetName = target.targetInfo.url || target.targetInfo.targetId;
120
120
  log.verbose('target-manager', `target ${targetName} attached`);
121
121
 
122
- const trueProtocolListener = this._getProtocolEventListener(newSession.id());
122
+ const trueProtocolListener = this._getProtocolEventListener(targetType, newSession.id());
123
123
  /** @type {(event: unknown) => void} */
124
124
  // @ts-expect-error - pptr currently typed only for single arg emits.
125
125
  const protocolListener = trueProtocolListener;
@@ -156,9 +156,10 @@ class TargetManager extends ProtocolEventEmitter {
156
156
  /**
157
157
  * Returns a listener for all protocol events from session, and augments the
158
158
  * event with the sessionId.
159
+ * @param {LH.Protocol.TargetType} targetType
159
160
  * @param {string} sessionId
160
161
  */
161
- _getProtocolEventListener(sessionId) {
162
+ _getProtocolEventListener(targetType, sessionId) {
162
163
  /**
163
164
  * @template {keyof LH.Protocol.RawEventMessageRecord} EventName
164
165
  * @param {EventName} method
@@ -166,7 +167,8 @@ class TargetManager extends ProtocolEventEmitter {
166
167
  */
167
168
  const onProtocolEvent = (method, params) => {
168
169
  // Cast because tsc 4.7 still can't quite track the dependent parameters.
169
- const payload = /** @type {LH.Protocol.RawEventMessage} */ ({method, params, sessionId});
170
+ const payload = /** @type {LH.Protocol.RawEventMessage} */ (
171
+ {method, params, targetType, sessionId});
170
172
  this.emit('protocolevent', payload);
171
173
  };
172
174
 
@@ -54,8 +54,8 @@ class OptimizedImages extends FRGatherer {
54
54
  /** @type {Set<string>} */
55
55
  const seenUrls = new Set();
56
56
  return networkRecords.reduce((prev, record) => {
57
- // Skip records that we've seen before, never finished, or came from child targets (OOPIFS).
58
- if (seenUrls.has(record.url) || !record.finished || record.sessionId) {
57
+ // Skip records that we've seen before, never finished, or came from OOPIFs.
58
+ if (seenUrls.has(record.url) || !record.finished || record.isOutOfProcessIframe) {
59
59
  return prev;
60
60
  }
61
61
 
@@ -55,8 +55,7 @@ class ResponseCompression extends FRGatherer {
55
55
  const unoptimizedResponses = [];
56
56
 
57
57
  networkRecords.forEach(record => {
58
- // Ignore records from child targets (OOPIFS).
59
- if (record.sessionId) return;
58
+ if (record.isOutOfProcessIframe) return;
60
59
 
61
60
  const mimeType = record.mimeType;
62
61
  const resourceType = record.resourceType || NetworkRequest.TYPES.Other;
@@ -65,8 +65,7 @@ class ScriptElements extends FRGatherer {
65
65
 
66
66
  const scriptRecords = networkRecords
67
67
  .filter(record => record.resourceType === NetworkRequest.TYPES.Script)
68
- // Ignore records from OOPIFs
69
- .filter(record => !record.sessionId);
68
+ .filter(record => !record.isOutOfProcessIframe);
70
69
 
71
70
  for (let i = 0; i < scriptRecords.length; i++) {
72
71
  const record = scriptRecords[i];
@@ -7,8 +7,6 @@ declare class Scripts extends FRGatherer {
7
7
  _scriptParsedEvents: LH.Crdp.Debugger.ScriptParsedEvent[];
8
8
  /** @type {Array<string | undefined>} */
9
9
  _scriptContents: Array<string | undefined>;
10
- /** @type {string|null|undefined} */
11
- _mainSessionId: string | null | undefined;
12
10
  /**
13
11
  * @param {LH.Crdp.Debugger.ScriptParsedEvent} params
14
12
  */
@@ -59,9 +59,6 @@ class Scripts extends FRGatherer {
59
59
  /** @type {Array<string | undefined>} */
60
60
  _scriptContents = [];
61
61
 
62
- /** @type {string|null|undefined} */
63
- _mainSessionId = null;
64
-
65
62
  constructor() {
66
63
  super();
67
64
  this.onScriptParsed = this.onScriptParsed.bind(this);
@@ -17,6 +17,8 @@ export class Connection {
17
17
  _lastCommandId: number;
18
18
  /** @type {Map<number, CommandCallback>} */
19
19
  _callbacks: Map<number, CommandCallback>;
20
+ /** @type {Map<string, LH.Protocol.TargetType>} */
21
+ _sessionIdToTargetType: Map<string, LH.Protocol.TargetType>;
20
22
  _eventEmitter: CrdpEventMessageEmitter | null;
21
23
  /**
22
24
  * @return {Promise<void>}
@@ -25,6 +25,8 @@ class Connection {
25
25
  this._lastCommandId = 0;
26
26
  /** @type {Map<number, CommandCallback>} */
27
27
  this._callbacks = new Map();
28
+ /** @type {Map<string, LH.Protocol.TargetType>} */
29
+ this._sessionIdToTargetType = new Map();
28
30
 
29
31
  this._eventEmitter = /** @type {?CrdpEventMessageEmitter} */ (new EventEmitter());
30
32
  }
@@ -129,6 +131,18 @@ class Connection {
129
131
  if (!('id' in object)) {
130
132
  log.formatProtocol('<= event',
131
133
  {method: object.method, params: object.params}, 'verbose');
134
+ if (object.method === 'Target.attachedToTarget') {
135
+ const type = object.params.targetInfo.type;
136
+ if (type === 'page' || type === 'iframe') {
137
+ this._sessionIdToTargetType.set(object.params.sessionId, type);
138
+ }
139
+ }
140
+ if (object.sessionId) {
141
+ const type = this._sessionIdToTargetType.get(object.sessionId);
142
+ if (type) {
143
+ object.targetType = type;
144
+ }
145
+ }
132
146
  this.emitProtocolEvent(object);
133
147
  return;
134
148
  }
@@ -175,6 +189,7 @@ class Connection {
175
189
  this._eventEmitter.removeAllListeners();
176
190
  this._eventEmitter = null;
177
191
  }
192
+ this._sessionIdToTargetType.clear();
178
193
  }
179
194
  }
180
195
 
@@ -22,8 +22,6 @@ export class NetworkRecorder extends NetworkRecorder_base {
22
22
  _records: NetworkRequest[];
23
23
  /** @type {Map<string, NetworkRequest>} */
24
24
  _recordsById: Map<string, NetworkRequest>;
25
- /** @type {string|null|undefined} */
26
- _mainSessionId: string | null | undefined;
27
25
  /**
28
26
  * Returns the array of raw network request data without finalizing the initiator and
29
27
  * redirect chain.
@@ -45,52 +43,59 @@ export class NetworkRecorder extends NetworkRecorder_base {
45
43
  */
46
44
  private onRequestFinished;
47
45
  /**
48
- * @param {{params: LH.Crdp.Network.RequestWillBeSentEvent, sessionId?: string}} event
46
+ * @param {{params: LH.Crdp.Network.RequestWillBeSentEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
49
47
  */
50
48
  onRequestWillBeSent(event: {
51
49
  params: LH.Crdp.Network.RequestWillBeSentEvent;
50
+ targetType: LH.Protocol.TargetType;
52
51
  sessionId?: string;
53
52
  }): void;
54
53
  /**
55
- * @param {{params: LH.Crdp.Network.RequestServedFromCacheEvent, sessionId?: string}} event
54
+ * @param {{params: LH.Crdp.Network.RequestServedFromCacheEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
56
55
  */
57
56
  onRequestServedFromCache(event: {
58
57
  params: LH.Crdp.Network.RequestServedFromCacheEvent;
58
+ targetType: LH.Protocol.TargetType;
59
59
  sessionId?: string;
60
60
  }): void;
61
61
  /**
62
- * @param {{params: LH.Crdp.Network.ResponseReceivedEvent, sessionId?: string}} event
62
+ * @param {{params: LH.Crdp.Network.ResponseReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
63
63
  */
64
64
  onResponseReceived(event: {
65
65
  params: LH.Crdp.Network.ResponseReceivedEvent;
66
+ targetType: LH.Protocol.TargetType;
66
67
  sessionId?: string;
67
68
  }): void;
68
69
  /**
69
- * @param {{params: LH.Crdp.Network.DataReceivedEvent, sessionId?: string}} event
70
+ * @param {{params: LH.Crdp.Network.DataReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
70
71
  */
71
72
  onDataReceived(event: {
72
73
  params: LH.Crdp.Network.DataReceivedEvent;
74
+ targetType: LH.Protocol.TargetType;
73
75
  sessionId?: string;
74
76
  }): void;
75
77
  /**
76
- * @param {{params: LH.Crdp.Network.LoadingFinishedEvent, sessionId?: string}} event
78
+ * @param {{params: LH.Crdp.Network.LoadingFinishedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
77
79
  */
78
80
  onLoadingFinished(event: {
79
81
  params: LH.Crdp.Network.LoadingFinishedEvent;
82
+ targetType: LH.Protocol.TargetType;
80
83
  sessionId?: string;
81
84
  }): void;
82
85
  /**
83
- * @param {{params: LH.Crdp.Network.LoadingFailedEvent, sessionId?: string}} event
86
+ * @param {{params: LH.Crdp.Network.LoadingFailedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
84
87
  */
85
88
  onLoadingFailed(event: {
86
89
  params: LH.Crdp.Network.LoadingFailedEvent;
90
+ targetType: LH.Protocol.TargetType;
87
91
  sessionId?: string;
88
92
  }): void;
89
93
  /**
90
- * @param {{params: LH.Crdp.Network.ResourceChangedPriorityEvent, sessionId?: string}} event
94
+ * @param {{params: LH.Crdp.Network.ResourceChangedPriorityEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
91
95
  */
92
96
  onResourceChangedPriority(event: {
93
97
  params: LH.Crdp.Network.ResourceChangedPriorityEvent;
98
+ targetType: LH.Protocol.TargetType;
94
99
  sessionId?: string;
95
100
  }): void;
96
101
  /**
@@ -105,10 +110,11 @@ export class NetworkRecorder extends NetworkRecorder_base {
105
110
  * message is referring.
106
111
  *
107
112
  * @param {string} requestId
113
+ * @param {LH.Protocol.TargetType} targetType
108
114
  * @param {string|undefined} sessionId
109
115
  * @return {NetworkRequest|undefined}
110
116
  */
111
- _findRealRequestAndSetSession(requestId: string, sessionId: string | undefined): NetworkRequest | undefined;
117
+ _findRealRequestAndSetSession(requestId: string, targetType: LH.Protocol.TargetType, sessionId: string | undefined): NetworkRequest | undefined;
112
118
  }
113
119
  import { NetworkRequest } from './network-request.js';
114
120
  export {};
@@ -31,8 +31,6 @@ class NetworkRecorder extends RequestEventEmitter {
31
31
  this._records = [];
32
32
  /** @type {Map<string, NetworkRequest>} */
33
33
  this._recordsById = new Map();
34
- /** @type {string|null|undefined} */
35
- this._mainSessionId = null;
36
34
  }
37
35
 
38
36
  /**
@@ -71,11 +69,12 @@ class NetworkRecorder extends RequestEventEmitter {
71
69
  // DevTools SDK network layer.
72
70
 
73
71
  /**
74
- * @param {{params: LH.Crdp.Network.RequestWillBeSentEvent, sessionId?: string}} event
72
+ * @param {{params: LH.Crdp.Network.RequestWillBeSentEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
75
73
  */
76
74
  onRequestWillBeSent(event) {
77
75
  const data = event.params;
78
- const originalRequest = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
76
+ const originalRequest = this._findRealRequestAndSetSession(
77
+ data.requestId, event.targetType, event.sessionId);
79
78
  // This is a simple new request, create the NetworkRequest object and finish.
80
79
  if (!originalRequest) {
81
80
  const request = new NetworkRequest();
@@ -114,44 +113,48 @@ class NetworkRecorder extends RequestEventEmitter {
114
113
  }
115
114
 
116
115
  /**
117
- * @param {{params: LH.Crdp.Network.RequestServedFromCacheEvent, sessionId?: string}} event
116
+ * @param {{params: LH.Crdp.Network.RequestServedFromCacheEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
118
117
  */
119
118
  onRequestServedFromCache(event) {
120
119
  const data = event.params;
121
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
120
+ const request = this._findRealRequestAndSetSession(
121
+ data.requestId, event.targetType, event.sessionId);
122
122
  if (!request) return;
123
123
  log.verbose('network', `${request.url} served from cache`);
124
124
  request.onRequestServedFromCache();
125
125
  }
126
126
 
127
127
  /**
128
- * @param {{params: LH.Crdp.Network.ResponseReceivedEvent, sessionId?: string}} event
128
+ * @param {{params: LH.Crdp.Network.ResponseReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
129
129
  */
130
130
  onResponseReceived(event) {
131
131
  const data = event.params;
132
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
132
+ const request = this._findRealRequestAndSetSession(
133
+ data.requestId, event.targetType, event.sessionId);
133
134
  if (!request) return;
134
135
  log.verbose('network', `${request.url} response received`);
135
136
  request.onResponseReceived(data);
136
137
  }
137
138
 
138
139
  /**
139
- * @param {{params: LH.Crdp.Network.DataReceivedEvent, sessionId?: string}} event
140
+ * @param {{params: LH.Crdp.Network.DataReceivedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
140
141
  */
141
142
  onDataReceived(event) {
142
143
  const data = event.params;
143
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
144
+ const request = this._findRealRequestAndSetSession(
145
+ data.requestId, event.targetType, event.sessionId);
144
146
  if (!request) return;
145
147
  log.verbose('network', `${request.url} data received`);
146
148
  request.onDataReceived(data);
147
149
  }
148
150
 
149
151
  /**
150
- * @param {{params: LH.Crdp.Network.LoadingFinishedEvent, sessionId?: string}} event
152
+ * @param {{params: LH.Crdp.Network.LoadingFinishedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
151
153
  */
152
154
  onLoadingFinished(event) {
153
155
  const data = event.params;
154
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
156
+ const request = this._findRealRequestAndSetSession(
157
+ data.requestId, event.targetType, event.sessionId);
155
158
  if (!request) return;
156
159
  log.verbose('network', `${request.url} loading finished`);
157
160
  request.onLoadingFinished(data);
@@ -159,11 +162,12 @@ class NetworkRecorder extends RequestEventEmitter {
159
162
  }
160
163
 
161
164
  /**
162
- * @param {{params: LH.Crdp.Network.LoadingFailedEvent, sessionId?: string}} event
165
+ * @param {{params: LH.Crdp.Network.LoadingFailedEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
163
166
  */
164
167
  onLoadingFailed(event) {
165
168
  const data = event.params;
166
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
169
+ const request = this._findRealRequestAndSetSession(
170
+ data.requestId, event.targetType, event.sessionId);
167
171
  if (!request) return;
168
172
  log.verbose('network', `${request.url} loading failed`);
169
173
  request.onLoadingFailed(data);
@@ -171,11 +175,12 @@ class NetworkRecorder extends RequestEventEmitter {
171
175
  }
172
176
 
173
177
  /**
174
- * @param {{params: LH.Crdp.Network.ResourceChangedPriorityEvent, sessionId?: string}} event
178
+ * @param {{params: LH.Crdp.Network.ResourceChangedPriorityEvent, targetType: LH.Protocol.TargetType, sessionId?: string}} event
175
179
  */
176
180
  onResourceChangedPriority(event) {
177
181
  const data = event.params;
178
- const request = this._findRealRequestAndSetSession(data.requestId, event.sessionId);
182
+ const request = this._findRealRequestAndSetSession(
183
+ data.requestId, event.targetType, event.sessionId);
179
184
  if (!request) return;
180
185
  request.onResourceChangedPriority(data);
181
186
  }
@@ -204,24 +209,11 @@ class NetworkRecorder extends RequestEventEmitter {
204
209
  * message is referring.
205
210
  *
206
211
  * @param {string} requestId
212
+ * @param {LH.Protocol.TargetType} targetType
207
213
  * @param {string|undefined} sessionId
208
214
  * @return {NetworkRequest|undefined}
209
215
  */
210
- _findRealRequestAndSetSession(requestId, sessionId) {
211
- // The very first sessionId processed is always the main sessionId. In all but DevTools,
212
- // this sessionId is undefined. However, in DevTools the main Lighthouse protocol connection
213
- // does send events with sessionId set to a string, because of how DevTools routes the protocol
214
- // to Lighthouse.
215
- // Many places in Lighthouse use `record.sessionId === undefined` to mean that the session is not
216
- // an OOPIF. To maintain this property, we intercept sessionId here and set it to undefined if
217
- // it matches the first value seen.
218
- if (this._mainSessionId === null) {
219
- this._mainSessionId = sessionId;
220
- }
221
- if (this._mainSessionId === sessionId) {
222
- sessionId = undefined;
223
- }
224
-
216
+ _findRealRequestAndSetSession(requestId, targetType, sessionId) {
225
217
  let request = this._recordsById.get(requestId);
226
218
  if (!request || !request.isValid) return undefined;
227
219
 
@@ -230,6 +222,7 @@ class NetworkRecorder extends RequestEventEmitter {
230
222
  }
231
223
 
232
224
  request.setSession(sessionId);
225
+ request.sessionTargetType = targetType;
233
226
 
234
227
  return request;
235
228
  }
@@ -133,12 +133,10 @@ export class NetworkRequest {
133
133
  fetchedViaServiceWorker: boolean;
134
134
  /** @type {string|undefined} */
135
135
  frameId: string | undefined;
136
- /**
137
- * @type {string|undefined}
138
- * Only set for child targets (OOPIFs). This is the sessionId of the protocol connection on
139
- * which this request was discovered. `undefined` means it came from the root.
140
- */
136
+ /** @type {string|undefined} */
141
137
  sessionId: string | undefined;
138
+ /** @type {LH.Protocol.TargetType|undefined} */
139
+ sessionTargetType: LH.Protocol.TargetType | undefined;
142
140
  isLinkPreload: boolean;
143
141
  /**
144
142
  * @return {boolean}
@@ -178,9 +176,10 @@ export class NetworkRequest {
178
176
  */
179
177
  onRedirectResponse(data: LH.Crdp.Network.RequestWillBeSentEvent): void;
180
178
  /**
181
- * @param {string=} sessionId
179
+ * @param {string|undefined} sessionId
182
180
  */
183
- setSession(sessionId?: string | undefined): void;
181
+ setSession(sessionId: string | undefined): void;
182
+ get isOutOfProcessIframe(): boolean;
184
183
  /**
185
184
  * @param {LH.Crdp.Network.Response} response
186
185
  * @param {number} timestamp in seconds
@@ -178,12 +178,10 @@ class NetworkRequest {
178
178
  this.fetchedViaServiceWorker = false;
179
179
  /** @type {string|undefined} */
180
180
  this.frameId = '';
181
- /**
182
- * @type {string|undefined}
183
- * Only set for child targets (OOPIFs). This is the sessionId of the protocol connection on
184
- * which this request was discovered. `undefined` means it came from the root.
185
- */
181
+ /** @type {string|undefined} */
186
182
  this.sessionId = undefined;
183
+ /** @type {LH.Protocol.TargetType|undefined} */
184
+ this.sessionTargetType = undefined;
187
185
  this.isLinkPreload = false;
188
186
  }
189
187
 
@@ -320,12 +318,16 @@ class NetworkRequest {
320
318
  }
321
319
 
322
320
  /**
323
- * @param {string=} sessionId
321
+ * @param {string|undefined} sessionId
324
322
  */
325
323
  setSession(sessionId) {
326
324
  this.sessionId = sessionId;
327
325
  }
328
326
 
327
+ get isOutOfProcessIframe() {
328
+ return this.sessionTargetType === 'iframe';
329
+ }
330
+
329
331
  /**
330
332
  * @param {LH.Crdp.Network.Response} response
331
333
  * @param {number} timestamp in seconds
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "10.1.1-dev.20230430",
4
+ "version": "10.1.1-dev.20230502",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -10,6 +10,8 @@ type CrdpEvents = CrdpMappings.Events;
10
10
  type CrdpCommands = CrdpMappings.Commands;
11
11
 
12
12
  declare module Protocol {
13
+ type TargetType = 'page' | 'iframe' | 'worker';
14
+
13
15
  /**
14
16
  * An intermediate type, used to create a record of all possible Crdp raw event
15
17
  * messages, keyed on method. e.g. {
@@ -22,6 +24,7 @@ declare module Protocol {
22
24
  method: K,
23
25
  // Drop [] for `undefined` (so a JS value is valid).
24
26
  params: CrdpEvents[K] extends [] ? undefined: CrdpEvents[K][number]
27
+ targetType: TargetType;
25
28
  // If sessionId is not set, it means the event was from the root target.
26
29
  sessionId?: string;
27
30
  };