chrome-devtools-frontend 1.0.1515796 → 1.0.1515988

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 (129) hide show
  1. package/docs/contributing/infrastructure.md +131 -82
  2. package/front_end/Tests.js +3 -29
  3. package/front_end/core/common/Progress.ts +73 -55
  4. package/front_end/core/host/UserMetrics.ts +0 -1
  5. package/front_end/core/protocol_client/InspectorBackend.ts +2 -0
  6. package/front_end/core/root/Runtime.ts +0 -1
  7. package/front_end/core/sdk/CSSMatchedStyles.ts +12 -10
  8. package/front_end/core/sdk/CSSModel.ts +1 -31
  9. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +27 -7
  10. package/front_end/core/sdk/DebuggerModel.ts +1 -31
  11. package/front_end/core/sdk/EnhancedTracesParser.ts +81 -50
  12. package/front_end/core/sdk/NetworkManager.ts +1 -31
  13. package/front_end/core/sdk/NetworkRequest.ts +1 -31
  14. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1003 -0
  15. package/front_end/core/sdk/RehydratingConnection.ts +13 -18
  16. package/front_end/core/sdk/RehydratingObject.ts +8 -31
  17. package/front_end/core/sdk/RemoteObject.ts +1 -31
  18. package/front_end/core/sdk/ResourceTreeModel.ts +1 -31
  19. package/front_end/core/sdk/RuntimeModel.ts +1 -31
  20. package/front_end/core/sdk/ServiceWorkerManager.ts +1 -31
  21. package/front_end/core/sdk/SourceMap.ts +1 -31
  22. package/front_end/core/sdk/TraceObject.ts +8 -3
  23. package/front_end/entrypoints/main/MainImpl.ts +0 -2
  24. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -3
  25. package/front_end/models/ai_assistance/ConversationHandler.ts +4 -6
  26. package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -1
  27. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +107 -72
  28. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +2 -2
  29. package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -2
  30. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +178 -85
  31. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +308 -218
  32. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +100 -100
  33. package/front_end/models/ai_assistance/data_formatters/UnitFormatters.ts +10 -1
  34. package/front_end/models/ai_assistance/performance/AIContext.ts +19 -21
  35. package/front_end/models/bindings/ContentProviderBasedProject.ts +6 -4
  36. package/front_end/models/breakpoints/BreakpointManager.ts +3 -3
  37. package/front_end/models/har/Writer.ts +11 -11
  38. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +3 -3
  39. package/front_end/models/persistence/IsolatedFileSystem.ts +4 -4
  40. package/front_end/models/persistence/IsolatedFileSystemManager.ts +7 -7
  41. package/front_end/models/persistence/PersistenceImpl.ts +8 -8
  42. package/front_end/models/persistence/PlatformFileSystem.ts +1 -1
  43. package/front_end/models/trace/ModelImpl.ts +2 -16
  44. package/front_end/models/trace/Processor.ts +15 -9
  45. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +4 -4
  46. package/front_end/models/trace/handlers/FramesHandler.ts +2 -2
  47. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +7 -10
  48. package/front_end/models/trace/handlers/MetaHandler.ts +11 -9
  49. package/front_end/models/trace/handlers/ScreenshotsHandler.ts +1 -1
  50. package/front_end/models/trace/handlers/ScriptsHandler.ts +5 -5
  51. package/front_end/models/trace/handlers/UserInteractionsHandler.ts +2 -14
  52. package/front_end/models/trace/handlers/UserTimingsHandler.ts +3 -4
  53. package/front_end/models/trace/insights/CLSCulprits.ts +1 -1
  54. package/front_end/models/trace/insights/DocumentLatency.ts +3 -4
  55. package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -1
  56. package/front_end/models/trace/insights/INPBreakdown.ts +1 -1
  57. package/front_end/models/trace/insights/ImageDelivery.ts +1 -1
  58. package/front_end/models/trace/insights/LCPBreakdown.ts +1 -1
  59. package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
  60. package/front_end/models/trace/insights/ModernHTTP.ts +1 -1
  61. package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -1
  62. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  63. package/front_end/models/trace/insights/types.ts +2 -0
  64. package/front_end/models/trace/types/TraceEvents.ts +41 -64
  65. package/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.ts +1 -1
  66. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -99
  67. package/front_end/panels/application/ServiceWorkersView.ts +0 -1
  68. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +2 -3
  69. package/front_end/panels/common/GdpSignUpDialog.ts +6 -3
  70. package/front_end/panels/console/ConsoleView.ts +23 -28
  71. package/front_end/panels/console/ConsoleViewport.ts +2 -2
  72. package/front_end/panels/console/consoleView.css +11 -1
  73. package/front_end/panels/coverage/CoverageView.ts +2 -2
  74. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -2
  75. package/front_end/panels/elements/StyleEditorWidget.ts +8 -19
  76. package/front_end/panels/elements/StylePropertyTreeElement.ts +39 -25
  77. package/front_end/panels/elements/StylesSidebarPane.ts +2 -2
  78. package/front_end/panels/elements/stylePropertiesTreeOutline.css +4 -3
  79. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -2
  80. package/front_end/panels/layers/LayerTreeModel.ts +3 -3
  81. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +4 -4
  82. package/front_end/panels/network/NetworkLogView.ts +1 -1
  83. package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
  84. package/front_end/panels/network/NetworkSearchScope.ts +6 -6
  85. package/front_end/panels/search/SearchView.ts +33 -32
  86. package/front_end/panels/settings/components/SyncSection.ts +6 -1
  87. package/front_end/panels/sources/SourcesSearchScope.ts +4 -4
  88. package/front_end/panels/sources/TabbedEditorContainer.ts +5 -5
  89. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +10 -5
  90. package/front_end/panels/timeline/TimelineFlameChartView.ts +18 -15
  91. package/front_end/panels/timeline/TimelinePanel.ts +41 -22
  92. package/front_end/panels/timeline/TracingLayerTree.ts +4 -5
  93. package/front_end/panels/timeline/components/ExportTraceOptions.ts +37 -22
  94. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +17 -7
  95. package/front_end/third_party/axe-core/README.chromium +1 -0
  96. package/front_end/third_party/codemirror/README.chromium +1 -0
  97. package/front_end/third_party/codemirror.next/README.chromium +1 -0
  98. package/front_end/third_party/csp_evaluator/README.chromium +1 -0
  99. package/front_end/third_party/diff/README.chromium +1 -0
  100. package/front_end/third_party/i18n/README.chromium +1 -0
  101. package/front_end/third_party/intl-messageformat/README.chromium +1 -0
  102. package/front_end/third_party/json5/README.chromium +1 -0
  103. package/front_end/third_party/legacy-javascript/README.chromium +1 -0
  104. package/front_end/third_party/lighthouse/README.chromium +1 -0
  105. package/front_end/third_party/lit/README.chromium +1 -0
  106. package/front_end/third_party/marked/README.chromium +1 -0
  107. package/front_end/third_party/puppeteer-replay/README.chromium +1 -0
  108. package/front_end/third_party/third-party-web/README.chromium +1 -0
  109. package/front_end/third_party/vscode.web-custom-data/README.chromium +1 -0
  110. package/front_end/third_party/wasmparser/README.chromium +1 -0
  111. package/front_end/third_party/web-vitals/README.chromium +1 -0
  112. package/front_end/ui/components/tooltips/Tooltip.ts +17 -1
  113. package/front_end/ui/legacy/ContextMenu.ts +2 -2
  114. package/front_end/ui/legacy/GlassPane.ts +7 -3
  115. package/front_end/ui/legacy/ProgressIndicator.ts +29 -16
  116. package/front_end/ui/legacy/TabbedPane.ts +2 -2
  117. package/front_end/ui/legacy/Treeoutline.ts +10 -5
  118. package/front_end/ui/legacy/UIUtils.ts +42 -10
  119. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +14 -14
  120. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +6 -6
  121. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +3 -29
  122. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +14 -14
  123. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  124. package/inspector_overlay/highlight_common.ts +1 -27
  125. package/inspector_overlay/highlight_grid_common.ts +1 -27
  126. package/inspector_overlay/tool_highlight.ts +1 -27
  127. package/inspector_overlay/tool_persistent.ts +1 -27
  128. package/inspector_overlay/tool_source_order.ts +1 -27
  129. package/package.json +1 -1
@@ -115,6 +115,7 @@ interface SearchViewInput {
115
115
  isRegex: boolean;
116
116
  searchMessage: string;
117
117
  searchResultsMessage: string;
118
+ progress: Common.Progress.Progress|null;
118
119
  onQueryChange: (query: string) => void;
119
120
  onQueryKeyDown: (evt: KeyboardEvent) => void;
120
121
  onPanelKeyDown: (evt: KeyboardEvent) => void;
@@ -127,7 +128,6 @@ interface SearchViewInput {
127
128
 
128
129
  interface SearchViewOutput {
129
130
  searchResultsElement?: HTMLElement;
130
- searchProgressPlaceholderElement?: HTMLElement;
131
131
  }
132
132
 
133
133
  type View = (input: SearchViewInput, output: SearchViewOutput, target: HTMLElement) => void;
@@ -140,6 +140,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
140
140
  isRegex,
141
141
  searchMessage,
142
142
  searchResultsMessage,
143
+ progress,
143
144
  onQueryChange,
144
145
  onQueryKeyDown,
145
146
  onPanelKeyDown,
@@ -228,7 +229,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
228
229
  </div>
229
230
  <div class="search-toolbar-summary" @keydown=${onPanelKeyDown}>
230
231
  <div class="search-message">${searchMessage}</div>
231
- <div class="flex-centered" ${ref(e => {output.searchProgressPlaceholderElement = e as HTMLElement;})}>
232
+ <div class="flex-centered">
233
+ ${progress ? html`
234
+ <devtools-progress .title=${progress.title ?? ''}
235
+ .worked=${progress.worked} .totalWork=${progress.totalWork}>
236
+ </devtools-progress>` : ''}
232
237
  </div>
233
238
  <div class="search-message">${searchResultsMessage}</div>
234
239
  </div>`, target);
@@ -248,14 +253,13 @@ export class SearchView extends UI.Widget.VBox {
248
253
  #searchConfig: Workspace.SearchConfig.SearchConfig|null;
249
254
  #pendingSearchConfig: Workspace.SearchConfig.SearchConfig|null;
250
255
  #searchResultsPane: SearchResultsPane|null;
251
- #progressIndicator: UI.ProgressIndicator.ProgressIndicator|null;
256
+ #progress: Common.Progress.Progress|null;
252
257
  #visiblePane: UI.Widget.Widget|null;
253
258
  #searchResultsElement!: HTMLElement;
254
259
  #query: string;
255
260
  #matchCase = false;
256
261
  #isRegex = false;
257
262
  #searchMessage = '';
258
- #searchProgressPlaceholderElement!: HTMLElement;
259
263
  #searchResultsMessage = '';
260
264
  readonly #advancedSearchConfig: Common.Settings.Setting<{
261
265
  query: string,
@@ -290,7 +294,7 @@ export class SearchView extends UI.Widget.VBox {
290
294
  this.#searchConfig = null;
291
295
  this.#pendingSearchConfig = null;
292
296
  this.#searchResultsPane = null;
293
- this.#progressIndicator = null;
297
+ this.#progress = null;
294
298
  this.#visiblePane = null;
295
299
  this.#throttler = throttler;
296
300
 
@@ -317,6 +321,7 @@ export class SearchView extends UI.Widget.VBox {
317
321
  isRegex: this.#isRegex,
318
322
  searchMessage: this.#searchMessage,
319
323
  searchResultsMessage: this.#searchResultsMessage,
324
+ progress: this.#progress,
320
325
  onQueryChange: (query: string) => {
321
326
  this.#query = query;
322
327
  },
@@ -334,9 +339,6 @@ export class SearchView extends UI.Widget.VBox {
334
339
  if (output.searchResultsElement) {
335
340
  this.#searchResultsElement = output.searchResultsElement;
336
341
  }
337
- if (output.searchProgressPlaceholderElement) {
338
- this.#searchProgressPlaceholderElement = output.searchProgressPlaceholderElement;
339
- }
340
342
  }
341
343
 
342
344
  #onToggleRegex(): void {
@@ -375,13 +377,12 @@ export class SearchView extends UI.Widget.VBox {
375
377
  }
376
378
 
377
379
  #onIndexingFinished(): void {
378
- if (!this.#progressIndicator) {
380
+ if (!this.#progress) {
379
381
  return;
380
382
  }
381
383
 
382
- const finished = !this.#progressIndicator.isCanceled();
383
- this.#progressIndicator.done();
384
- this.#progressIndicator = null;
384
+ const finished = !this.#progress.canceled;
385
+ this.#progress = null;
385
386
  this.#isIndexing = false;
386
387
  this.#searchMessage = finished ? '' : i18nString(UIStrings.indexingInterrupted);
387
388
  if (!finished) {
@@ -393,21 +394,20 @@ export class SearchView extends UI.Widget.VBox {
393
394
  }
394
395
  const searchConfig = this.#pendingSearchConfig;
395
396
  this.#pendingSearchConfig = null;
396
- this.#innerStartSearch(searchConfig);
397
+ this.#startSearch(searchConfig);
397
398
  }
398
399
 
399
400
  #startIndexing(): void {
400
401
  this.#isIndexing = true;
401
- if (this.#progressIndicator) {
402
- this.#progressIndicator.done();
402
+ if (this.#progress) {
403
+ this.#progress.done = true;
403
404
  }
404
- this.#progressIndicator = document.createElement('devtools-progress');
405
+ this.#progress = new Common.Progress.ProgressProxy(
406
+ new Common.Progress.Progress(), this.#onIndexingFinished.bind(this), this.requestUpdate.bind(this));
405
407
  this.#searchMessage = i18nString(UIStrings.indexing);
406
- this.#searchProgressPlaceholderElement.appendChild(this.#progressIndicator);
407
408
  this.performUpdate();
408
409
  if (this.#searchScope) {
409
- this.#searchScope.performIndexing(
410
- new Common.Progress.ProgressProxy(this.#progressIndicator, this.#onIndexingFinished.bind(this)));
410
+ this.#searchScope.performIndexing(this.#progress);
411
411
  }
412
412
  }
413
413
 
@@ -420,10 +420,10 @@ export class SearchView extends UI.Widget.VBox {
420
420
  }
421
421
 
422
422
  #onSearchResult(searchId: number, searchResult: SearchResult): void {
423
- if (searchId !== this.#searchId || !this.#progressIndicator) {
423
+ if (searchId !== this.#searchId || !this.#progress) {
424
424
  return;
425
425
  }
426
- if (this.#progressIndicator?.isCanceled()) {
426
+ if (this.#progress?.canceled) {
427
427
  this.#onIndexingFinished();
428
428
  return;
429
429
  }
@@ -450,27 +450,29 @@ export class SearchView extends UI.Widget.VBox {
450
450
  }
451
451
 
452
452
  #onSearchFinished(searchId: number, finished: boolean): void {
453
- if (searchId !== this.#searchId || !this.#progressIndicator) {
453
+ if (searchId !== this.#searchId || !this.#progress) {
454
454
  return;
455
455
  }
456
456
  if (!this.#searchResultsPane) {
457
457
  this.#nothingFound();
458
458
  }
459
+ this.#progress = null;
459
460
  this.#searchFinished(finished);
460
461
  this.#searchConfig = null;
461
462
  UI.ARIAUtils.LiveAnnouncer.alert(this.#searchMessage + ' ' + this.#searchResultsMessage);
462
463
  }
463
464
 
464
- #innerStartSearch(searchConfig: Workspace.SearchConfig.SearchConfig): void {
465
+ #startSearch(searchConfig: Workspace.SearchConfig.SearchConfig): void {
465
466
  this.#searchConfig = searchConfig;
466
- if (this.#progressIndicator) {
467
- this.#progressIndicator.done();
467
+ if (this.#progress) {
468
+ this.#progress.done = true;
468
469
  }
469
- this.#progressIndicator = document.createElement('devtools-progress');
470
- this.#searchStarted(this.#progressIndicator);
470
+ this.#progress =
471
+ new Common.Progress.ProgressProxy(new Common.Progress.Progress(), undefined, this.requestUpdate.bind(this));
472
+ this.#searchStarted();
471
473
  if (this.#searchScope) {
472
474
  void this.#searchScope.performSearch(
473
- searchConfig, this.#progressIndicator, this.#onSearchResult.bind(this, this.#searchId),
475
+ searchConfig, this.#progress, this.#onSearchResult.bind(this, this.#searchId),
474
476
  this.#onSearchFinished.bind(this, this.#searchId));
475
477
  }
476
478
  }
@@ -485,8 +487,8 @@ export class SearchView extends UI.Widget.VBox {
485
487
  }
486
488
 
487
489
  #stopSearch(): void {
488
- if (this.#progressIndicator && !this.#isIndexing) {
489
- this.#progressIndicator.cancel();
490
+ if (this.#progress && !this.#isIndexing) {
491
+ this.#progress.canceled = true;
490
492
  }
491
493
  if (this.#searchScope) {
492
494
  this.#searchScope.stopSearch();
@@ -494,7 +496,7 @@ export class SearchView extends UI.Widget.VBox {
494
496
  this.#searchConfig = null;
495
497
  }
496
498
 
497
- #searchStarted(progressIndicator: UI.ProgressIndicator.ProgressIndicator): void {
499
+ #searchStarted(): void {
498
500
  this.#searchMatchesCount = 0;
499
501
  this.#searchResultsCount = 0;
500
502
  this.#nonEmptySearchResultsCount = 0;
@@ -504,7 +506,6 @@ export class SearchView extends UI.Widget.VBox {
504
506
  this.#showPane(this.#searchingView);
505
507
  this.#searchMessage = i18nString(UIStrings.searching);
506
508
  this.performUpdate();
507
- this.#searchProgressPlaceholderElement.appendChild(progressIndicator);
508
509
  this.#updateSearchResultsMessage();
509
510
  }
510
511
 
@@ -204,6 +204,7 @@ export class SyncSection extends HTMLElement {
204
204
  receiveBadgesSettingContainerRef: this.#receiveBadgesSettingContainerRef,
205
205
  gdpProfile: this.#gdpProfile,
206
206
  isEligibleToCreateProfile: this.#isEligibleToCreateGdpProfile,
207
+ onSignUpSuccess: this.#fetchGdpDetails.bind(this),
207
208
  })}
208
209
  </fieldset>
209
210
  `, this.#shadow, {host: this});
@@ -295,8 +296,10 @@ function renderGdpSectionIfNeeded({
295
296
  receiveBadgesSettingContainerRef,
296
297
  gdpProfile,
297
298
  isEligibleToCreateProfile,
299
+ onSignUpSuccess,
298
300
  }: {
299
301
  receiveBadgesSettingContainerRef: Lit.Directives.Ref<HTMLElement>,
302
+ onSignUpSuccess: () => void,
300
303
  receiveBadgesSetting?: Common.Settings.Setting<boolean>,
301
304
  gdpProfile?: Host.GdpClient.Profile,
302
305
  isEligibleToCreateProfile?: boolean,
@@ -345,7 +348,9 @@ function renderGdpSectionIfNeeded({
345
348
  <div class="gdp-profile-sign-up-content">
346
349
  ${renderBrand()}
347
350
  <devtools-button
348
- @click=${() => PanelCommon.GdpSignUpDialog.show()}
351
+ @click=${() => PanelCommon.GdpSignUpDialog.show({
352
+ onSuccess: onSignUpSuccess
353
+ })}
349
354
  .jslogContext=${'gdp.sign-up-dialog-open'}
350
355
  .variant=${Buttons.Button.Variant.OUTLINED}>
351
356
  ${i18nString(UIStrings.signUp)}
@@ -184,12 +184,12 @@ export class SourcesSearchScope implements Search.SearchScope.SearchScope {
184
184
 
185
185
  const files = this.searchResultCandidates;
186
186
  if (!files.length) {
187
- progress.done();
187
+ progress.done = true;
188
188
  callback();
189
189
  return;
190
190
  }
191
191
 
192
- progress.setTotalWork(files.length);
192
+ progress.totalWork = files.length;
193
193
 
194
194
  let fileIndex = 0;
195
195
  const maxFileContentRequests = 20;
@@ -213,7 +213,7 @@ export class SourcesSearchScope implements Search.SearchScope.SearchScope {
213
213
  function scheduleSearchInNextFileOrFinish(this: SourcesSearchScope): void {
214
214
  if (fileIndex >= files.length) {
215
215
  if (!callbacksLeft) {
216
- progress.done();
216
+ progress.done = true;
217
217
  callback();
218
218
  return;
219
219
  }
@@ -228,7 +228,7 @@ export class SourcesSearchScope implements Search.SearchScope.SearchScope {
228
228
  function contentLoaded(
229
229
  this: SourcesSearchScope, uiSourceCode: Workspace.UISourceCode.UISourceCode,
230
230
  content: TextUtils.Text.Text): void {
231
- progress.incrementWorked(1);
231
+ ++progress.worked;
232
232
  let matches: TextUtils.ContentProvider.SearchMatch[] = [];
233
233
  const searchConfig = (this.searchConfig as Workspace.SearchConfig.SearchConfig);
234
234
  const queries = searchConfig.queries();
@@ -196,7 +196,7 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
196
196
  frame?.currentUISourceCode() === uiSourceCode) {
197
197
  Common.EventTarget.fireEvent('source-file-loaded', uiSourceCode.displayName(true));
198
198
  } else {
199
- this.innerShowFile(uiSourceCode, true);
199
+ this.#showFile(uiSourceCode, true);
200
200
  }
201
201
  }
202
202
 
@@ -279,7 +279,7 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
279
279
  }
280
280
  }
281
281
 
282
- private innerShowFile(uiSourceCode: Workspace.UISourceCode.UISourceCode, userGesture?: boolean): void {
282
+ #showFile(uiSourceCode: Workspace.UISourceCode.UISourceCode, userGesture?: boolean): void {
283
283
  if (this.reentrantShow) {
284
284
  return;
285
285
  }
@@ -430,7 +430,7 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
430
430
 
431
431
  // Select tab if this file was the last to be shown.
432
432
  if (!index) {
433
- this.innerShowFile(uiSourceCode, false);
433
+ this.#showFile(uiSourceCode, false);
434
434
  return;
435
435
  }
436
436
 
@@ -441,7 +441,7 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
441
441
  const currentProjectIsSnippets = Snippets.ScriptSnippetFileSystem.isSnippetsUISourceCode(this.#currentFile);
442
442
  const addedProjectIsSnippets = Snippets.ScriptSnippetFileSystem.isSnippetsUISourceCode(uiSourceCode);
443
443
  if (this.history.index(historyItemKey(this.#currentFile)) && currentProjectIsSnippets && !addedProjectIsSnippets) {
444
- this.innerShowFile(uiSourceCode, false);
444
+ this.#showFile(uiSourceCode, false);
445
445
  }
446
446
  }
447
447
 
@@ -578,7 +578,7 @@ export class TabbedEditorContainer extends Common.ObjectWrapper.ObjectWrapper<Ev
578
578
 
579
579
  const uiSourceCode = this.files.get(tabId);
580
580
  if (uiSourceCode) {
581
- this.innerShowFile(uiSourceCode, isUserGesture);
581
+ this.#showFile(uiSourceCode, isUserGesture);
582
582
  }
583
583
  }
584
584
 
@@ -248,12 +248,17 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW
248
248
 
249
249
  const contextMenu = new UI.ContextMenu.ContextMenu(mouseEvent);
250
250
  if (perfAIEntryPointEnabled && this.parsedTrace) {
251
- const aiCallTree = AIAssistance.AICallTree.fromEvent(entry, this.parsedTrace);
252
- if (aiCallTree) {
251
+ const callTree = AIAssistance.AICallTree.fromEvent(entry, this.parsedTrace);
252
+ if (callTree) {
253
+ let focus = UI.Context.Context.instance().flavor(AIAssistance.AgentFocus);
254
+ if (focus) {
255
+ focus = focus.withCallTree(callTree);
256
+ } else {
257
+ focus = AIAssistance.AgentFocus.fromCallTree(callTree);
258
+ }
259
+ UI.Context.Context.instance().setFlavor(AIAssistance.AgentFocus, focus);
260
+
253
261
  const action = UI.ActionRegistry.ActionRegistry.instance().getAction(PERF_AI_ACTION_ID);
254
- // The other side of setFlavor is handleTraceEntryNodeFlavorChange() in FreestylerPanel
255
- const context = AIAssistance.AgentFocus.fromCallTree(aiCallTree);
256
- UI.Context.Context.instance().setFlavor(AIAssistance.AgentFocus, context);
257
262
 
258
263
  if (Root.Runtime.hostConfig.devToolsAiSubmenuPrompts?.enabled) {
259
264
  function appendSubmenuPromptAction(
@@ -1510,22 +1510,25 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
1510
1510
  // supports (currently, only main thread events), then set the context's
1511
1511
  // "flavor" to be the AI Call Tree of the active event.
1512
1512
  // This is listened to by the AI Assistance panel to update its state.
1513
- // Note that we do not change the Context back to `null` if the user picks
1514
- // an invalid event - we don't want to reset it back as it may be they are
1515
- // clicking around in order to understand something.
1516
1513
  // We also do this in a rAF to not block the UI updating to show the selected event first.
1517
- if (selectionIsEvent(selection) && this.#parsedTrace) {
1518
- requestAnimationFrame(() => {
1519
- if (!this.#parsedTrace) {
1520
- return;
1521
- }
1522
- const aiCallTree = AIAssistance.AICallTree.fromEvent(selection.event, this.#parsedTrace);
1523
- if (aiCallTree) {
1524
- const context = AIAssistance.AgentFocus.fromCallTree(aiCallTree);
1525
- UI.Context.Context.instance().setFlavor(AIAssistance.AgentFocus, context);
1526
- }
1527
- });
1528
- }
1514
+ requestAnimationFrame(() => {
1515
+ if (!this.#parsedTrace) {
1516
+ return;
1517
+ }
1518
+
1519
+ const callTree =
1520
+ selectionIsEvent(selection) ? AIAssistance.AICallTree.fromEvent(selection.event, this.#parsedTrace) : null;
1521
+ let focus = UI.Context.Context.instance().flavor(AIAssistance.AgentFocus);
1522
+ if (focus) {
1523
+ focus = focus.withCallTree(callTree);
1524
+ } else if (callTree) {
1525
+ focus = AIAssistance.AgentFocus.fromCallTree(callTree);
1526
+ } else {
1527
+ focus = null;
1528
+ }
1529
+
1530
+ UI.Context.Context.instance().setFlavor(AIAssistance.AgentFocus, focus);
1531
+ });
1529
1532
  }
1530
1533
 
1531
1534
  // Only opens the details view of a selection. This is used for Timing Markers. Timing markers replace
@@ -940,9 +940,9 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
940
940
  throw new Error('could not create performance agent focus');
941
941
  }
942
942
 
943
- const agent = conversationHandler.createAgent(AiAssistanceModel.ConversationType.PERFORMANCE_FULL);
943
+ const agent = conversationHandler.createAgent(AiAssistanceModel.ConversationType.PERFORMANCE);
944
944
  const conversation = new AiAssistanceModel.Conversation(
945
- AiAssistanceModel.ConversationType.PERFORMANCE_FULL,
945
+ AiAssistanceModel.ConversationType.PERFORMANCE,
946
946
  [],
947
947
  agent.id,
948
948
  /* isReadOnly */ true,
@@ -950,6 +950,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
950
950
  );
951
951
 
952
952
  const selected = new AiAssistanceModel.PerformanceTraceContext(focus);
953
+ selected.external = true;
953
954
 
954
955
  this.#externalAIConversationData = {
955
956
  conversationHandler,
@@ -1373,18 +1374,17 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1373
1374
  void contextMenu.show();
1374
1375
  }
1375
1376
 
1376
- /**
1377
- * Saves a trace file to disk.
1378
- * Pass `config.savingEnhancedTrace === true` to include source maps in the resulting metadata.
1379
- * Pass `config.addModifications === true` to include user modifications to the trace file, which includes:
1380
- * 1. Annotations
1381
- * 2. Filtering / collapsing of the flame chart.
1382
- * 3. Visual track configuration (re-ordering or hiding tracks).
1383
- */
1384
1377
  async saveToFile(config: {
1385
1378
  includeScriptContent: boolean,
1386
1379
  includeSourceMaps: boolean,
1380
+ /**
1381
+ * Includes many things:
1382
+ * 1. annotations
1383
+ * 2. filtering / collapsing of the flame chart
1384
+ * 3. visual track configuration (re-ordering or hiding tracks)
1385
+ **/
1387
1386
  addModifications: boolean,
1387
+ shouldCompress: boolean,
1388
1388
  }): Promise<void> {
1389
1389
  if (this.state !== State.IDLE) {
1390
1390
  return;
@@ -1407,7 +1407,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1407
1407
  }
1408
1408
 
1409
1409
  const traceEvents = parsedTrace.traceEvents.map(event => {
1410
- if (Trace.Types.Events.isAnyScriptCatchupEvent(event) && event.name !== 'StubScriptCatchup') {
1410
+ if (Trace.Types.Events.isAnyScriptSourceEvent(event) && event.name !== 'StubScriptCatchup') {
1411
1411
  const mappedScript = scriptByIdMap.get(`${event.args.data.isolate}.${event.args.data.scriptId}`);
1412
1412
 
1413
1413
  // If the checkbox to include script content is not checked or if it comes from and
@@ -1425,7 +1425,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1425
1425
  args: {
1426
1426
  data: {isolate: event.args.data.isolate, scriptId: event.args.data.scriptId},
1427
1427
  },
1428
- } as Trace.Types.Events.V8SourceRundownSourcesStubScriptCatchupEvent;
1428
+ } as Trace.Types.Events.RundownScriptStub;
1429
1429
  }
1430
1430
  }
1431
1431
 
@@ -1447,7 +1447,8 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1447
1447
  await this.innerSaveToFile(traceEvents, metadata, {
1448
1448
  includeScriptContent: config.includeScriptContent,
1449
1449
  includeSourceMaps: config.includeSourceMaps,
1450
- addModifications: config.addModifications
1450
+ addModifications: config.addModifications,
1451
+ shouldCompress: config.shouldCompress,
1451
1452
  });
1452
1453
  } catch (e) {
1453
1454
  // We expect the error to be an Error class, but this deals with any weird case where it's not.
@@ -1467,6 +1468,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1467
1468
  includeScriptContent: boolean,
1468
1469
  includeSourceMaps: boolean,
1469
1470
  addModifications: boolean,
1471
+ shouldCompress: boolean,
1470
1472
  }): Promise<void> {
1471
1473
  // Base the filename on the trace's time of recording
1472
1474
  const isoDate =
@@ -1501,8 +1503,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1501
1503
 
1502
1504
  let blob = new Blob(blobParts, {type: 'application/json'});
1503
1505
 
1504
- // TODO: Enable by default and connect with upcoming SaveDialog
1505
- if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_SAVE_AS_GZ)) {
1506
+ if (config.shouldCompress) {
1506
1507
  fileName = `${fileName}.gz` as Platform.DevToolsPath.RawPathString;
1507
1508
  const gzStream = Common.Gzip.compressStream(blob.stream());
1508
1509
  blob = await new Response(gzStream, {
@@ -1537,6 +1538,18 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
1537
1538
  }
1538
1539
  }
1539
1540
 
1541
+ async handleSaveToFileAction(): Promise<void> {
1542
+ const exportTraceOptionsElement =
1543
+ this.saveButton.element as TimelineComponents.ExportTraceOptions.ExportTraceOptions;
1544
+ const state = exportTraceOptionsElement.state;
1545
+ await this.saveToFile({
1546
+ includeScriptContent: state.includeScriptContent,
1547
+ includeSourceMaps: state.includeSourceMaps,
1548
+ addModifications: state.includeAnnotations,
1549
+ shouldCompress: state.shouldCompress,
1550
+ });
1551
+ }
1552
+
1540
1553
  #filterMetadataSourceMaps(metadata: Trace.Types.File.MetaData): Trace.Types.File.MetadataSourceMap[]|undefined {
1541
1554
  if (!metadata.sourceMaps) {
1542
1555
  return undefined;
@@ -2125,8 +2138,9 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2125
2138
 
2126
2139
  const exclusiveFilter = this.#exclusiveFilterPerTrace.get(traceIndex) ?? null;
2127
2140
  this.#applyActiveFilters(parsedTrace.data.Meta.traceIsGeneric, exclusiveFilter);
2128
- (this.saveButton.element as TimelineComponents.ExportTraceOptions.ExportTraceOptions)
2129
- .updateContentVisibility(currentManager ? currentManager.getAnnotations()?.length > 0 : false);
2141
+ (this.saveButton.element as TimelineComponents.ExportTraceOptions.ExportTraceOptions).updateContentVisibility({
2142
+ annotationsExist: currentManager ? currentManager.getAnnotations()?.length > 0 : false
2143
+ });
2130
2144
 
2131
2145
  // Add ModificationsManager listeners for annotations change to update the
2132
2146
  // Annotation Overlays.
@@ -2226,6 +2240,9 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2226
2240
  Host.UserMetrics.TimelineNavigationSetting.MODERN_AT_SESSION_FIRST_TRACE);
2227
2241
  }
2228
2242
  }
2243
+
2244
+ UI.Context.Context.instance().setFlavor(
2245
+ AiAssistanceModel.AgentFocus, AiAssistanceModel.AgentFocus.full(parsedTrace));
2229
2246
  }
2230
2247
 
2231
2248
  #onAnnotationModifiedEvent(e: Event): void {
@@ -2258,8 +2275,9 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2258
2275
  const annotations = currentManager?.getAnnotations() ?? [];
2259
2276
  const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations);
2260
2277
  this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap);
2261
- (this.saveButton.element as TimelineComponents.ExportTraceOptions.ExportTraceOptions)
2262
- .updateContentVisibility(currentManager ? currentManager.getAnnotations()?.length > 0 : false);
2278
+ (this.saveButton.element as TimelineComponents.ExportTraceOptions.ExportTraceOptions).updateContentVisibility({
2279
+ annotationsExist: currentManager ? currentManager.getAnnotations()?.length > 0 : false
2280
+ });
2263
2281
  }
2264
2282
 
2265
2283
  /**
@@ -2650,7 +2668,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2650
2668
  }
2651
2669
 
2652
2670
  #createSourceMapResolver(isFreshRecording: boolean, metadata: Trace.Types.File.MetaData|null):
2653
- Trace.TraceModel.ParseConfig['resolveSourceMap'] {
2671
+ Trace.Types.Configuration.ParseOptions['resolveSourceMap'] {
2654
2672
  const debuggerModelForFrameId = new Map<string, SDK.DebuggerModel.DebuggerModel>();
2655
2673
  for (const target of SDK.TargetManager.TargetManager.instance().targets()) {
2656
2674
  const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
@@ -2742,6 +2760,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2742
2760
  metadata: metadata ?? undefined,
2743
2761
  isFreshRecording,
2744
2762
  resolveSourceMap: this.#createSourceMapResolver(isFreshRecording, metadata),
2763
+ isCPUProfile: metadata?.dataOrigin === Trace.Types.File.DataOrigin.CPU_PROFILE,
2745
2764
  };
2746
2765
 
2747
2766
  if (window.location.href.includes('devtools/bundled') || window.location.search.includes('debugFrontend')) {
@@ -3112,7 +3131,7 @@ ${responseTextForPassedInsights}`;
3112
3131
  Promise<AsyncGenerator<AiAssistanceModel.ExternalRequestResponse, AiAssistanceModel.ExternalRequestResponse>> {
3113
3132
  const data = TimelinePanel.instance().getOrCreateExternalAIConversationData();
3114
3133
  return await data.conversationHandler.handleExternalRequest({
3115
- conversationType: AiAssistanceModel.ConversationType.PERFORMANCE_FULL,
3134
+ conversationType: AiAssistanceModel.ConversationType.PERFORMANCE,
3116
3135
  prompt,
3117
3136
  data,
3118
3137
  });
@@ -3196,7 +3215,7 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
3196
3215
  panel.recordReload();
3197
3216
  return true;
3198
3217
  case 'timeline.save-to-file':
3199
- void panel.saveToFile({includeScriptContent: false, includeSourceMaps: false, addModifications: false});
3218
+ void panel.handleSaveToFileAction();
3200
3219
  return true;
3201
3220
  case 'timeline.load-from-file':
3202
3221
  panel.selectFileToLoad();
@@ -38,10 +38,10 @@ export class TracingLayerTree extends SDK.LayerTreeBase.LayerTreeBase {
38
38
  this.layersById = new Map();
39
39
  this.setContentRoot(null);
40
40
  if (root) {
41
- const convertedLayers = this.innerSetLayers(oldLayersById, root);
41
+ const convertedLayers = this.#setLayers(oldLayersById, root);
42
42
  this.setRoot(convertedLayers);
43
43
  } else if (layers) {
44
- const processedLayers = layers.map(this.innerSetLayers.bind(this, oldLayersById));
44
+ const processedLayers = layers.map(this.#setLayers.bind(this, oldLayersById));
45
45
  const contentRoot = this.contentRoot();
46
46
  if (!contentRoot) {
47
47
  throw new Error('Content root is not set.');
@@ -86,8 +86,7 @@ export class TracingLayerTree extends SDK.LayerTreeBase.LayerTreeBase {
86
86
  }
87
87
  }
88
88
 
89
- private innerSetLayers(oldLayersById: Map<string|number, SDK.LayerTreeBase.Layer>, payload: TracingLayerPayload):
90
- TracingLayer {
89
+ #setLayers(oldLayersById: Map<string|number, SDK.LayerTreeBase.Layer>, payload: TracingLayerPayload): TracingLayer {
91
90
  let layer = (oldLayersById.get(payload.layer_id) as TracingLayer | null);
92
91
  if (layer) {
93
92
  layer.reset(payload);
@@ -102,7 +101,7 @@ export class TracingLayerTree extends SDK.LayerTreeBase.LayerTreeBase {
102
101
  this.setContentRoot(layer);
103
102
  }
104
103
  for (let i = 0; payload.children && i < payload.children.length; ++i) {
105
- layer.addChild(this.innerSetLayers(oldLayersById, payload.children[i]));
104
+ layer.addChild(this.#setLayers(oldLayersById, payload.children[i]));
106
105
  }
107
106
  return layer;
108
107
  }