chrome-devtools-frontend 1.0.972865 → 1.0.973253

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.
@@ -672,7 +672,7 @@ grd_files_debug_sources = [
672
672
  "front_end/entrypoints/inspector_main/RenderingOptions.js",
673
673
  "front_end/entrypoints/inspector_main/nodeIcon.css.js",
674
674
  "front_end/entrypoints/inspector_main/renderingOptions.css.js",
675
- "front_end/entrypoints/lighthouse_worker/LighthouseService.js",
675
+ "front_end/entrypoints/lighthouse_worker/LighthouseWorkerService.js",
676
676
  "front_end/entrypoints/main/ExecutionContextSelector.js",
677
677
  "front_end/entrypoints/main/MainImpl.js",
678
678
  "front_end/entrypoints/main/SimpleApp.js",
@@ -11,13 +11,17 @@ function disableLoggingForTest(): void {
11
11
  }
12
12
 
13
13
  /**
14
+ * LegacyPort is provided to Lighthouse as the CDP connection in legacyNavigation mode.
15
+ * Its complement is https://github.com/GoogleChrome/lighthouse/blob/v9.3.1/lighthouse-core/gather/connections/raw.js
16
+ * It speaks pure CDP via notifyFrontendViaWorkerMessage
17
+ *
14
18
  * Any message that comes back from Lighthouse has to go via a so-called "port".
15
19
  * This class holds the relevant callbacks that Lighthouse provides and that
16
20
  * can be called in the onmessage callback of the worker, so that the frontend
17
21
  * can communicate to Lighthouse. Lighthouse itself communicates to the frontend
18
22
  * via status updates defined below.
19
23
  */
20
- class LighthousePort {
24
+ class LegacyPort {
21
25
  onMessage?: (message: string) => void;
22
26
  onClose?: () => void;
23
27
  on(eventName: string, callback: (arg?: string) => void): void {
@@ -35,6 +39,10 @@ class LighthousePort {
35
39
  }
36
40
  }
37
41
 
42
+ /**
43
+ * ConnectionProxy is a SDK interface, but the implementation has no knowledge it's a parallelConnection.
44
+ * The CDP traffic is smuggled back and forth by the system described in LighthouseProtocolService
45
+ */
38
46
  class ConnectionProxy implements SDK.Connections.ParallelConnectionInterface {
39
47
  sessionId: string;
40
48
  onMessage: ((arg0: Object) => void)|null;
@@ -73,15 +81,15 @@ class ConnectionProxy implements SDK.Connections.ParallelConnectionInterface {
73
81
  }
74
82
  }
75
83
 
76
- const port = new LighthousePort();
77
- let rawConnection: ConnectionProxy|undefined;
84
+ const legacyPort = new LegacyPort();
85
+ let cdpConnection: ConnectionProxy|undefined;
78
86
  let endTimespan: (() => unknown)|undefined;
79
87
 
80
88
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
- async function start(method: string, params: any): Promise<unknown> {
89
+ async function invokeLH(action: string, args: any): Promise<unknown> {
82
90
  if (Root.Runtime.Runtime.queryParam('isUnderTest')) {
83
91
  disableLoggingForTest();
84
- params.flags.maxWaitForLoad = 2 * 1000;
92
+ args.flags.maxWaitForLoad = 2 * 1000;
85
93
  }
86
94
 
87
95
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
@@ -95,7 +103,7 @@ async function start(method: string, params: any): Promise<unknown> {
95
103
  try {
96
104
  // For timespan we only need to perform setup on startTimespan.
97
105
  // Config, flags, locale, etc. should be stored in the closure of endTimespan.
98
- if (method === 'endTimespan') {
106
+ if (action === 'endTimespan') {
99
107
  if (!endTimespan) {
100
108
  throw new Error('Cannot end a timespan before starting one');
101
109
  }
@@ -104,35 +112,36 @@ async function start(method: string, params: any): Promise<unknown> {
104
112
  return result;
105
113
  }
106
114
 
107
- const locale = await fetchLocaleData(params.locales);
108
- const flags = params.flags;
115
+ const locale = await fetchLocaleData(args.locales);
116
+ const flags = args.flags;
109
117
  flags.logLevel = flags.logLevel || 'info';
110
118
  flags.channel = 'devtools';
111
119
  flags.locale = locale;
112
120
 
113
121
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
114
- const config = self.createConfig(params.categoryIDs, flags.emulatedFormFactor);
115
- const url = params.url;
122
+ const config = self.createConfig(args.categoryIDs, flags.emulatedFormFactor);
123
+ const url = args.url;
116
124
 
117
125
  // Handle legacy Lighthouse runner path.
118
- if (method === 'navigation' && flags.legacyNavigation) {
126
+ if (action === 'navigation' && flags.legacyNavigation) {
119
127
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
120
- const connection = self.setUpWorkerConnection(port);
128
+ const connection = self.setUpWorkerConnection(legacyPort);
121
129
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
122
130
  return await self.runLighthouse(url, flags, config, connection);
123
131
  }
124
132
 
125
- const {mainTargetId, mainFrameId, mainSessionId} = params.target;
126
- rawConnection = new ConnectionProxy(mainSessionId);
127
- const {page} = puppeteerConnection =
128
- await Puppeteer.PuppeteerConnection.getPuppeteerConnection(rawConnection, mainFrameId, mainTargetId);
133
+ const {mainTargetId, mainFrameId, mainSessionId} = args.target;
134
+ cdpConnection = new ConnectionProxy(mainSessionId);
135
+ puppeteerConnection =
136
+ await Puppeteer.PuppeteerConnection.getPuppeteerConnection(cdpConnection, mainFrameId, mainTargetId);
137
+ const {page} = puppeteerConnection;
129
138
 
130
- if (method === 'snapshot') {
139
+ if (action === 'snapshot') {
131
140
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
132
141
  return await self.runLighthouseSnapshot({config, page});
133
142
  }
134
143
 
135
- if (method === 'startTimespan') {
144
+ if (action === 'startTimespan') {
136
145
  // @ts-expect-error https://github.com/GoogleChrome/lighthouse/issues/11628
137
146
  const timespan = await self.startLighthouseTimespan({config, page});
138
147
  endTimespan = timespan.endTimespan;
@@ -149,7 +158,7 @@ async function start(method: string, params: any): Promise<unknown> {
149
158
  });
150
159
  } finally {
151
160
  // endTimespan will need to use the same connection as startTimespan.
152
- if (method !== 'startTimespan') {
161
+ if (action !== 'startTimespan') {
153
162
  puppeteerConnection?.browser.disconnect();
154
163
  }
155
164
  }
@@ -192,34 +201,42 @@ async function fetchLocaleData(locales: string[]): Promise<string|void> {
192
201
  return;
193
202
  }
194
203
 
204
+ /**
205
+ * `notifyFrontendViaWorkerMessage` and `onFrontendMessage` work with the FE's ProtocolService.
206
+ *
207
+ * onFrontendMessage takes action-wrapped messages and either invoking lighthouse or delivering it CDP traffic.
208
+ * notifyFrontendViaWorkerMessage posts action-wrapped messages to the FE.
209
+ */
195
210
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
196
- function notifyFrontendViaWorkerMessage(method: string, params: any): void {
197
- self.postMessage(JSON.stringify({method, params}));
211
+ function notifyFrontendViaWorkerMessage(action: string, args: any): void {
212
+ self.postMessage(JSON.stringify({action, args}));
198
213
  }
199
214
 
200
- self.onmessage = async(event: MessageEvent): Promise<void> => {
215
+ async function onFrontendMessage(event: MessageEvent): Promise<void> {
201
216
  const messageFromFrontend = JSON.parse(event.data);
202
- switch (messageFromFrontend.method) {
217
+ switch (messageFromFrontend.action) {
203
218
  case 'startTimespan':
204
219
  case 'endTimespan':
205
220
  case 'snapshot':
206
221
  case 'navigation': {
207
- const result = await start(messageFromFrontend.method, messageFromFrontend.params);
222
+ const result = await invokeLH(messageFromFrontend.action, messageFromFrontend.args);
208
223
  self.postMessage(JSON.stringify({id: messageFromFrontend.id, result}));
209
224
  break;
210
225
  }
211
226
  case 'dispatchProtocolMessage': {
212
- rawConnection?.onMessage?.(
213
- JSON.parse(messageFromFrontend.params.message),
227
+ cdpConnection?.onMessage?.(
228
+ JSON.parse(messageFromFrontend.args.message),
214
229
  );
215
- port.onMessage?.(messageFromFrontend.params.message);
230
+ legacyPort.onMessage?.(messageFromFrontend.args.message);
216
231
  break;
217
232
  }
218
233
  default: {
219
234
  throw new Error(`Unknown event: ${event.data}`);
220
235
  }
221
236
  }
222
- };
237
+ }
238
+
239
+ self.onmessage = onFrontendMessage;
223
240
 
224
241
  // Make lighthouse and traceviewer happy.
225
242
  // @ts-ignore https://github.com/GoogleChrome/lighthouse/issues/11628
@@ -2,7 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import './LighthouseService.js';
5
+ import './LighthouseWorkerService.js';
6
6
  import '../../third_party/lighthouse/lighthouse-dt-bundle.js';
7
7
 
8
8
  self.postMessage('workerReady');
@@ -270,7 +270,7 @@ export class LayoutPane extends HTMLElement {
270
270
  </span>
271
271
  </label>
272
272
  <label @keyup=${onColorLabelKeyUp} @keydown=${onColorLabelKeyDown} tabindex="0" title=${i18nString(UIStrings.chooseElementOverlayColor)} class="color-picker-label" style="background: ${element.color};">
273
- <input @change=${onColorChange} @input=${onColorChange} class="color-picker" type="color" value=${element.color} />
273
+ <input @change=${onColorChange} @input=${onColorChange} tabindex="-1" class="color-picker" type="color" value=${element.color} />
274
274
  </label>
275
275
  <button tabindex="0" @click=${onElementClick} title=${i18nString(UIStrings.showElementInTheElementsPanel)} class="show-element"></button>
276
276
  </div>`;
@@ -8,6 +8,40 @@ import * as SDK from '../../core/sdk/sdk.js';
8
8
 
9
9
  import type * as ReportRenderer from './LighthouseReporterTypes.js';
10
10
 
11
+ /**
12
+ * @overview
13
+ ┌────────────┐
14
+ │CDP Backend │
15
+ └────────────┘
16
+ │ ▲
17
+ │ │ parallelConnection
18
+ ┌┐ ▼ │ ┌┐
19
+ ││ dispatchProtocolMessage sendProtocolMessage ││
20
+ ││ │ ▲ ││
21
+ ProtocolService ││ | │ ││
22
+ ││ sendWithResponse ▼ │ ││
23
+ ││ │ send onWorkerMessage ││
24
+ └┘ │ │ ▲ └┘
25
+ worker boundary - - - - - - - - ┼ - -│- - - - - - - - -│- - - - - - - - - - - -
26
+ ┌┐ ▼ ▼ │ ┌┐
27
+ ││ onFrontendMessage notifyFrontendViaWorkerMessage ││
28
+ ││ │ ▲ ││
29
+ ││ ▼ │ ││
30
+ LighthouseWorkerService ││ Either ConnectionProxy or LegacyPort ││
31
+ ││ │ ▲ ││
32
+ ││ ┌─────────────────────┼─┼───────────────────────┐ ││
33
+ ││ │ Lighthouse ┌────▼──────┐ │ ││
34
+ ││ │ │connection │ │ ││
35
+ ││ │ └───────────┘ │ ││
36
+ └┘ └───────────────────────────────────────────────┘ └┘
37
+
38
+ * All messages traversing the worker boundary are action-wrapped.
39
+ * All messages over the parallelConnection speak pure CDP.
40
+ * All messages within ConnectionProxy/LegacyPort speak pure CDP.
41
+ * The foundational CDP connection is `parallelConnection`.
42
+ * All connections within the worker are not actual ParallelConnection's.
43
+ */
44
+
11
45
  let lastId = 1;
12
46
 
13
47
  export interface LighthouseRun {
@@ -16,13 +50,16 @@ export interface LighthouseRun {
16
50
  flags: Record<string, Object|undefined>;
17
51
  }
18
52
 
53
+ /**
54
+ * ProtocolService manages a connection between the frontend (Lighthouse panel) and the Lighthouse worker.
55
+ */
19
56
  export class ProtocolService {
20
57
  private targetInfo?: {
21
58
  mainSessionId: string,
22
59
  mainTargetId: string,
23
60
  mainFrameId: string,
24
61
  };
25
- private rawConnection?: ProtocolClient.InspectorBackend.Connection;
62
+ private parallelConnection?: ProtocolClient.InspectorBackend.Connection;
26
63
  private lighthouseWorkerPromise?: Promise<Worker>;
27
64
  private lighthouseMessageUpdateCallback?: ((arg0: string) => void);
28
65
 
@@ -52,7 +89,7 @@ export class ProtocolService {
52
89
  this.dispatchProtocolMessage(message);
53
90
  });
54
91
 
55
- this.rawConnection = connection;
92
+ this.parallelConnection = connection;
56
93
  this.targetInfo = {
57
94
  mainTargetId: await childTargetManager.getParentTargetId(),
58
95
  mainFrameId: mainFrame.id,
@@ -103,20 +140,20 @@ export class ProtocolService {
103
140
 
104
141
  async detach(): Promise<void> {
105
142
  const oldLighthouseWorker = this.lighthouseWorkerPromise;
106
- const oldRawConnection = this.rawConnection;
143
+ const oldParallelConnection = this.parallelConnection;
107
144
 
108
145
  // When detaching, make sure that we remove the old promises, before we
109
146
  // perform any async cleanups. That way, if there is a message coming from
110
147
  // lighthouse while we are in the process of cleaning up, we shouldn't deliver
111
148
  // them to the backend.
112
149
  this.lighthouseWorkerPromise = undefined;
113
- this.rawConnection = undefined;
150
+ this.parallelConnection = undefined;
114
151
 
115
152
  if (oldLighthouseWorker) {
116
153
  (await oldLighthouseWorker).terminate();
117
154
  }
118
- if (oldRawConnection) {
119
- await oldRawConnection.disconnect();
155
+ if (oldParallelConnection) {
156
+ await oldParallelConnection.disconnect();
120
157
  }
121
158
  await SDK.TargetManager.TargetManager.instance().resumeAllTargets();
122
159
  }
@@ -140,7 +177,7 @@ export class ProtocolService {
140
177
  method?: string,
141
178
  };
142
179
  if (protocolMessage.sessionId || (protocolMessage.method && protocolMessage.method.startsWith('Target'))) {
143
- void this.sendWithoutResponse('dispatchProtocolMessage', {message: JSON.stringify(message)});
180
+ void this.send('dispatchProtocolMessage', {message: JSON.stringify(message)});
144
181
  }
145
182
  }
146
183
 
@@ -160,18 +197,7 @@ export class ProtocolService {
160
197
  return;
161
198
  }
162
199
 
163
- const lighthouseMessage = JSON.parse(event.data);
164
-
165
- if (lighthouseMessage.method === 'statusUpdate') {
166
- if (this.lighthouseMessageUpdateCallback && lighthouseMessage.params &&
167
- 'message' in lighthouseMessage.params) {
168
- this.lighthouseMessageUpdateCallback(lighthouseMessage.params.message as string);
169
- }
170
- } else if (lighthouseMessage.method === 'sendProtocolMessage') {
171
- if (lighthouseMessage.params && 'message' in lighthouseMessage.params) {
172
- this.sendProtocolMessage(lighthouseMessage.params.message as string);
173
- }
174
- }
200
+ this.onWorkerMessage(event);
175
201
  });
176
202
  });
177
203
  return this.lighthouseWorkerPromise;
@@ -187,19 +213,34 @@ export class ProtocolService {
187
213
  return worker;
188
214
  }
189
215
 
216
+ private onWorkerMessage(event: MessageEvent): void {
217
+ const lighthouseMessage = JSON.parse(event.data);
218
+
219
+ if (lighthouseMessage.action === 'statusUpdate') {
220
+ if (this.lighthouseMessageUpdateCallback && lighthouseMessage.args && 'message' in lighthouseMessage.args) {
221
+ this.lighthouseMessageUpdateCallback(lighthouseMessage.args.message as string);
222
+ }
223
+ } else if (lighthouseMessage.action === 'sendProtocolMessage') {
224
+ if (lighthouseMessage.args && 'message' in lighthouseMessage.args) {
225
+ this.sendProtocolMessage(lighthouseMessage.args.message as string);
226
+ }
227
+ }
228
+ }
229
+
190
230
  private sendProtocolMessage(message: string): void {
191
- if (this.rawConnection) {
192
- this.rawConnection.sendRawMessage(message);
231
+ if (this.parallelConnection) {
232
+ this.parallelConnection.sendRawMessage(message);
193
233
  }
194
234
  }
195
235
 
196
- private async sendWithoutResponse(method: string, params: {[x: string]: string|string[]|Object} = {}): Promise<void> {
236
+ private async send(action: string, args: {[x: string]: string|string[]|Object} = {}): Promise<void> {
197
237
  const worker = await this.ensureWorkerExists();
198
238
  const messageId = lastId++;
199
- worker.postMessage(JSON.stringify({id: messageId, method, params: {...params, id: messageId}}));
239
+ worker.postMessage(JSON.stringify({id: messageId, action, args: {...args, id: messageId}}));
200
240
  }
201
241
 
202
- private async sendWithResponse(method: string, params: {[x: string]: string|string[]|Object} = {}):
242
+ /** sendWithResponse currently only handles the original startLighthouse request and LHR-filled response. */
243
+ private async sendWithResponse(action: string, args: {[x: string]: string|string[]|Object} = {}):
203
244
  Promise<ReportRenderer.RunnerResult> {
204
245
  const worker = await this.ensureWorkerExists();
205
246
  const messageId = lastId++;
@@ -214,7 +255,7 @@ export class ProtocolService {
214
255
  };
215
256
  worker.addEventListener('message', workerListener);
216
257
  });
217
- worker.postMessage(JSON.stringify({id: messageId, method, params: {...params, id: messageId}}));
258
+ worker.postMessage(JSON.stringify({id: messageId, action, args: {...args, id: messageId}}));
218
259
 
219
260
  return messageResult;
220
261
  }
@@ -30,7 +30,7 @@ export {ensureSyntaxTree, indentOnInput, indentUnit,Language, LanguageSupport, s
30
30
  export {bracketMatching} from '@codemirror/matchbrackets';
31
31
  export {Panel, showPanel} from '@codemirror/panel';
32
32
  export {Range, RangeSet, RangeSetBuilder} from '@codemirror/rangeset';
33
- export {selectNextOccurrence} from '@codemirror/search';
33
+ export { highlightSelectionMatches,selectNextOccurrence} from '@codemirror/search';
34
34
  export {
35
35
  Annotation, AnnotationType, ChangeDesc, ChangeSet, ChangeSpec, Compartment,
36
36
  EditorSelection, EditorState, EditorStateConfig, Extension, Facet, MapMode