chrome-devtools-frontend 1.0.1548980 → 1.0.1549484

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 (188) hide show
  1. package/docs/contributing/settings-experiments-features.md +35 -0
  2. package/docs/styleguide/ux/patterns.md +27 -0
  3. package/eslint.config.mjs +1 -0
  4. package/front_end/Tests.js +2 -0
  5. package/front_end/core/host/InspectorFrontendHost.ts +26 -558
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +6 -3
  7. package/front_end/core/host/InspectorFrontendHostStub.ts +558 -0
  8. package/front_end/core/host/ResourceLoader.ts +9 -23
  9. package/front_end/core/host/UserMetrics.ts +4 -4
  10. package/front_end/core/root/DevToolsContext.ts +4 -0
  11. package/front_end/core/root/Runtime.ts +10 -0
  12. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -2
  13. package/front_end/core/sdk/CSSModel.ts +24 -24
  14. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +11 -11
  15. package/front_end/core/sdk/CSSQuery.ts +1 -1
  16. package/front_end/core/sdk/CSSRule.ts +2 -2
  17. package/front_end/core/sdk/CSSStyleDeclaration.ts +1 -1
  18. package/front_end/core/sdk/CSSStyleSheetHeader.ts +1 -1
  19. package/front_end/core/sdk/DOMModel.ts +3 -0
  20. package/front_end/core/sdk/NetworkManager.ts +29 -31
  21. package/front_end/core/sdk/NetworkRequest.ts +4 -0
  22. package/front_end/core/sdk/OverlayModel.ts +2 -2
  23. package/front_end/core/sdk/PageResourceLoader.ts +63 -37
  24. package/front_end/core/sdk/SourceMap.ts +6 -0
  25. package/front_end/core/sdk/SourceMapCache.ts +21 -0
  26. package/front_end/core/sdk/SourceMapManager.ts +7 -6
  27. package/front_end/core/sdk/SourceMapScopesInfo.ts +6 -2
  28. package/front_end/core/sdk/TargetManager.ts +14 -2
  29. package/front_end/core/sdk/sdk-meta.ts +13 -0
  30. package/front_end/entrypoints/formatter_worker/FormatterActions.ts +1 -0
  31. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +1 -1
  32. package/front_end/entrypoints/main/MainImpl.ts +13 -3
  33. package/front_end/foundation/Universe.ts +1 -1
  34. package/front_end/generated/Deprecation.ts +18 -4
  35. package/front_end/generated/InspectorBackendCommands.ts +33 -31
  36. package/front_end/generated/SupportedCSSProperties.js +41 -41
  37. package/front_end/generated/protocol-mapping.d.ts +12 -0
  38. package/front_end/generated/protocol-proxy-api.d.ts +11 -0
  39. package/front_end/generated/protocol.ts +70 -35
  40. package/front_end/models/ai_assistance/AiConversation.ts +5 -4
  41. package/front_end/models/ai_assistance/ChangeManager.ts +4 -4
  42. package/front_end/models/ai_assistance/ConversationHandler.ts +0 -15
  43. package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -6
  44. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +135 -3
  45. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +24 -0
  46. package/front_end/models/bindings/CompilerScriptMapping.ts +43 -0
  47. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +19 -0
  48. package/front_end/models/bindings/ResourceMapping.ts +73 -0
  49. package/front_end/models/bindings/ResourceScriptMapping.ts +50 -0
  50. package/front_end/models/issues_manager/GenericIssue.ts +17 -0
  51. package/front_end/models/issues_manager/descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  52. package/front_end/models/javascript_metadata/NativeFunctions.js +7 -3
  53. package/front_end/models/source_map_scopes/FunctionCodeResolver.snapshot.txt +98 -0
  54. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +270 -0
  55. package/front_end/models/source_map_scopes/source_map_scopes.ts +2 -0
  56. package/front_end/models/workspace/UISourceCode.ts +51 -44
  57. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +76 -34
  58. package/front_end/panels/ai_assistance/aiAssistancePanel.css +1 -0
  59. package/front_end/panels/ai_assistance/components/ChatView.ts +23 -11
  60. package/front_end/panels/application/AppManifestView.ts +3 -2
  61. package/front_end/panels/application/FrameDetailsView.ts +5 -6
  62. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  63. package/front_end/panels/application/TrustTokensTreeElement.ts +2 -6
  64. package/front_end/panels/application/components/PermissionsPolicySection.ts +201 -157
  65. package/front_end/panels/application/components/ProtocolHandlersView.ts +117 -80
  66. package/front_end/panels/application/components/ServiceWorkerRouterView.ts +47 -41
  67. package/front_end/panels/application/components/StorageMetadataView.ts +31 -34
  68. package/front_end/panels/application/components/TrustTokensView.ts +76 -68
  69. package/front_end/panels/console/ConsoleView.ts +3 -2
  70. package/front_end/panels/console/ConsoleViewMessage.ts +6 -4
  71. package/front_end/panels/console/console-meta.ts +0 -13
  72. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +3 -1
  73. package/front_end/panels/elements/CSSRuleValidator.ts +7 -7
  74. package/front_end/panels/elements/CSSRuleValidatorHelper.ts +2 -2
  75. package/front_end/panels/elements/ElementsTreeElement.ts +16 -13
  76. package/front_end/panels/elements/ElementsTreeOutline.ts +2 -1
  77. package/front_end/panels/elements/LayoutPane.ts +12 -10
  78. package/front_end/panels/elements/StylePropertyTreeElement.ts +12 -12
  79. package/front_end/panels/elements/components/AdornerManager.ts +3 -3
  80. package/front_end/panels/elements/components/StylePropertyEditor.ts +6 -6
  81. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +27 -49
  82. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +15 -11
  83. package/front_end/panels/media/PlayerListView.ts +100 -73
  84. package/front_end/panels/media/playerListView.css +5 -0
  85. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +3 -3
  86. package/front_end/panels/network/RequestConditionsDrawer.ts +5 -5
  87. package/front_end/panels/network/components/DirectSocketConnectionView.ts +17 -0
  88. package/front_end/panels/network/resourceChunkView.css +4 -0
  89. package/front_end/panels/security/CookieControlsView.ts +1 -1
  90. package/front_end/panels/sensors/LocationsSettingsTab.ts +1 -1
  91. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +1 -1
  92. package/front_end/panels/settings/KeybindsSettingsTab.ts +1 -1
  93. package/front_end/panels/settings/SettingsScreen.ts +6 -6
  94. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  95. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -1
  96. package/front_end/panels/snippets/SnippetsQuickOpen.ts +4 -2
  97. package/front_end/panels/sources/CSSPlugin.ts +1 -1
  98. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +13 -5
  99. package/front_end/panels/sources/GoToLineQuickOpen.ts +4 -2
  100. package/front_end/panels/sources/NavigatorView.ts +2 -2
  101. package/front_end/panels/sources/OpenFileQuickOpen.ts +7 -8
  102. package/front_end/panels/sources/OutlineQuickOpen.ts +6 -3
  103. package/front_end/panels/sources/ProfilePlugin.ts +21 -12
  104. package/front_end/panels/sources/UISourceCodeFrame.ts +0 -1
  105. package/front_end/panels/sources/filteredUISourceCodeListProvider.css +41 -0
  106. package/front_end/panels/timeline/TimelinePanel.ts +17 -18
  107. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +3 -3
  108. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
  109. package/front_end/panels/timeline/docs/flame_chart_migration.md +11 -16
  110. package/front_end/panels/utils/utils.ts +17 -3
  111. package/front_end/panels/whats_new/ReleaseNoteText.ts +10 -20
  112. package/front_end/panels/whats_new/resources/WNDT.md +8 -8
  113. package/front_end/third_party/chromium/README.chromium +1 -1
  114. package/front_end/third_party/puppeteer/third_party/mitt/README.chromium +1 -0
  115. package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -0
  116. package/front_end/third_party/puppeteer/third_party/rxjs/README.chromium +1 -0
  117. package/front_end/ui/components/adorners/Adorner.ts +1 -1
  118. package/front_end/ui/components/annotations/AnnotationRepository.ts +98 -0
  119. package/front_end/ui/components/annotations/AnnotationType.ts +10 -0
  120. package/front_end/ui/components/annotations/annotations.ts +6 -0
  121. package/front_end/ui/components/buttons/Button.ts +1 -1
  122. package/front_end/ui/components/buttons/FloatingButton.ts +1 -1
  123. package/front_end/ui/components/chrome_link/ChromeLink.ts +1 -1
  124. package/front_end/ui/components/dialogs/ButtonDialog.ts +1 -1
  125. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  126. package/front_end/ui/components/dialogs/ShortcutDialog.ts +1 -0
  127. package/front_end/ui/components/diff_view/DiffView.ts +1 -1
  128. package/front_end/ui/components/expandable_list/ExpandableList.ts +1 -1
  129. package/front_end/ui/components/highlighting/HighlightElement.ts +1 -0
  130. package/front_end/ui/components/highlighting/MarkupHighlight.ts +162 -0
  131. package/front_end/ui/components/highlighting/highlighting.ts +7 -0
  132. package/front_end/ui/components/icon_button/FileSourceIcon.ts +1 -1
  133. package/front_end/ui/components/icon_button/Icon.ts +4 -2
  134. package/front_end/ui/components/icon_button/IconButton.ts +1 -1
  135. package/front_end/ui/components/issue_counter/IssueCounter.ts +1 -1
  136. package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +1 -1
  137. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +1 -1
  138. package/front_end/ui/components/linkifier/LinkifierImpl.ts +1 -1
  139. package/front_end/ui/components/list/List.ts +184 -0
  140. package/front_end/ui/components/list/list.css +90 -0
  141. package/front_end/ui/components/{cards/cards.ts → list/lists.ts} +3 -3
  142. package/front_end/ui/components/markdown_view/CodeBlock.ts +1 -1
  143. package/front_end/ui/components/markdown_view/MarkdownImage.ts +1 -1
  144. package/front_end/ui/components/markdown_view/MarkdownLink.ts +1 -1
  145. package/front_end/ui/components/markdown_view/MarkdownView.ts +1 -1
  146. package/front_end/ui/components/menus/Menu.ts +1 -1
  147. package/front_end/ui/components/menus/SelectMenu.ts +1 -1
  148. package/front_end/ui/components/node_text/NodeText.ts +1 -1
  149. package/front_end/ui/components/panel_feedback/FeedbackButton.ts +1 -1
  150. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +1 -1
  151. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  152. package/front_end/ui/components/panel_introduction_steps/PanelIntroductionSteps.ts +1 -1
  153. package/front_end/ui/components/report_view/ReportView.ts +1 -1
  154. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -1
  155. package/front_end/ui/components/settings/SettingCheckbox.ts +1 -1
  156. package/front_end/ui/components/settings/SettingDeprecationWarning.ts +1 -1
  157. package/front_end/ui/components/snackbars/Snackbar.ts +1 -1
  158. package/front_end/ui/components/spinners/Spinner.ts +1 -1
  159. package/front_end/ui/components/srgb_overlay/SrgbOverlay.ts +1 -1
  160. package/front_end/ui/components/suggestion_input/SuggestionInput.ts +1 -0
  161. package/front_end/ui/components/survey_link/SurveyLink.ts +1 -1
  162. package/front_end/ui/components/switch/SwitchImpl.ts +1 -1
  163. package/front_end/ui/components/text_editor/TextEditor.ts +1 -0
  164. package/front_end/ui/components/text_prompt/TextPrompt.ts +1 -1
  165. package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
  166. package/front_end/ui/components/tree_outline/TreeOutline.ts +1 -1
  167. package/front_end/ui/kit/kit.ts +5 -0
  168. package/front_end/ui/legacy/TabbedPane.ts +98 -0
  169. package/front_end/ui/legacy/UIUtils.ts +0 -184
  170. package/front_end/ui/legacy/ViewManager.ts +23 -8
  171. package/front_end/ui/legacy/ViewRegistration.ts +21 -22
  172. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +5 -4
  173. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +73 -35
  174. package/front_end/ui/legacy/components/perf_ui/LiveHeapProfile.ts +11 -2
  175. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +12 -13
  176. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +7 -16
  177. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +5 -6
  178. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +18 -65
  179. package/front_end/ui/legacy/components/source_frame/JSONView.ts +2 -1
  180. package/front_end/ui/legacy/tabbedPane.css +10 -0
  181. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  182. package/inspector_overlay/README.md +3 -3
  183. package/mcp/HostBindings.ts +310 -0
  184. package/mcp/mcp.ts +17 -0
  185. package/mcp/tsconfig.json +6 -1
  186. package/package.json +26 -24
  187. /package/front_end/ui/{components → kit}/cards/Card.ts +0 -0
  188. /package/front_end/ui/{components → kit}/cards/card.css +0 -0
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
- import '../../ui/components/cards/cards.js';
6
+ import '../../ui/kit/kit.js';
7
7
 
8
8
  import * as Common from '../../core/common/common.js';
9
9
  import * as i18n from '../../core/i18n/i18n.js';
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
- import '../../ui/components/cards/cards.js';
6
+ import '../../ui/kit/kit.js';
7
7
 
8
8
  import * as Common from '../../core/common/common.js';
9
9
  import * as i18n from '../../core/i18n/i18n.js';
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
- import '../../ui/components/cards/cards.js';
6
+ import '../../ui/kit/kit.js';
7
7
 
8
8
  import * as Common from '../../core/common/common.js';
9
9
  import * as Host from '../../core/host/host.js';
@@ -5,16 +5,16 @@
5
5
 
6
6
  /* eslint-disable @devtools/no-imperative-dom-api */
7
7
 
8
- import '../../ui/components/cards/cards.js';
8
+ import '../../ui/kit/kit.js';
9
9
 
10
10
  import * as Common from '../../core/common/common.js';
11
11
  import * as Host from '../../core/host/host.js';
12
12
  import * as i18n from '../../core/i18n/i18n.js';
13
13
  import * as Root from '../../core/root/root.js';
14
14
  import * as Buttons from '../../ui/components/buttons/buttons.js';
15
- import type * as Cards from '../../ui/components/cards/cards.js';
16
15
  import * as IconButton from '../../ui/components/icon_button/icon_button.js';
17
16
  import * as UIHelpers from '../../ui/helpers/helpers.js';
17
+ import type {Card} from '../../ui/kit/kit.js';
18
18
  import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
19
19
  import * as Components from '../../ui/legacy/components/utils/utils.js';
20
20
  import * as UI from '../../ui/legacy/legacy.js';
@@ -83,7 +83,7 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
83
83
 
84
84
  let settingsScreenInstance: SettingsScreen;
85
85
 
86
- function createSettingsCard(heading: Common.UIString.LocalizedString, ...content: HTMLElement[]): Cards.Card.Card {
86
+ function createSettingsCard(heading: Common.UIString.LocalizedString, ...content: HTMLElement[]): Card {
87
87
  const card = document.createElement('devtools-card');
88
88
  card.heading = heading;
89
89
  card.append(...content);
@@ -382,8 +382,8 @@ export class GenericSettingsTab extends UI.Widget.VBox implements SettingsTab {
382
382
  }
383
383
 
384
384
  export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTab {
385
- #experimentsSection: Cards.Card.Card|undefined;
386
- #unstableExperimentsSection: Cards.Card.Card|undefined;
385
+ #experimentsSection: Card|undefined;
386
+ #unstableExperimentsSection: Card|undefined;
387
387
  private readonly experimentToControl = new Map<Root.Runtime.Experiment, HTMLElement>();
388
388
  private readonly containerElement: HTMLElement;
389
389
 
@@ -581,7 +581,7 @@ export class Revealer implements Common.Revealer.Revealer<Root.Runtime.Experimen
581
581
  }
582
582
 
583
583
  // Reveal settings views
584
- for (const view of UI.ViewManager.getRegisteredViewExtensions()) {
584
+ for (const view of UI.ViewManager.ViewManager.instance().getRegisteredViewExtensions()) {
585
585
  const id = view.viewId();
586
586
  const location = view.location();
587
587
  if (location !== UI.ViewManager.ViewLocationValues.SETTINGS_VIEW) {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import '../../ui/legacy/legacy.js';
6
6
  import '../../ui/components/buttons/buttons.js';
7
- import '../../ui/components/cards/cards.js';
7
+ import '../../ui/kit/kit.js';
8
8
 
9
9
  import * as Common from '../../core/common/common.js';
10
10
  import * as i18n from '../../core/i18n/i18n.js';
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
- import '../../../ui/components/cards/cards.js';
6
+ import '../../../ui/kit/kit.js';
7
7
 
8
8
  import * as i18n from '../../../core/i18n/i18n.js';
9
9
  import * as EmulationModel from '../../../models/emulation/emulation.js';
@@ -81,9 +81,11 @@ export class SnippetsQuickOpen extends QuickOpen.FilteredListWidget.Provider {
81
81
  return this.snippets[itemIndex].name();
82
82
  }
83
83
 
84
- override renderItem(itemIndex: number, query: string, titleElement: Element, _subtitleElement: Element): void {
84
+ override renderItem(itemIndex: number, query: string, wrapperElement: Element): void {
85
+ const itemElement = wrapperElement.createChild('div');
86
+ const titleElement = itemElement.createChild('div');
85
87
  const icon = IconButton.Icon.create('snippet', 'snippet');
86
- titleElement.parentElement?.parentElement?.insertBefore(icon, titleElement.parentElement);
88
+ wrapperElement.insertBefore(icon, itemElement);
87
89
  titleElement.textContent = this.snippets[itemIndex].name();
88
90
  QuickOpen.FilteredListWidget.FilteredListWidget.highlightRanges(titleElement, query, true);
89
91
  }
@@ -61,7 +61,7 @@ function findPropertyAt(node: CodeMirror.SyntaxNode, pos: number): CodeMirror.Sy
61
61
  }
62
62
 
63
63
  function getCurrentStyleSheet(
64
- url: Platform.DevToolsPath.UrlString, cssModel: SDK.CSSModel.CSSModel): Protocol.CSS.StyleSheetId {
64
+ url: Platform.DevToolsPath.UrlString, cssModel: SDK.CSSModel.CSSModel): Protocol.DOM.StyleSheetId {
65
65
  const currentStyleSheet = cssModel.getStyleSheetIdsForURL(url);
66
66
  if (currentStyleSheet.length === 0) {
67
67
  throw new Error('Can\'t find style sheet ID for current URL');
@@ -7,10 +7,12 @@ import * as i18n from '../../core/i18n/i18n.js';
7
7
  import * as Root from '../../core/root/root.js';
8
8
  import * as Persistence from '../../models/persistence/persistence.js';
9
9
  import * as Workspace from '../../models/workspace/workspace.js';
10
+ import * as Highlighting from '../../ui/components/highlighting/highlighting.js';
10
11
  import * as QuickOpen from '../../ui/legacy/components/quick_open/quick_open.js';
11
12
  import * as UI from '../../ui/legacy/legacy.js';
12
13
 
13
14
  import {FilePathScoreFunction} from './FilePathScoreFunction.js';
15
+ import filteredUISourceCodeListProviderStyles from './filteredUISourceCodeListProvider.css.js';
14
16
 
15
17
  const UIStrings = {
16
18
  /**
@@ -143,8 +145,13 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg
143
145
  return score + multiplier * (contentTypeBonus + this.scorer.calculateScore(fullDisplayName, null));
144
146
  }
145
147
 
146
- override renderItem(itemIndex: number, query: string, titleElement: Element, subtitleElement: Element): void {
147
- titleElement.parentElement?.parentElement?.classList.toggle('search-mode', Boolean(query));
148
+ override renderItem(itemIndex: number, query: string, wrapperElement: Element): void {
149
+ wrapperElement.createChild('style').textContent = filteredUISourceCodeListProviderStyles;
150
+ const itemElement = wrapperElement.createChild('div', 'filtered-ui-source-code-list-item');
151
+
152
+ const titleElement = itemElement.createChild('div', 'filtered-ui-source-code-title');
153
+
154
+ titleElement.classList.toggle('search-mode', Boolean(query));
148
155
  query = this.rewriteQuery(query);
149
156
  const uiSourceCode = this.uiSourceCodes[itemIndex];
150
157
  const fullDisplayName = uiSourceCode.fullDisplayName();
@@ -157,11 +164,12 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg
157
164
  let tooltipText = fullDisplayName;
158
165
 
159
166
  if (isIgnoreListed) {
160
- titleElement.parentElement?.classList.add('is-ignore-listed');
167
+ itemElement.classList.add('is-ignore-listed');
161
168
  tooltipText = i18nString(UIStrings.sIgnoreListed, {PH1: tooltipText});
162
169
  }
163
170
 
164
171
  titleElement.textContent = uiSourceCode.displayName() + (this.queryLineNumberAndColumnNumber || '');
172
+ const subtitleElement = itemElement.createChild('div', 'filtered-ui-source-code-subtitle');
165
173
  this.renderSubtitleElement(subtitleElement, fullDisplayName.substring(0, fileNameIndex + 1));
166
174
  UI.Tooltip.Tooltip.install((subtitleElement as HTMLElement), tooltipText);
167
175
 
@@ -174,9 +182,9 @@ export class FilteredUISourceCodeListProvider extends QuickOpen.FilteredListWidg
174
182
  for (let i = 0; i < ranges.length; ++i) {
175
183
  ranges[i].offset -= fileNameIndex + 1;
176
184
  }
177
- UI.UIUtils.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
185
+ Highlighting.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
178
186
  } else {
179
- UI.UIUtils.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
187
+ Highlighting.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
180
188
  }
181
189
  }
182
190
 
@@ -77,9 +77,11 @@ export class GoToLineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
77
77
  return this.#goToLineStrings.length;
78
78
  }
79
79
 
80
- override renderItem(itemIndex: number, _query: string, titleElement: Element, _subtitleElement: Element): void {
80
+ override renderItem(itemIndex: number, _query: string, wrapperElement: Element): void {
81
+ const itemElement = wrapperElement.createChild('div');
82
+ const titleElement = itemElement.createChild('div');
81
83
  const icon = IconButton.Icon.create('colon');
82
- titleElement.parentElement?.parentElement?.insertBefore(icon, titleElement.parentElement);
84
+ wrapperElement.insertBefore(icon, itemElement);
83
85
  UI.UIUtils.createTextChild(titleElement, this.#goToLineStrings[itemIndex]);
84
86
  }
85
87
 
@@ -819,9 +819,9 @@ export class NavigatorView extends UI.Widget.VBox implements SDK.TargetManager.O
819
819
  }
820
820
  if (this.scriptsTree.selectedTreeElement) {
821
821
  // If the tree outline is being marked as "being edited" (i.e. we're renaming a file
822
- // or chosing the name for a new snippet), we shall not proceed with revealing here,
822
+ // or choosing the name for a new snippet), we shall not proceed with revealing here,
823
823
  // as that will steal focus from the input widget and thus cancel editing. The
824
- // test/e2e/snippets/breakpoint_test.ts exercises this.
824
+ // test/e2e/snippets/breakpoint.test.ts exercises this.
825
825
  if (UI.UIUtils.isBeingEdited(this.scriptsTree.selectedTreeElement.treeOutline?.element)) {
826
826
  return null;
827
827
  }
@@ -40,9 +40,12 @@ export class OpenFileQuickOpen extends FilteredUISourceCodeListProvider {
40
40
  return !project.isServiceProject();
41
41
  }
42
42
 
43
- override renderItem(itemIndex: number, query: string, titleElement: Element, subtitleElement: Element): void {
44
- super.renderItem(itemIndex, query, titleElement, subtitleElement);
45
-
43
+ override renderItem(itemIndex: number, query: string, wrapperElement: Element): void {
44
+ super.renderItem(itemIndex, query, wrapperElement);
45
+ const itemElement = wrapperElement.firstChild;
46
+ if (!itemElement) {
47
+ return;
48
+ }
46
49
  const iconElement = new IconButton.Icon.Icon();
47
50
  const {iconName, color} = PanelUtils.iconDataForResourceType(this.itemContentTypeAt(itemIndex));
48
51
  iconElement.name = iconName;
@@ -50,10 +53,6 @@ export class OpenFileQuickOpen extends FilteredUISourceCodeListProvider {
50
53
  iconElement.style.color = color;
51
54
  }
52
55
  iconElement.classList.add('large');
53
- titleElement.parentElement?.parentElement?.insertBefore(iconElement, titleElement.parentElement);
54
- }
55
-
56
- override renderAsTwoRows(): boolean {
57
- return true;
56
+ wrapperElement.insertBefore(iconElement, itemElement);
58
57
  }
59
58
  }
@@ -317,10 +317,13 @@ export class OutlineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
317
317
  return -item.lineNumber - 1;
318
318
  }
319
319
 
320
- override renderItem(itemIndex: number, query: string, titleElement: Element, _subtitleElement: Element): void {
320
+ override renderItem(itemIndex: number, query: string, wrapperElement: Element): void {
321
321
  const item = this.items[itemIndex];
322
+ const itemElement = wrapperElement.createChild('div');
323
+ const titleElement = itemElement.createChild('div');
324
+
322
325
  const icon = IconButton.Icon.create('deployed');
323
- titleElement.parentElement?.parentElement?.insertBefore(icon, titleElement.parentElement);
326
+ wrapperElement.insertBefore(icon, itemElement);
324
327
  titleElement.textContent = item.title + (item.subtitle ? item.subtitle : '');
325
328
  QuickOpen.FilteredListWidget.FilteredListWidget.highlightRanges(titleElement, query);
326
329
 
@@ -329,7 +332,7 @@ export class OutlineQuickOpen extends QuickOpen.FilteredListWidget.Provider {
329
332
  return;
330
333
  }
331
334
 
332
- const tagElement = titleElement.parentElement?.parentElement?.createChild('span', 'tag');
335
+ const tagElement = wrapperElement.createChild('span', 'tag');
333
336
  if (!tagElement) {
334
337
  return;
335
338
  }
@@ -8,6 +8,7 @@ import * as Platform from '../../core/platform/platform.js';
8
8
  import * as Workspace from '../../models/workspace/workspace.js';
9
9
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
10
10
  import type * as TextEditor from '../../ui/components/text_editor/text_editor.js';
11
+ import type * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
11
12
 
12
13
  import {Plugin} from './Plugin.js';
13
14
 
@@ -89,20 +90,16 @@ class PerformanceMarker extends CodeMirror.GutterMarker {
89
90
  }
90
91
 
91
92
  function markersFromProfileData(
92
- map: Map<number, number>|Map<number, Map<number, number>>, state: CodeMirror.EditorState,
93
+ map: Workspace.UISourceCode.LineColumnProfileMap, state: CodeMirror.EditorState,
93
94
  type: Workspace.UISourceCode.DecoratorType): CodeMirror.RangeSet<CodeMirror.GutterMarker> {
94
95
  const markerType = type === Workspace.UISourceCode.DecoratorType.PERFORMANCE ? PerformanceMarker : MemoryMarker;
95
96
  const markers: Array<CodeMirror.Range<CodeMirror.GutterMarker>> = [];
96
97
  const aggregatedByLine = new Map<number, number>();
97
98
  for (const [line, value] of map) {
98
99
  if (line <= state.doc.lines) {
99
- if (value instanceof Map) {
100
- for (const [, data] of value) {
101
- aggregatedByLine.set(line, (aggregatedByLine.get(line) || 0) + data);
102
- }
103
- continue;
100
+ for (const [, data] of value) {
101
+ aggregatedByLine.set(line, (aggregatedByLine.get(line) || 0) + data);
104
102
  }
105
- aggregatedByLine.set(line, value);
106
103
  }
107
104
  }
108
105
  for (const [line, value] of aggregatedByLine) {
@@ -112,13 +109,15 @@ function markersFromProfileData(
112
109
  return CodeMirror.RangeSet.of(markers, true);
113
110
  }
114
111
 
115
- const makeLineLevelProfilePlugin = (type: Workspace.UISourceCode.DecoratorType): typeof Plugin => class extends Plugin {
116
- updateEffect = CodeMirror.StateEffect.define<Map<number, number>|Map<number, Map<number, number>>>();
112
+ const makeLineLevelProfilePlugin = (type: Workspace.UISourceCode.DecoratorType): typeof Plugin =>
113
+ class ProfilePlugin extends Plugin {
114
+ updateEffect = CodeMirror.StateEffect.define<Workspace.UISourceCode.LineColumnProfileMap>();
117
115
  field: CodeMirror.StateField<CodeMirror.RangeSet<CodeMirror.GutterMarker>>;
118
116
  gutter: CodeMirror.Extension;
119
117
  compartment: CodeMirror.Compartment = new CodeMirror.Compartment();
118
+ readonly #transformer: SourceFrame.SourceFrame.Transformer;
120
119
 
121
- constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode) {
120
+ constructor(uiSourceCode: Workspace.UISourceCode.UISourceCode, transformer: SourceFrame.SourceFrame.Transformer) {
122
121
  super(uiSourceCode);
123
122
 
124
123
  this.field = CodeMirror.StateField.define<CodeMirror.RangeSet<CodeMirror.GutterMarker>>({
@@ -136,14 +135,24 @@ const makeLineLevelProfilePlugin = (type: Workspace.UISourceCode.DecoratorType):
136
135
  markers: view => view.state.field(this.field),
137
136
  class: `cm-${type}Gutter`,
138
137
  });
138
+
139
+ this.#transformer = transformer;
139
140
  }
140
141
 
141
142
  static override accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
142
143
  return uiSourceCode.contentType().hasScripts();
143
144
  }
144
145
 
145
- private getLineMap(): Map<number, number>|Map<number, Map<number, number>>|undefined {
146
- return this.uiSourceCode.getDecorationData(type);
146
+ private getLineMap(): Workspace.UISourceCode.LineColumnProfileMap|undefined {
147
+ const uiSourceCodeProfileMap = this.uiSourceCode.getDecorationData(type);
148
+ if (!uiSourceCodeProfileMap) {
149
+ return undefined;
150
+ }
151
+
152
+ return Workspace.UISourceCode.createMappedProfileData(uiSourceCodeProfileMap, (line, column) => {
153
+ const editorLocation = this.#transformer.uiLocationToEditorLocation(line, column);
154
+ return [editorLocation.lineNumber, editorLocation.columnNumber];
155
+ });
147
156
  }
148
157
 
149
158
  override editorExtension(): CodeMirror.Extension {
@@ -238,7 +238,6 @@ export class UISourceCodeFrame extends Common.ObjectWrapper
238
238
  }
239
239
 
240
240
  override async setContent(content: string): Promise<void> {
241
- this.#uiSourceCode.formatChanged(this.formattedMap);
242
241
  this.disposePlugins();
243
242
  this.loadPlugins();
244
243
  await super.setContent(content);
@@ -0,0 +1,41 @@
1
+ /*
2
+ * Copyright 2025 The Chromium Authors
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ .filtered-list-widget-item > .filtered-ui-source-code-list-item {
8
+ align-content: center;
9
+ display: grid;
10
+ gap: var(--sys-size-2);
11
+ line-height: initial;
12
+ }
13
+
14
+ .filtered-ui-source-code-list-item.is-ignore-listed * {
15
+ color: var(--sys-color-state-disabled);
16
+ }
17
+
18
+ .filtered-ui-source-code-title {
19
+ overflow: hidden;
20
+ text-overflow: ellipsis;
21
+ }
22
+
23
+ .filtered-ui-source-code-title:not(.search-mode) {
24
+ font-weight: var(--ref-typeface-weight-bold);
25
+ }
26
+
27
+ .filtered-ui-source-code-subtitle {
28
+ flex: none;
29
+ overflow: hidden;
30
+ text-overflow: ellipsis;
31
+ color: var(--sys-color-on-surface-subtle);
32
+ padding-left: var(--sys-size-3);
33
+ display: flex;
34
+ white-space: pre;
35
+ }
36
+
37
+ .filtered-ui-source-code-subtitle .first-part {
38
+ flex-shrink: 1000;
39
+ overflow: hidden;
40
+ text-overflow: ellipsis;
41
+ }
@@ -2105,8 +2105,6 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2105
2105
  }
2106
2106
 
2107
2107
  Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager);
2108
- // Clear the line level profile that could exist from the previous trace.
2109
- PerfUI.LineLevelProfile.Performance.instance().reset();
2110
2108
 
2111
2109
  this.#minimapComponent.reset();
2112
2110
 
@@ -2164,20 +2162,15 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2164
2162
  this.flameChart.bulkAddOverlays(currModificationManager.getOverlays());
2165
2163
  }
2166
2164
 
2167
- // Set up line level profiling with CPU profiles, if we found any.
2168
- PerfUI.LineLevelProfile.Performance.instance().reset();
2169
- if (parsedTrace.data.Samples.profilesInProcess.size) {
2170
- const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
2171
- // Gather up all CPU Profiles we found when parsing this trace.
2172
- const cpuProfiles =
2173
- Array.from(parsedTrace.data.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => {
2174
- const profiles = Array.from(threadsInProcess.values()).map(profileData => profileData.parsedProfile);
2175
- return profiles;
2176
- });
2177
- for (const profile of cpuProfiles) {
2178
- PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(profile, primaryPageTarget);
2179
- }
2180
- }
2165
+ // Set up line level profiling with CPU profiles.
2166
+ const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
2167
+ // Gather up all CPU Profiles we found when parsing this trace.
2168
+ const cpuProfiles =
2169
+ Array.from(parsedTrace.data.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => {
2170
+ const profiles = Array.from(threadsInProcess.values()).map(profileData => profileData.parsedProfile);
2171
+ return profiles;
2172
+ });
2173
+ PerfUI.LineLevelProfile.Performance.instance().initialize(cpuProfiles, primaryPageTarget);
2181
2174
 
2182
2175
  // Initialize EntityMapper
2183
2176
  this.#entityMapper = new Trace.EntityMapper.EntityMapper(parsedTrace);
@@ -2650,6 +2643,7 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2650
2643
  initiatorUrl: script.url as Platform.DevToolsPath.UrlString
2651
2644
  };
2652
2645
  rawSourceMap = await SDK.SourceMapManager.tryLoadSourceMap(
2646
+ SDK.PageResourceLoader.PageResourceLoader.instance(),
2653
2647
  script.sourceMapUrl as Platform.DevToolsPath.UrlString, initiator);
2654
2648
  }
2655
2649
 
@@ -2747,8 +2741,13 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2747
2741
  // non-final navigations during the trace will never have their source maps
2748
2742
  // fetched by the debugger model. That's only ever done here.
2749
2743
 
2750
- const initiator = {target: null, frameId: frame, initiatorUrl: sourceUrl};
2751
- const payload = await SDK.SourceMapManager.tryLoadSourceMap(sourceMapUrl, initiator);
2744
+ const initiator = {
2745
+ target: debuggerModelForFrameId.get(frame)?.target() ?? null,
2746
+ frameId: frame,
2747
+ initiatorUrl: sourceUrl
2748
+ };
2749
+ const payload = await SDK.SourceMapManager.tryLoadSourceMap(
2750
+ SDK.PageResourceLoader.PageResourceLoader.instance(), sourceMapUrl, initiator);
2752
2751
  return payload ? new SDK.SourceMap.SourceMap(sourceUrl, sourceMapUrl, payload) : null;
2753
2752
  };
2754
2753
  }
@@ -235,7 +235,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
235
235
  const nonMatches = timing[SelectorTimingsKey.MatchAttempts] - timing[SelectorTimingsKey.MatchCount];
236
236
  const slowPathNonMatches =
237
237
  (nonMatches ? 1.0 - timing[SelectorTimingsKey.FastRejectCount] / nonMatches : 0) * 100;
238
- const styleSheetId = timing[SelectorTimingsKey.StyleSheetId] as Protocol.CSS.StyleSheetId;
238
+ const styleSheetId = timing[SelectorTimingsKey.StyleSheetId] as Protocol.DOM.StyleSheetId;
239
239
  let linkData = '';
240
240
  const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
241
241
  const cssModel = target?.model(SDK.CSSModel.CSSModel);
@@ -462,7 +462,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
462
462
 
463
463
  private async processSelectorTimings(timings: Trace.Types.Events.SelectorTiming[]): Promise<SelectorTiming[]> {
464
464
  async function toSourceFileLocation(
465
- cssModel: SDK.CSSModel.CSSModel, styleSheetId: Protocol.CSS.StyleSheetId, selectorText: string,
465
+ cssModel: SDK.CSSModel.CSSModel, styleSheetId: Protocol.DOM.StyleSheetId, selectorText: string,
466
466
  selectorLocations: Map<string, Protocol.CSS.SourceRange[]>):
467
467
  Promise<Linkifier.Linkifier.LinkifierData[]|undefined> {
468
468
  if (!cssModel) {
@@ -505,7 +505,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox {
505
505
 
506
506
  return await Promise.all(
507
507
  timings.sort((a, b) => b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed]).map(async x => {
508
- const styleSheetId = x[SelectorTimingsKey.StyleSheetId] as Protocol.CSS.StyleSheetId;
508
+ const styleSheetId = x[SelectorTimingsKey.StyleSheetId] as Protocol.DOM.StyleSheetId;
509
509
  const selectorText = x[SelectorTimingsKey.Selector].trim();
510
510
  const locations = styleSheetId === 'n/a' ?
511
511
  null :
@@ -35,7 +35,7 @@ export class SlowCSSSelector extends BaseInsightComponent<SlowCSSSelectorInsight
35
35
  if (!cssModel) {
36
36
  return undefined;
37
37
  }
38
- const styleSheetHeader = cssModel.styleSheetHeaderForId(selector.style_sheet_id as Protocol.CSS.StyleSheetId);
38
+ const styleSheetHeader = cssModel.styleSheetHeaderForId(selector.style_sheet_id as Protocol.DOM.StyleSheetId);
39
39
  if (!styleSheetHeader?.resourceURL()) {
40
40
  return undefined;
41
41
  }
@@ -45,7 +45,7 @@ export class SlowCSSSelector extends BaseInsightComponent<SlowCSSSelectorInsight
45
45
  let ranges = this.#selectorLocations.get(key);
46
46
  if (!ranges) {
47
47
  const result = await cssModel.agent.invoke_getLocationForSelector(
48
- {selectorText: selector.selector, styleSheetId: selector.style_sheet_id as Protocol.CSS.StyleSheetId});
48
+ {selectorText: selector.selector, styleSheetId: selector.style_sheet_id as Protocol.DOM.StyleSheetId});
49
49
  if (result.getError() || !result.ranges) {
50
50
  return undefined;
51
51
  }
@@ -16,21 +16,20 @@ Flame chart data providers have two jobs:
16
16
 
17
17
  The main flame chart is currently being migrated to use the data of the new engine. This migration is supposed to be done on a track by track basis (https://crbug.com/1416533).
18
18
 
19
-
20
19
  ## Migrating a track from the main flame chart to use the new engine
21
20
 
22
21
  Migrating a track consists of taking the code in the data provider corresponding to a track (both the appending into the flame chart data and the handling of extra features) and moving it to a dedicated "track appender". Generally this boils down to these steps (note that steps 3 - 6 must be implemented together in the same change):
23
22
 
24
- 0. Add screenshot tests for the track. In order to ensure no regressions are introduced after a migration we use screenshot tests for expanded and collapsed track. See for example the [gpu_track_test](../../../test/interactions/panels/performance/timeline/gpu_track_test.ts).
23
+ 0. Add screenshot tests for the track. In order to ensure no regressions are introduced after a migration we use screenshot tests for expanded and collapsed track. See for example the [gpu_track_test](../../../test/interactions/panels/performance/timeline/gpu_track.test.ts).
25
24
 
26
- After adding the test file, you can run `npm run auto-screenshotstest` to generate the screenshot locally to check before submitting.
25
+ After adding the test file, you can run `npm run auto-screenshotstest` to generate the screenshot locally to check before submitting.
27
26
 
28
- Or you can upload to the Gerrit and after the screenshot tests fails, run `./scripts/tools/update_goldens.py` to update the screenshots.
29
- See [update_goldens.py](../../../scripts/tools/update_goldens.py) for more information.
27
+ Or you can upload to the Gerrit and after the screenshot tests fails, run `./scripts/tools/update_goldens.py` to update the screenshots.
28
+ See [update_goldens.py](../../../scripts/tools/update_goldens.py) for more information.
30
29
 
31
30
  1. Add missing related functionality to the new engine (not always needed).
32
31
 
33
- Whatever's needed to support using the new engine as source of data for the track being migrated. This could mean adding a new handler or buffering/exporting a new kind of event in a particular handler, for example.
32
+ Whatever's needed to support using the new engine as source of data for the track being migrated. This could mean adding a new handler or buffering/exporting a new kind of event in a particular handler, for example.
34
33
 
35
34
  2. Define a new appender for the track being migrated. Make sure the class implements the `CompatibilityTracksAppender.TrackAppender` interface. See for example the [TimingsTrackAppender](TimingsTrackAppender.ts).
36
35
 
@@ -38,24 +37,20 @@ Migrating a track consists of taking the code in the data provider corresponding
38
37
 
39
38
  4. Move the appending of the data track in the data provider into the new track appender:
40
39
 
41
- The data appending happens at the [appendLegacyTrackData method](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/TimelineFlameChartDataProvider.ts;l=528). The implementation for each track should be under the switch case with the track being migrated.
40
+ The data appending happens at the [appendLegacyTrackData method](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/TimelineFlameChartDataProvider.ts;l=528). The implementation for each track should be under the switch case with the track being migrated.
42
41
 
43
- The appending is usually the result of calling `appendSyncEvents` and/or `appendAsyncEventsGroup`. These two methods are commonly shared across tracks in the legacy system, and as such contain the handling of particular details of all tracks, which makes them very complex. To migrate a track to the new system, you will have to inspect the code paths invoked to append a track in the legacy system and extract them. The extracted code should be re-implemented in a functionally-equivalent way under the `appendTrackAtLevel` method implementation of the new track appender.
42
+ The appending is usually the result of calling `appendSyncEvents` and/or `appendAsyncEventsGroup`. These two methods are commonly shared across tracks in the legacy system, and as such contain the handling of particular details of all tracks, which makes them very complex. To migrate a track to the new system, you will have to inspect the code paths invoked to append a track in the legacy system and extract them. The extracted code should be re-implemented in a functionally-equivalent way under the `appendTrackAtLevel` method implementation of the new track appender.
44
43
 
45
- Note that there might be similarities in the way multiple track appenders "append" their data, in that case it would make sense to introduce new helpers that are shared between appenders to prevent code duplication.
44
+ Note that there might be similarities in the way multiple track appenders "append" their data, in that case it would make sense to introduce new helpers that are shared between appenders to prevent code duplication.
46
45
 
47
46
  5. Move the handling of the extra features.
48
47
 
49
- This is usually achieved by implementing the methods `colorForEvent`, `titleForEvent` and `popoverInfo`. Note how The implementation of these methods should be equivalent to the codepaths of the methods with the same names in the data provider related to the tracks/events being migrated. Here again we should look out for opportunities to introduce helpers to share between track appenders.
48
+ This is usually achieved by implementing the methods `colorForEvent`, `titleForEvent` and `popoverInfo`. Note how The implementation of these methods should be equivalent to the codepaths of the methods with the same names in the data provider related to the tracks/events being migrated. Here again we should look out for opportunities to introduce helpers to share between track appenders.
50
49
 
51
- Note: Queries done by the FlameChart renderer for events' extra features are passed from the data provider to the CompatibilityTracksAppender ([see example](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/TimelineFlameChartDataProvider.ts;l=1083)), which then [forwards](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/CompatibilityTracksAppender.ts;l=107) the query to the appropriate track appender.
50
+ Note: Queries done by the FlameChart renderer for events' extra features are passed from the data provider to the CompatibilityTracksAppender ([see example](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/TimelineFlameChartDataProvider.ts;l=1083)), which then [forwards](https://source.chromium.org/chromium/_/chromium/devtools/devtools-frontend/+/3925b7d73681966c9a8c844c49c7e815ecdcff82:front_end/panels/timeline/CompatibilityTracksAppender.ts;l=107) the query to the appropriate track appender.
52
51
 
53
52
  6. Look for any remaining references to the track, or events in the track being migrated, throughout [TimelineFlameChartDataProvider.ts](TimelineFlameChartDataProvider.ts). Make sure they have an equivalent in the new system and that it would be invoked at the same time as it was before the migration. There is no more specific rule that can be followed: each track needs to be checked independently.
54
53
 
55
-
56
54
  ### Things to look out for:
57
55
 
58
- * Timings: Trace events in the new engine uses raw timestamps coming from a trace. This means the new engine uses **microseconds**. However, most features in the panel use **milliseconds**. Make sure you make the appropriate time conversion when appending new tracks.
59
-
60
-
61
-
56
+ - Timings: Trace events in the new engine uses raw timestamps coming from a trace. This means the new engine uses **microseconds**. However, most features in the panel use **milliseconds**. Make sure you make the appropriate time conversion when appending new tracks.
@@ -42,6 +42,16 @@ const UIStrings = {
42
42
  * @example {3G} PH2
43
43
  */
44
44
  resourceTypeWithThrottling: '{PH1} (throttled to {PH2})',
45
+ /**
46
+ * @description Tooltip for a failed request
47
+ * @example {Document} PH1
48
+ */
49
+ requestFailed: '{PH1} request failed',
50
+ /**
51
+ * @description Tooltip for a failed request
52
+ * @example {Document} PH1
53
+ */
54
+ prefetchFailed: '{PH1} prefetch request failed',
45
55
  } as const;
46
56
 
47
57
  const str_ = i18n.i18n.registerUIStrings('panels/utils/utils.ts', UIStrings);
@@ -74,16 +84,19 @@ export class PanelUtils {
74
84
 
75
85
  if (PanelUtils.isFailedNetworkRequest(request)) {
76
86
  let iconName: string;
87
+ let title: string;
77
88
  // Failed prefetch network requests are displayed as warnings instead of errors.
78
89
  if (request.resourceType() === Common.ResourceType.resourceTypes.Prefetch) {
90
+ title = i18nString(UIStrings.prefetchFailed, {PH1: type.title()});
79
91
  iconName = 'warning-filled';
80
92
  } else {
93
+ title = i18nString(UIStrings.requestFailed, {PH1: type.title()});
81
94
  iconName = 'cross-circle-filled';
82
95
  }
83
96
 
84
97
  // clang-format off
85
98
  return html`<devtools-icon
86
- class="icon" name=${iconName} title=${type.title()}>
99
+ class="icon" name=${iconName} title=${title}> role=img
87
100
  </devtools-icon>`;
88
101
  // clang-format on
89
102
  }
@@ -93,6 +106,7 @@ export class PanelUtils {
93
106
  return html`<devtools-icon
94
107
  class="icon"
95
108
  name="warning-filled"
109
+ role=img
96
110
  title=${i18nString(UIStrings.thirdPartyPhaseout)}
97
111
  ></devtools-icon>`;
98
112
  // clang-format on
@@ -112,7 +126,7 @@ export class PanelUtils {
112
126
 
113
127
  // clang-format off
114
128
  return html`<div class="network-override-marker">
115
- <devtools-icon class="icon" name="document" title=${title}></devtools-icon>
129
+ <devtools-icon class="icon" name="document" role=img title=${title}></devtools-icon>
116
130
  </div>`;
117
131
  // clang-format on
118
132
  }
@@ -149,7 +163,7 @@ export class PanelUtils {
149
163
  Common.ResourceType.ResourceType.simplifyContentType(request.mimeType) === 'application/json') {
150
164
  // clang-format off
151
165
  return html`<devtools-icon
152
- class="icon" name="file-json" title=${iconTitleForRequest(request)}
166
+ class="icon" name="file-json" title=${iconTitleForRequest(request)} role=img
153
167
  style="color:var(--icon-file-script)">
154
168
  </devtools-icon>`;
155
169
  // clang-format on