chrome-devtools-frontend 1.0.1514545 → 1.0.1515796

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.
Files changed (163) hide show
  1. package/AUTHORS +1 -0
  2. package/docs/committers_policy.md +1 -1
  3. package/docs/contributing/infrastructure.md +101 -5
  4. package/front_end/Images/gdp-logo-dark.png +0 -0
  5. package/front_end/Images/gdp-logo-light.png +0 -0
  6. package/front_end/core/common/Settings.ts +11 -32
  7. package/front_end/entrypoints/main/main-meta.ts +2 -2
  8. package/front_end/generated/InspectorBackendCommands.js +4 -4
  9. package/front_end/generated/SupportedCSSProperties.js +12 -0
  10. package/front_end/generated/protocol.ts +10 -1
  11. package/front_end/global_typings/global_defs.d.ts +15 -1
  12. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +22 -23
  13. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +6 -7
  14. package/front_end/models/ai_assistance/ai_assistance.ts +3 -0
  15. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +141 -2
  16. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +96 -10
  17. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +123 -55
  18. package/front_end/models/cpu_profile/ProfileTreeModel.ts +1 -1
  19. package/front_end/models/extensions/ExtensionPanel.ts +4 -0
  20. package/front_end/models/heap_snapshot_model/HeapSnapshotModel.ts +5 -1
  21. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -7
  22. package/front_end/models/text_utils/TextUtils.ts +26 -0
  23. package/front_end/models/trace/Processor.ts +1 -1
  24. package/front_end/models/trace/helpers/Trace.ts +1 -1
  25. package/front_end/models/trace/insights/DocumentLatency.ts +9 -7
  26. package/front_end/models/trace/types/Configuration.ts +12 -0
  27. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +6 -7
  28. package/front_end/panels/ai_assistance/components/ChatView.ts +1 -2
  29. package/front_end/panels/application/components/BackForwardCacheStrings.ts +8 -2
  30. package/front_end/panels/common/BadgeNotification.ts +10 -8
  31. package/front_end/panels/common/GdpSignUpDialog.ts +25 -16
  32. package/front_end/panels/common/gdpSignUpDialog.css +10 -14
  33. package/front_end/panels/console/ConsoleView.ts +4 -0
  34. package/front_end/panels/elements/ElementsPanel.ts +4 -0
  35. package/front_end/panels/elements/StylePropertiesSection.ts +4 -4
  36. package/front_end/panels/network/NetworkConfigView.ts +1 -1
  37. package/front_end/panels/network/NetworkLogView.ts +2 -2
  38. package/front_end/panels/network/components/HeaderSectionRow.ts +2 -3
  39. package/front_end/panels/profiler/HeapProfileView.ts +1 -3
  40. package/front_end/panels/profiler/HeapSnapshotView.ts +5 -1
  41. package/front_end/panels/profiler/ProfileDataGrid.ts +4 -0
  42. package/front_end/panels/profiler/ProfileFlameChartDataProvider.ts +7 -29
  43. package/front_end/panels/profiler/ProfileView.ts +4 -0
  44. package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -2
  45. package/front_end/panels/search/SearchView.ts +322 -248
  46. package/front_end/panels/settings/KeybindsSettingsTab.ts +1 -1
  47. package/front_end/panels/settings/SettingsScreen.ts +1 -1
  48. package/front_end/panels/settings/components/SyncSection.ts +59 -14
  49. package/front_end/panels/settings/components/syncSection.css +17 -4
  50. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -7
  51. package/front_end/panels/sources/SourcesView.ts +4 -0
  52. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +2 -2
  53. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +6 -3
  54. package/front_end/panels/timeline/CountersGraph.ts +5 -5
  55. package/front_end/panels/timeline/TimelineDetailsView.ts +2 -2
  56. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +4 -3
  57. package/front_end/panels/timeline/TimelineFlameChartView.ts +9 -4
  58. package/front_end/panels/timeline/TimelineHistoryManager.ts +2 -2
  59. package/front_end/panels/timeline/TimelinePanel.ts +4 -3
  60. package/front_end/panels/timeline/TimelineTreeView.ts +6 -2
  61. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -1
  62. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +2 -2
  63. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +6 -6
  64. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +2 -2
  65. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -3
  66. package/front_end/panels/timeline/utils/utils.ts +0 -8
  67. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  68. package/front_end/{panels/timeline/utils → services/tracing}/FreshRecording.ts +1 -1
  69. package/front_end/services/tracing/tracing.ts +2 -0
  70. package/front_end/third_party/chromium/README.chromium +1 -1
  71. package/front_end/third_party/puppeteer/README.chromium +2 -2
  72. package/front_end/third_party/puppeteer/package/README.md +6 -3
  73. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +11 -1
  75. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js +2 -2
  77. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  78. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +5 -1
  79. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  80. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +30 -8
  81. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +1 -3
  84. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  86. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +8 -2
  89. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +5 -1
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +8 -2
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +5 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  101. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +12 -2
  102. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +22 -8
  103. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +11 -1
  105. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js +2 -2
  107. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +5 -1
  109. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +30 -8
  111. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +1 -3
  114. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +8 -2
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +5 -1
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +8 -2
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +5 -0
  127. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/types.d.ts +12 -2
  129. package/front_end/third_party/puppeteer/package/package.json +4 -4
  130. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +1 -1
  131. package/front_end/third_party/puppeteer/package/src/api/Page.ts +13 -2
  132. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +50 -8
  133. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +0 -1
  134. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +8 -1
  135. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +21 -5
  136. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  137. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +12 -0
  138. package/front_end/ui/components/text_editor/config.ts +66 -16
  139. package/front_end/ui/legacy/Dialog.ts +38 -13
  140. package/front_end/ui/legacy/InspectorView.ts +7 -9
  141. package/front_end/ui/legacy/ProgressIndicator.ts +4 -5
  142. package/front_end/ui/legacy/SearchableView.ts +73 -55
  143. package/front_end/ui/legacy/SettingsUI.ts +5 -5
  144. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +1 -4
  145. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +5 -5
  146. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -2
  147. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +2 -2
  148. package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +2 -2
  149. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +1 -4
  150. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +3 -3
  151. package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +2 -2
  152. package/front_end/ui/legacy/components/source_frame/JSONView.ts +10 -10
  153. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -0
  154. package/front_end/ui/legacy/components/source_frame/XMLView.ts +4 -0
  155. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -4
  156. package/front_end/ui/legacy/searchableView.css +0 -4
  157. package/front_end/ui/visual_logging/Debugging.ts +24 -12
  158. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  159. package/package.json +3 -3
  160. package/front_end/Images/src/gdp-logo-standalone.svg +0 -9
  161. /package/front_end/{panels/timeline/utils → models/ai_assistance/performance}/AICallTree.ts +0 -0
  162. /package/front_end/{panels/timeline/utils → models/ai_assistance/performance}/AIContext.ts +0 -0
  163. /package/front_end/{panels/timeline/utils/InsightAIContext.ts → models/ai_assistance/performance/AIQueries.ts} +0 -0
@@ -202,70 +202,133 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
202
202
  };
203
203
  }
204
204
 
205
+ async #completeCodeCached(request: Host.AidaClient.CompletionRequest): Promise<{
206
+ response: Host.AidaClient.CompletionResponse | null,
207
+ fromCache: boolean,
208
+ }> {
209
+ const cachedResponse = this.#checkCachedRequestForResponse(request);
210
+ if (cachedResponse) {
211
+ return {response: cachedResponse, fromCache: true};
212
+ }
213
+
214
+ const response = await this.#aidaClient.completeCode(request);
215
+ if (!response) {
216
+ return {
217
+ response: null,
218
+ fromCache: false,
219
+ };
220
+ }
221
+
222
+ this.#updateCachedRequest(request, response);
223
+ return {
224
+ response,
225
+ fromCache: false,
226
+ };
227
+ }
228
+
229
+ #pickSampleFromResponse(response: Host.AidaClient.CompletionResponse): Host.AidaClient.GenerationSample|null {
230
+ if (!response.generatedSamples.length) {
231
+ return null;
232
+ }
233
+
234
+ // `currentHint` is the portion of a standard autocomplete suggestion that the user has not yet typed.
235
+ // For example, if the user types `document.queryS` and the autocomplete suggests `document.querySelector`,
236
+ // the `currentHint` is `elector`.
237
+ const currentHintInMenu = this.#editor.editor.plugin(TextEditor.Config.showCompletionHint)?.currentHint;
238
+ // TODO(ergunsh): We should not do this check here. Instead, the AI code suggestions should be provided
239
+ // as it is to the view plugin. The view plugin should choose which one to use based on the completion hint
240
+ // and selected completion.
241
+ if (!currentHintInMenu) {
242
+ return response.generatedSamples[0];
243
+ }
244
+
245
+ // TODO(ergunsh): This does not handle looking for `selectedCompletion`. The `currentHint` is `null`
246
+ // for the Sources panel case.
247
+ // Even though there is no match, we still return the first suggestion which will be displayed
248
+ // when the traditional autocomplete menu is closed.
249
+ return response.generatedSamples.find(sample => sample.generationString.startsWith(currentHintInMenu)) ??
250
+ response.generatedSamples[0];
251
+ }
252
+
253
+ async #generateSampleForRequest(request: Host.AidaClient.CompletionRequest, cursor: number): Promise<{
254
+ suggestionText: string,
255
+ sampleId: number,
256
+ fromCache: boolean,
257
+ citations: Host.AidaClient.Citation[],
258
+ rpcGlobalId?: Host.AidaClient.RpcGlobalId,
259
+ }|null> {
260
+ const {response, fromCache} = await this.#completeCodeCached(request);
261
+ debugLog('At cursor position', cursor, {request, response, fromCache});
262
+ if (!response) {
263
+ return null;
264
+ }
265
+
266
+ const suggestionSample = this.#pickSampleFromResponse(response);
267
+ if (!suggestionSample) {
268
+ return null;
269
+ }
270
+
271
+ const shouldBlock =
272
+ suggestionSample.attributionMetadata?.attributionAction === Host.AidaClient.RecitationAction.BLOCK;
273
+ if (shouldBlock) {
274
+ return null;
275
+ }
276
+
277
+ const suggestionText = this.#trimSuggestionOverlap(suggestionSample.generationString, request);
278
+ if (suggestionText.length === 0) {
279
+ return null;
280
+ }
281
+
282
+ return {
283
+ suggestionText,
284
+ sampleId: suggestionSample.sampleId,
285
+ fromCache,
286
+ citations: suggestionSample.attributionMetadata?.citations ?? [],
287
+ rpcGlobalId: response.metadata.rpcGlobalId,
288
+ };
289
+ }
290
+
205
291
  async #requestAidaSuggestion(request: Host.AidaClient.CompletionRequest, cursor: number): Promise<void> {
206
292
  const startTime = performance.now();
207
- let servedFromCache = false;
208
293
  this.dispatchEventToListeners(Events.REQUEST_TRIGGERED, {});
209
294
 
210
295
  try {
211
- let response = this.#checkCachedRequestForResponse(request);
212
- if (!response) {
213
- response = await this.#aidaClient.completeCode(request);
214
- if (response) {
215
- this.#updateCachedRequest(request, response);
216
- }
217
- } else {
218
- servedFromCache = true;
296
+ const sampleResponse = await this.#generateSampleForRequest(request, cursor);
297
+ if (!sampleResponse) {
298
+ this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
299
+ return;
219
300
  }
220
- debugLog('At cursor position', cursor, {request, response});
221
- if (response && response.generatedSamples.length > 0 && response.generatedSamples[0].generationString) {
222
- if (response.generatedSamples[0].attributionMetadata?.attributionAction ===
223
- Host.AidaClient.RecitationAction.BLOCK) {
224
- this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
225
- return;
226
- }
227
301
 
228
- // Use the suffix from the request to find and remove any overlap.
229
- let suggestionText = response.generatedSamples[0].generationString;
230
- if (request.suffix && request.suffix.length > 0) {
231
- suggestionText = this.#trimSuggestionOverlap(response.generatedSamples[0].generationString, request.suffix);
302
+ const {
303
+ suggestionText,
304
+ sampleId,
305
+ fromCache,
306
+ citations,
307
+ rpcGlobalId,
308
+ } = sampleResponse;
309
+ const remainingDelay = Math.max(DELAY_BEFORE_SHOWING_RESPONSE_MS - (performance.now() - startTime), 0);
310
+ this.#renderingTimeout = window.setTimeout(() => {
311
+ this.#editor.dispatch({
312
+ effects: TextEditor.Config.setAiAutoCompleteSuggestion.of({
313
+ text: suggestionText,
314
+ from: cursor,
315
+ rpcGlobalId,
316
+ sampleId,
317
+ })
318
+ });
319
+
320
+ if (fromCache) {
321
+ Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionResponseServedFromCache);
232
322
  }
233
- if (suggestionText.length === 0) {
234
- this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
235
- return;
323
+
324
+ if (rpcGlobalId) {
325
+ const latency = performance.now() - startTime;
326
+ this.#registerUserImpression(rpcGlobalId, sampleId, latency);
236
327
  }
237
328
 
238
- const remainderDelay = Math.max(DELAY_BEFORE_SHOWING_RESPONSE_MS - (performance.now() - startTime), 0);
239
- // Delays the rendering of the Code completion
240
- this.#renderingTimeout = window.setTimeout(() => {
241
- // We are not cancelling the previous responses even when there are more recent responses
242
- // from the LLM as:
243
- // In case the user kept typing characters that are prefix of the previous suggestion, it
244
- // is a valid suggestion and we should display it to the user.
245
- // In case the user typed a different character, the config for AI auto complete suggestion
246
- // will set the suggestion to null.
247
- this.#editor.dispatch({
248
- effects: TextEditor.Config.setAiAutoCompleteSuggestion.of({
249
- text: suggestionText,
250
- from: cursor,
251
- rpcGlobalId: response.metadata.rpcGlobalId,
252
- sampleId: response.generatedSamples[0].sampleId,
253
- })
254
- });
255
- if (servedFromCache) {
256
- Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeCompletionResponseServedFromCache);
257
- }
258
- debugLog('Suggestion dispatched to the editor', response.generatedSamples[0], 'at cursor position', cursor);
259
- if (response.metadata.rpcGlobalId) {
260
- const latency = performance.now() - startTime;
261
- this.#registerUserImpression(response.metadata.rpcGlobalId, response.generatedSamples[0].sampleId, latency);
262
- }
263
- const citations = response.generatedSamples[0].attributionMetadata?.citations;
264
- this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {citations});
265
- }, remainderDelay);
266
- } else {
267
- this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
268
- }
329
+ debugLog('Suggestion dispatched to the editor', suggestionText, 'at cursor position', cursor);
330
+ this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {citations});
331
+ }, remainingDelay);
269
332
  } catch (e) {
270
333
  debugLog('Error while fetching code completion suggestions from AIDA', e);
271
334
  this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
@@ -289,7 +352,12 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
289
352
  /**
290
353
  * Removes the end of a suggestion if it overlaps with the start of the suffix.
291
354
  */
292
- #trimSuggestionOverlap(generationString: string, suffix: string): string {
355
+ #trimSuggestionOverlap(generationString: string, request: Host.AidaClient.CompletionRequest): string {
356
+ const suffix = request.suffix;
357
+ if (!suffix) {
358
+ return generationString;
359
+ }
360
+
293
361
  // Iterate from the longest possible overlap down to the shortest
294
362
  for (let i = Math.min(generationString.length, suffix.length); i > 0; i--) {
295
363
  const overlapCandidate = suffix.substring(0, i);
@@ -12,7 +12,7 @@ export class ProfileNode {
12
12
  total: number;
13
13
  id: number;
14
14
  parent: ProfileNode|null;
15
- children: ProfileNode[];
15
+ children: this[];
16
16
  functionName: string;
17
17
  depth!: number;
18
18
  deoptReason!: string|null;
@@ -69,6 +69,10 @@ export class ExtensionPanel extends UI.Panel.Panel implements UI.SearchableView.
69
69
  return false;
70
70
  }
71
71
 
72
+ supportsWholeWordSearch(): boolean {
73
+ return false;
74
+ }
75
+
72
76
  supportsRegexSearch(): boolean {
73
77
  return false;
74
78
  }
@@ -239,12 +239,16 @@ export class NodeFilter {
239
239
  export class SearchConfig {
240
240
  query: string;
241
241
  caseSensitive: boolean;
242
+ wholeWord: boolean;
242
243
  isRegex: boolean;
243
244
  shouldJump: boolean;
244
245
  jumpBackward: boolean;
245
- constructor(query: string, caseSensitive: boolean, isRegex: boolean, shouldJump: boolean, jumpBackward: boolean) {
246
+ constructor(
247
+ query: string, caseSensitive: boolean, wholeWord: boolean, isRegex: boolean, shouldJump: boolean,
248
+ jumpBackward: boolean) {
246
249
  this.query = query;
247
250
  this.caseSensitive = caseSensitive;
251
+ this.wholeWord = wholeWord;
248
252
  this.isRegex = isRegex;
249
253
  this.shouldJump = shouldJump;
250
254
  this.jumpBackward = jumpBackward;
@@ -6088,7 +6088,7 @@ export const NativeFunctions = [
6088
6088
  },
6089
6089
  {
6090
6090
  name: "addAnimation",
6091
- signatures: [["animation"]]
6091
+ signatures: [["animation","action","behavior"]]
6092
6092
  },
6093
6093
  {
6094
6094
  name: "removeAnimation",
@@ -6765,6 +6765,10 @@ export const NativeFunctions = [
6765
6765
  name: "DragEvent",
6766
6766
  signatures: [["type","?eventInitDict"]]
6767
6767
  },
6768
+ {
6769
+ name: "EmailVerifiedEvent",
6770
+ signatures: [["type","?eventInitDict"]]
6771
+ },
6768
6772
  {
6769
6773
  name: "ErrorEvent",
6770
6774
  signatures: [["type","?eventInitDict"]]
@@ -7605,7 +7609,7 @@ export const NativeFunctions = [
7605
7609
  signatures: [["element","x","y","?dwidth","?dheight"]]
7606
7610
  },
7607
7611
  {
7608
- name: "drawHTML",
7612
+ name: "drawElementImage",
7609
7613
  signatures: [["element","x","y","?dwidth","?dheight"]]
7610
7614
  },
7611
7615
  {
@@ -8420,10 +8424,6 @@ export const NativeFunctions = [
8420
8424
  name: "RTCRtpScriptTransform",
8421
8425
  signatures: [["worker","?options","?transfer"]]
8422
8426
  },
8423
- {
8424
- name: "sendRtp",
8425
- signatures: [["packet","options"]]
8426
- },
8427
8427
  {
8428
8428
  name: "setHeaderExtensionsToNegotiate",
8429
8429
  signatures: [["extensions"]]
@@ -8891,7 +8891,7 @@ export const NativeFunctions = [
8891
8891
  signatures: [["provokeMode"]]
8892
8892
  },
8893
8893
  {
8894
- name: "texHTML2D",
8894
+ name: "texElementImage2D",
8895
8895
  signatures: [["target","level","internalformat","format","type","element"]]
8896
8896
  },
8897
8897
  {
@@ -367,6 +367,32 @@ export const performSearchInSearchMatches = function(
367
367
  return result;
368
368
  };
369
369
 
370
+ /**
371
+ * Finds the longest overlapping string segment between the end of the first
372
+ * string and the beginning of the second string.
373
+ *
374
+ * @param s1 The first string (whose suffix will be checked).
375
+ * @param s2 The second string (whose prefix will be checked).
376
+ * @returns The overlapping string segment, or an empty string ("")
377
+ * if no overlap is found.
378
+ */
379
+ export const getOverlap = function(s1: string, s2: string): string|null {
380
+ const minLen = Math.min(s1.length, s2.length);
381
+ // Check from longest possible overlap down to 1
382
+ for (let n = minLen; n > 0; n--) {
383
+ // slice(-n) gets the last 'n' chars
384
+ const suffix = s1.slice(-n);
385
+ // substring(0, n) gets the first 'n' chars
386
+ const prefix = s2.substring(0, n);
387
+
388
+ if (suffix === prefix) {
389
+ return suffix;
390
+ }
391
+ }
392
+
393
+ return null;
394
+ };
395
+
370
396
  export interface ParsedFilter {
371
397
  key?: string;
372
398
  text?: string|null;
@@ -443,7 +443,7 @@ export class TraceProcessor extends EventTarget {
443
443
  let model: Insights.Types.InsightModel|Error;
444
444
  try {
445
445
  options.logger?.start(`insights:${name}`);
446
- model = insight.generateInsight(data, context);
446
+ model = insight.generateInsight(data, context, options.insightTimeFormatters);
447
447
  model.frameId = context.frameId;
448
448
  const navId = context.navigation?.args.data?.navigationId;
449
449
  if (navId) {
@@ -766,7 +766,7 @@ export function extractSampleTraceId(event: Types.Events.Event): number|null {
766
766
  return event.args?.sampleTraceId ?? event.args?.data?.sampleTraceId ?? null;
767
767
  }
768
768
 
769
- // This exactly matches EntryStyles.visibleTypes. See the runtime verification in maybeInitSylesMap.
769
+ // This exactly matches Trace.Styles.visibleTypes. See the runtime verification in maybeInitStylesMap.
770
770
  // TODO(crbug.com/410884528)
771
771
  export const VISIBLE_TRACE_EVENT_TYPES = new Set<Types.Events.Name>([
772
772
  Types.Events.Name.ABORT_POST_TASK_CALLBACK,
@@ -190,11 +190,14 @@ function finalize(partialModel: PartialInsightModel<DocumentLatencyInsightModel>
190
190
  }
191
191
 
192
192
  export function generateInsight(
193
- data: Handlers.Types.HandlerData, context: InsightSetContext): DocumentLatencyInsightModel {
193
+ data: Handlers.Types.HandlerData, context: InsightSetContext,
194
+ timeFormatters?: Types.Configuration.InsightTimeFormatters): DocumentLatencyInsightModel {
194
195
  if (!context.navigation) {
195
196
  return finalize({});
196
197
  }
197
198
 
199
+ const millisToString = timeFormatters?.milli ?? i18n.TimeUtilities.millisToString;
200
+
198
201
  const documentRequest = data.NetworkRequests.byId.get(context.navigationId);
199
202
  if (!documentRequest) {
200
203
  return finalize({warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});
@@ -212,7 +215,8 @@ export function generateInsight(
212
215
  overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);
213
216
  }
214
217
 
215
- const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);
218
+ const redirectDuration =
219
+ Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000) as Types.Timing.Milli;
216
220
  overallSavingsMs += redirectDuration;
217
221
 
218
222
  const metricSavings = {
@@ -237,16 +241,14 @@ export function generateInsight(
237
241
  noRedirects: {
238
242
  label: noRedirects ? i18nString(UIStrings.passingRedirects) : i18nString(UIStrings.failedRedirects, {
239
243
  PH1: documentRequest.args.data.redirects.length,
240
- PH2: i18n.TimeUtilities.millisToString(redirectDuration),
244
+ PH2: millisToString(redirectDuration),
241
245
  }),
242
246
  value: noRedirects
243
247
  },
244
248
  serverResponseIsFast: {
245
249
  label: serverResponseIsFast ?
246
- i18nString(
247
- UIStrings.passingServerResponseTime, {PH1: i18n.TimeUtilities.millisToString(serverResponseTime)}) :
248
- i18nString(
249
- UIStrings.failedServerResponseTime, {PH1: i18n.TimeUtilities.millisToString(serverResponseTime)}),
250
+ i18nString(UIStrings.passingServerResponseTime, {PH1: millisToString(serverResponseTime)}) :
251
+ i18nString(UIStrings.failedServerResponseTime, {PH1: millisToString(serverResponseTime)}),
250
252
  value: serverResponseIsFast
251
253
  },
252
254
  usesCompression: {
@@ -8,6 +8,7 @@ import type * as Protocol from '../../../generated/protocol.js';
8
8
  import type * as Lantern from '../lantern/lantern.js';
9
9
 
10
10
  import type * as File from './File.js';
11
+ import type {Milli} from './Timing.js';
11
12
 
12
13
  export interface Configuration {
13
14
  /**
@@ -83,6 +84,17 @@ export interface ParseOptions {
83
84
  end: (id: string) => void,
84
85
  };
85
86
  lanternSettings?: Omit<Lantern.Types.Simulation.Settings, 'networkAnalysis'>;
87
+ /**
88
+ * Used when an Insight needs to format a time to string as part of its
89
+ * output. By default we use the i18n.TimeUtilities in DevTools but this
90
+ * enables it to be overridden, which is useful if you are consuming the trace
91
+ * engine outside of DevTools.
92
+ */
93
+ insightTimeFormatters?: InsightTimeFormatters;
94
+ }
95
+
96
+ export interface InsightTimeFormatters {
97
+ milli: (x: Milli) => string;
86
98
  }
87
99
 
88
100
  export interface ResolveSourceMapParams {
@@ -22,7 +22,6 @@ import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
22
22
  import * as NetworkForward from '../network/forward/forward.js';
23
23
  import * as NetworkPanel from '../network/network.js';
24
24
  import * as TimelinePanel from '../timeline/timeline.js';
25
- import * as TimelineUtils from '../timeline/utils/utils.js';
26
25
 
27
26
  import aiAssistancePanelStyles from './aiAssistancePanel.css.js';
28
27
  import {
@@ -275,7 +274,7 @@ async function getEmptyStateSuggestions(
275
274
  ];
276
275
  case AiAssistanceModel.ConversationType.PERFORMANCE_INSIGHT:
277
276
  case AiAssistanceModel.ConversationType.PERFORMANCE_CALL_TREE: {
278
- const focus = context?.getItem() as TimelineUtils.AIContext.AgentFocus | null;
277
+ const focus = context?.getItem() as AiAssistanceModel.AgentFocus | null;
279
278
  if (focus?.data.type === 'call-tree') {
280
279
  return [
281
280
  {title: 'What\'s the purpose of this work?', jslogContext: 'performance-default'},
@@ -433,7 +432,7 @@ function createRequestContext(request: SDK.NetworkRequest.NetworkRequest|null):
433
432
  return new AiAssistanceModel.RequestContext(request, calculator);
434
433
  }
435
434
 
436
- function createPerformanceTraceContext(focus: TimelineUtils.AIContext.AgentFocus|null):
435
+ function createPerformanceTraceContext(focus: AiAssistanceModel.AgentFocus|null):
437
436
  AiAssistanceModel.PerformanceTraceContext|null {
438
437
  if (!focus) {
439
438
  return null;
@@ -710,7 +709,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
710
709
  this.#selectedRequest =
711
710
  createRequestContext(UI.Context.Context.instance().flavor(SDK.NetworkRequest.NetworkRequest));
712
711
  this.#selectedPerformanceTrace =
713
- createPerformanceTraceContext(UI.Context.Context.instance().flavor(TimelineUtils.AIContext.AgentFocus));
712
+ createPerformanceTraceContext(UI.Context.Context.instance().flavor(AiAssistanceModel.AgentFocus));
714
713
  this.#selectedFile = createFileContext(UI.Context.Context.instance().flavor(Workspace.UISourceCode.UISourceCode));
715
714
  this.#updateConversationState({agent: this.#conversationAgent});
716
715
 
@@ -723,7 +722,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
723
722
  UI.Context.Context.instance().addFlavorChangeListener(
724
723
  SDK.NetworkRequest.NetworkRequest, this.#handleNetworkRequestFlavorChange);
725
724
  UI.Context.Context.instance().addFlavorChangeListener(
726
- TimelineUtils.AIContext.AgentFocus, this.#handlePerformanceTraceFlavorChange);
725
+ AiAssistanceModel.AgentFocus, this.#handlePerformanceTraceFlavorChange);
727
726
  UI.Context.Context.instance().addFlavorChangeListener(
728
727
  Workspace.UISourceCode.UISourceCode, this.#handleUISourceCodeFlavorChange);
729
728
 
@@ -760,7 +759,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
760
759
  UI.Context.Context.instance().removeFlavorChangeListener(
761
760
  SDK.NetworkRequest.NetworkRequest, this.#handleNetworkRequestFlavorChange);
762
761
  UI.Context.Context.instance().removeFlavorChangeListener(
763
- TimelineUtils.AIContext.AgentFocus, this.#handlePerformanceTraceFlavorChange);
762
+ AiAssistanceModel.AgentFocus, this.#handlePerformanceTraceFlavorChange);
764
763
  UI.Context.Context.instance().removeFlavorChangeListener(
765
764
  Workspace.UISourceCode.UISourceCode, this.#handleUISourceCodeFlavorChange);
766
765
  UI.ViewManager.ViewManager.instance().removeEventListener(
@@ -838,7 +837,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
838
837
  };
839
838
 
840
839
  #handlePerformanceTraceFlavorChange =
841
- (ev: Common.EventTarget.EventTargetEvent<TimelineUtils.AIContext.AgentFocus>): void => {
840
+ (ev: Common.EventTarget.EventTargetEvent<AiAssistanceModel.AgentFocus>): void => {
842
841
  if (this.#selectedPerformanceTrace?.getItem() === ev.data) {
843
842
  return;
844
843
  }
@@ -14,7 +14,6 @@ import * as SDK from '../../../core/sdk/sdk.js';
14
14
  import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
15
15
  import * as Workspace from '../../../models/workspace/workspace.js';
16
16
  import * as ElementsPanel from '../../../panels/elements/elements.js';
17
- import * as TimelineUtils from '../../../panels/timeline/utils/utils.js';
18
17
  import * as PanelUtils from '../../../panels/utils/utils.js';
19
18
  import * as Marked from '../../../third_party/marked/marked.js';
20
19
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
@@ -1040,7 +1039,7 @@ function renderContextIcon(context: AiAssistanceModel.ConversationContext<unknow
1040
1039
  if (item instanceof Workspace.UISourceCode.UISourceCode) {
1041
1040
  return PanelUtils.PanelUtils.getIconForSourceFile(item);
1042
1041
  }
1043
- if (item instanceof TimelineUtils.AIContext.AgentFocus) {
1042
+ if (item instanceof AiAssistanceModel.AgentFocus) {
1044
1043
  return html`<devtools-icon name="performance" title="Performance"></devtools-icon>`;
1045
1044
  }
1046
1045
  if (item instanceof SDK.DOMModel.DOMNode) {
@@ -3,6 +3,8 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as i18n from '../../../core/i18n/i18n.js';
6
+ import type * as Platform from '../../../core/platform/platform.js';
7
+ import type * as Protocol from '../../../generated/protocol.js';
6
8
 
7
9
  const UIStrings = {
8
10
  /**
@@ -552,7 +554,10 @@ const UIStrings = {
552
554
  const str_ = i18n.i18n.registerUIStrings('panels/application/components/BackForwardCacheStrings.ts', UIStrings);
553
555
  const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
554
556
 
555
- export const NotRestoredReasonDescription = {
557
+ type NotRestoredReason =
558
+ Record<Protocol.Page.BackForwardCacheNotRestoredReason, {name: () => Platform.UIString.LocalizedString}>;
559
+
560
+ export const NotRestoredReasonDescription: NotRestoredReason = {
556
561
  NotPrimaryMainFrame: {name: i18nLazyString(UIStrings.notMainFrame)},
557
562
  BackForwardCacheDisabled: {name: i18nLazyString(UIStrings.backForwardCacheDisabled)},
558
563
  RelatedActiveContentsExist: {name: i18nLazyString(UIStrings.relatedActiveContentsExist)},
@@ -567,6 +572,7 @@ export const NotRestoredReasonDescription = {
567
572
  JavaScriptExecution: {name: i18nLazyString(UIStrings.JavaScriptExecution)},
568
573
  RendererProcessKilled: {name: i18nLazyString(UIStrings.rendererProcessKilled)},
569
574
  RendererProcessCrashed: {name: i18nLazyString(UIStrings.rendererProcessCrashed)},
575
+ // @ts-expect-error kept for backwards compatibly
570
576
  GrantedMediaStreamAccess: {name: i18nLazyString(UIStrings.grantedMediaStreamAccess)},
571
577
  CacheFlushed: {name: i18nLazyString(UIStrings.cacheFlushed)},
572
578
  ServiceWorkerVersionActivation: {name: i18nLazyString(UIStrings.serviceWorkerVersionActivation)},
@@ -713,4 +719,4 @@ export const NotRestoredReasonDescription = {
713
719
  {name: i18n.i18n.lockedLazyString('CacheLimitPrunedOnModerateMemoryPressure')},
714
720
  CacheLimitPrunedOnCriticalMemoryPressure:
715
721
  {name: i18n.i18n.lockedLazyString('CacheLimitPrunedOnCriticalMemoryPressure')},
716
- };
722
+ } as const;
@@ -21,16 +21,16 @@ const UIStrings = {
21
21
  /**
22
22
  * @description Title for close button
23
23
  */
24
- dismiss: 'Dismiss',
24
+ close: 'Close',
25
25
  /**
26
26
  * @description Activity based badge award notification text
27
27
  * @example {Badge Title} PH1
28
28
  */
29
- activityBasedBadgeAwardMessage: 'You earned the {PH1} badge! It has been added to your Developer Profile.',
29
+ activityBasedBadgeAwardMessage: 'You earned the {PH1} badge! It’s been added to your Developer Profile.',
30
30
  /**
31
31
  * @description Action title for navigating to the badge settings in Google Developer Profile section
32
32
  */
33
- badgeSettings: 'Badge settings',
33
+ manageSettings: 'Manage settings',
34
34
  /**
35
35
  * @description Action title for opening the Google Developer Program profile page of the user in a new tab
36
36
  */
@@ -55,7 +55,7 @@ const UIStrings = {
55
55
  /**
56
56
  * @description Action title for enabling the "Receive badges" setting
57
57
  */
58
- receiveBadges: 'Receive badges',
58
+ receiveBadges: 'Turn on badges',
59
59
  /**
60
60
  * @description Action title for creating a Google Developer Program profle
61
61
  */
@@ -103,10 +103,10 @@ const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement)
103
103
  class="dismiss notification-button"
104
104
  @click=${input.onCloseClick}
105
105
  jslog=${VisualLogging.action('badge-notification.dismiss').track({click: true})}
106
- aria-label=${i18nString(UIStrings.dismiss)}
106
+ aria-label=${i18nString(UIStrings.close)}
107
107
  .iconName=${'cross'}
108
108
  .variant=${Buttons.Button.Variant.ICON}
109
- .title=${i18nString(UIStrings.dismiss)}
109
+ .title=${i18nString(UIStrings.close)}
110
110
  .inverseColorTheme=${true}
111
111
  ></devtools-button>`;
112
112
 
@@ -114,7 +114,7 @@ const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement)
114
114
  <style>${badgeNotificationStyles}</style>
115
115
  <div class="container">
116
116
  <div class="badge-container">
117
- <img class="badge-image" src=${input.imageUri}>
117
+ <img class="badge-image" role="presentation" src=${input.imageUri}>
118
118
  </div>
119
119
  <div class="action-and-text-container">
120
120
  <div class="label-container">
@@ -145,6 +145,8 @@ export class BadgeNotification extends UI.Widget.Widget {
145
145
  super(element);
146
146
  this.#view = view;
147
147
 
148
+ // eslint-disable-next-line
149
+ this.contentElement.role = 'alert';
148
150
  this.markAsRoot();
149
151
  }
150
152
 
@@ -240,7 +242,7 @@ export class BadgeNotification extends UI.Widget.Widget {
240
242
  message: i18nString(UIStrings.activityBasedBadgeAwardMessage, {PH1: badge.title}),
241
243
  actions: [
242
244
  {
243
- label: i18nString(UIStrings.badgeSettings),
245
+ label: i18nString(UIStrings.manageSettings),
244
246
  onClick: () => {
245
247
  this.#close();
246
248
  revealBadgeSettings();