chrome-devtools-frontend 1.0.1556696 → 1.0.1559913

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 (201) hide show
  1. package/front_end/Images/src/container.svg +4 -0
  2. package/front_end/core/common/Gzip.ts +15 -0
  3. package/front_end/core/common/Object.ts +5 -1
  4. package/front_end/core/host/ResourceLoader.ts +1 -1
  5. package/front_end/core/host/UserMetrics.ts +3 -1
  6. package/front_end/core/sdk/CSSMetadata.ts +6 -6
  7. package/front_end/core/sdk/CSSModel.ts +2 -2
  8. package/front_end/core/sdk/DOMModel.ts +14 -3
  9. package/front_end/core/sdk/NetworkManager.ts +0 -7
  10. package/front_end/core/sdk/SourceMap.ts +16 -2
  11. package/front_end/core/sdk/SourceMapManager.ts +1 -1
  12. package/front_end/core/sdk/SourceMapScopesInfo.ts +11 -4
  13. package/front_end/entrypoints/formatter_worker/FormatterActions.ts +1 -0
  14. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +51 -8
  15. package/front_end/entrypoints/main/GlobalAiButton.ts +5 -1
  16. package/front_end/generated/Deprecation.ts +0 -7
  17. package/front_end/generated/InspectorBackendCommands.ts +5 -4
  18. package/front_end/generated/SupportedCSSProperties.js +64 -32
  19. package/front_end/generated/protocol-mapping.d.ts +9 -0
  20. package/front_end/generated/protocol-proxy-api.d.ts +7 -0
  21. package/front_end/generated/protocol.ts +23 -1
  22. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
  23. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +11 -7
  24. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +3 -3
  25. package/front_end/models/bindings/CompilerScriptMapping.ts +7 -6
  26. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +4 -4
  27. package/front_end/models/javascript_metadata/NativeFunctions.js +2 -2
  28. package/front_end/models/stack_trace/StackTraceImpl.ts +5 -3
  29. package/front_end/models/stack_trace/StackTraceModel.ts +53 -40
  30. package/front_end/models/trace/EventsSerializer.ts +8 -2
  31. package/front_end/models/trace/LanternComputationData.ts +4 -3
  32. package/front_end/models/trace/Processor.ts +6 -5
  33. package/front_end/models/trace/Styles.ts +10 -1
  34. package/front_end/models/trace/handlers/LargestImagePaintHandler.ts +2 -2
  35. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +2 -2
  36. package/front_end/models/trace/handlers/MetaHandler.ts +14 -0
  37. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +54 -34
  38. package/front_end/models/trace/helpers/Timing.ts +8 -1
  39. package/front_end/models/trace/insights/Common.ts +1 -1
  40. package/front_end/models/trace/insights/LCPBreakdown.ts +4 -4
  41. package/front_end/models/trace/insights/LCPDiscovery.ts +3 -3
  42. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  43. package/front_end/models/trace/insights/types.ts +1 -1
  44. package/front_end/models/trace/types/TraceEvents.ts +62 -10
  45. package/front_end/panels/application/AppManifestView.ts +134 -223
  46. package/front_end/panels/application/CookieItemsView.ts +1 -0
  47. package/front_end/panels/application/SharedStorageTreeElement.ts +3 -0
  48. package/front_end/panels/application/appManifestView.css +1 -1
  49. package/front_end/panels/common/AiCodeGenerationTeaser.ts +48 -12
  50. package/front_end/panels/common/aiCodeGenerationTeaser.css +14 -0
  51. package/front_end/panels/common/common.ts +1 -1
  52. package/front_end/panels/console/ConsoleViewMessage.ts +4 -3
  53. package/front_end/panels/console/consoleView.css +1 -1
  54. package/front_end/panels/elements/CSSRuleValidator.ts +38 -0
  55. package/front_end/panels/elements/ElementsTreeElement.ts +108 -58
  56. package/front_end/panels/elements/ElementsTreeOutline.ts +0 -17
  57. package/front_end/panels/elements/ElementsTreeOutlineRenderer.ts +7 -1
  58. package/front_end/panels/elements/StylesSidebarPane.ts +15 -4
  59. package/front_end/panels/elements/components/AdornerManager.ts +8 -0
  60. package/front_end/panels/emulation/DeviceModeToolbar.ts +3 -1
  61. package/front_end/panels/issues/AffectedResourcesView.ts +0 -1
  62. package/front_end/panels/lighthouse/LighthousePanel.ts +10 -0
  63. package/front_end/panels/lighthouse/lighthousePanel.css +46 -3
  64. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -9
  65. package/front_end/panels/network/RequestCookiesView.ts +125 -141
  66. package/front_end/panels/network/components/RequestHeadersView.ts +2 -2
  67. package/front_end/panels/network/requestCookiesView.css +22 -20
  68. package/front_end/panels/recorder/components/RecordingView.ts +3 -3
  69. package/front_end/panels/recorder/components/StepView.ts +2 -1
  70. package/front_end/panels/settings/keybindsSettingsTab.css +4 -0
  71. package/front_end/panels/sources/CallStackSidebarPane.ts +7 -3
  72. package/front_end/panels/sources/DebuggerPausedMessage.ts +125 -90
  73. package/front_end/panels/sources/SourcesPanel.ts +10 -7
  74. package/front_end/panels/sources/debuggerPausedMessage.css +8 -0
  75. package/front_end/panels/timeline/StatusDialog.ts +4 -3
  76. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +3 -16
  77. package/front_end/panels/timeline/TimelineFlameChartView.ts +64 -21
  78. package/front_end/panels/timeline/TimelinePanel.ts +71 -24
  79. package/front_end/panels/timeline/TimelineUIUtils.ts +28 -2
  80. package/front_end/panels/timeline/TimingsTrackAppender.ts +3 -1
  81. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  82. package/front_end/panels/timeline/components/insights/RenderBlocking.ts +6 -4
  83. package/front_end/panels/timeline/components/sidebarInsightsTab.css +2 -0
  84. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +4 -0
  85. package/front_end/panels/timeline/timelinePanel.css +8 -1
  86. package/front_end/panels/timeline/utils/EntryNodes.ts +2 -1
  87. package/front_end/third_party/acorn/estree-legacy.d.ts +2 -0
  88. package/front_end/third_party/chromium/README.chromium +1 -1
  89. package/front_end/third_party/puppeteer/README.chromium +2 -2
  90. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +12 -0
  91. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.js.map +1 -1
  93. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +14 -2
  94. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Browser.d.ts +3 -1
  97. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Browser.d.ts.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Browser.js +6 -0
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Browser.js.map +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts +0 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +0 -20
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +3 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +10 -14
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts +1 -0
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js +14 -0
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +3 -1
  113. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +12 -0
  115. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/EmulationManager.d.ts +1 -0
  117. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/EmulationManager.js +22 -0
  119. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/EmulationManager.js.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +3 -1
  121. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +9 -2
  123. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  126. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  127. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  129. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  131. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +26 -0
  132. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +72 -15
  133. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +12 -0
  134. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts.map +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js.map +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +14 -2
  137. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Browser.d.ts +3 -1
  140. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Browser.d.ts.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Browser.js +6 -0
  142. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Browser.js.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts +0 -1
  144. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +0 -20
  146. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
  147. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +3 -1
  148. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +11 -15
  150. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts +1 -0
  152. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  153. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js +14 -0
  154. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  155. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +3 -1
  156. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  157. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +12 -0
  158. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  159. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/EmulationManager.d.ts +1 -0
  160. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
  161. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/EmulationManager.js +22 -0
  162. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/EmulationManager.js.map +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +3 -1
  164. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  165. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +9 -2
  166. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  168. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  169. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  170. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  172. package/front_end/third_party/puppeteer/package/lib/types.d.ts +26 -0
  173. package/front_end/third_party/puppeteer/package/package.json +1 -1
  174. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +18 -0
  175. package/front_end/third_party/puppeteer/package/src/api/Page.ts +16 -2
  176. package/front_end/third_party/puppeteer/package/src/bidi/Browser.ts +13 -0
  177. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +0 -33
  178. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +14 -28
  179. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +19 -0
  180. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +19 -0
  181. package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +30 -0
  182. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +15 -6
  183. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  184. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  185. package/front_end/ui/components/icon_button/iconButton.css +3 -1
  186. package/front_end/ui/components/report_view/ReportView.ts +11 -2
  187. package/front_end/ui/components/report_view/report.css +16 -0
  188. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +202 -32
  189. package/front_end/ui/components/text_editor/config.ts +6 -6
  190. package/front_end/ui/legacy/ContextMenu.ts +11 -2
  191. package/front_end/ui/legacy/SearchableView.ts +11 -5
  192. package/front_end/ui/legacy/SplitWidget.ts +1 -1
  193. package/front_end/ui/legacy/TextPrompt.ts +1 -1
  194. package/front_end/ui/legacy/Toolbar.ts +4 -0
  195. package/front_end/ui/legacy/UIUtils.ts +0 -2
  196. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +18 -3
  197. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +3 -3
  198. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +6 -0
  199. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +43 -9
  200. package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
  201. package/package.json +1 -1
@@ -1,7 +1,6 @@
1
1
  // Copyright 2016 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-imperative-dom-api */
5
4
 
6
5
  import * as i18n from '../../core/i18n/i18n.js';
7
6
  import type * as Platform from '../../core/platform/platform.js';
@@ -10,14 +9,16 @@ import * as Protocol from '../../generated/protocol.js';
10
9
  import type * as Bindings from '../../models/bindings/bindings.js';
11
10
  import type * as BreakpointManager from '../../models/breakpoints/breakpoints.js';
12
11
  import * as uiI18n from '../../ui/i18n/i18n.js';
13
- import {Icon} from '../../ui/kit/kit.js';
14
12
  import * as UI from '../../ui/legacy/legacy.js';
13
+ import * as Lit from '../../ui/lit/lit.js';
15
14
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
16
15
  import * as PanelsCommon from '../common/common.js';
17
16
 
18
17
  import {getLocalizedBreakpointName} from './CategorizedBreakpointL10n.js';
19
18
  import debuggerPausedMessageStyles from './debuggerPausedMessage.css.js';
20
19
 
20
+ const {html, render, nothing, Directives: {ifDefined}} = Lit;
21
+
21
22
  const UIStrings = {
22
23
  /**
23
24
  * @description Text in the JavaScript Debugging pane of the Sources pane when a DOM breakpoint is hit
@@ -117,21 +118,79 @@ const str_ = i18n.i18n.registerUIStrings('panels/sources/DebuggerPausedMessage.t
117
118
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
118
119
  const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
119
120
 
120
- export class DebuggerPausedMessage {
121
- readonly #element: HTMLDivElement;
122
- private contentElement: HTMLElement;
123
- constructor() {
124
- this.#element = document.createElement('div');
125
- this.#element.classList.add('paused-message');
126
- this.#element.classList.add('flex-none');
127
- this.#element.setAttribute('jslog', `${VisualLogging.dialog('debugger-paused')}`);
128
- const root = UI.UIUtils.createShadowRootWithCoreStyles(this.#element, {cssFile: debuggerPausedMessageStyles});
129
- this.contentElement = root.createChild('div');
130
- UI.ARIAUtils.markAsPoliteLiveRegion(this.#element, false);
121
+ interface DOMBreakpointData {
122
+ type: Protocol.DOMDebugger.DOMBreakpointType;
123
+ node: SDK.DOMModel.DOMNode;
124
+ targetNode: SDK.DOMModel.DOMNode|null;
125
+ insertion: boolean;
126
+ }
127
+
128
+ interface ViewInput {
129
+ errorLike: boolean;
130
+ mainText: string;
131
+ subText?: string;
132
+ title?: string;
133
+ domBreakpointData?: DOMBreakpointData;
134
+ }
135
+
136
+ function domBreakpointSubtext(data: DOMBreakpointData): Lit.LitTemplate {
137
+ let messageElement: HTMLElement|undefined;
138
+ if (data.targetNode) {
139
+ const targetNodeLink = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(data.targetNode);
140
+ if (data.insertion) {
141
+ if (data.targetNode === data.node) {
142
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.childSAdded, {PH1: targetNodeLink});
143
+ } else {
144
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSAdded, {PH1: targetNodeLink});
145
+ }
146
+ } else {
147
+ messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSRemoved, {PH1: targetNodeLink});
148
+ }
131
149
  }
150
+ return html`
151
+ ${PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(data.node)}
152
+ ${data.targetNode ? html`<br/>${messageElement}` : nothing}
153
+ `;
154
+ }
155
+
156
+ const DEFAULT_VIEW = (input: ViewInput|null, _output: undefined, target: HTMLElement): void => {
157
+ render(
158
+ html`
159
+ <style>${debuggerPausedMessageStyles}</style>
160
+ <div aria-live="polite" ?hidden=${!input}>${
161
+ input ?
162
+ html`
163
+ <div class="paused-status ${input.errorLike ? 'error-reason' : ''}">
164
+ <span>
165
+ <div class="status-main">
166
+ <devtools-icon name=${input.errorLike ? 'cross-circle-filled' : 'info'} class="medium"></devtools-icon>
167
+ ${input.mainText}
168
+ </div>
169
+ ${
170
+ input.subText || input.domBreakpointData ?
171
+ html`
172
+ <div class="status-sub monospace" title=${ifDefined(input.title ?? input.subText)}>${
173
+ input.domBreakpointData ? domBreakpointSubtext(input.domBreakpointData) : input.subText}</div>
174
+ ` :
175
+ nothing}
176
+ </span>
177
+ </div>` :
178
+ nothing}
179
+ </div>
180
+ `,
181
+ target);
182
+ };
183
+
184
+ type View = typeof DEFAULT_VIEW;
132
185
 
133
- element(): Element {
134
- return this.#element;
186
+ export class DebuggerPausedMessage extends UI.Widget.Widget {
187
+ #viewInput: ViewInput|null = null;
188
+ constructor(element?: HTMLElement, private readonly view: View = DEFAULT_VIEW) {
189
+ super(element, {
190
+ jslog: `${VisualLogging.dialog('debugger-paused')}`,
191
+ classes: ['paused-message', 'flex-none'],
192
+ useShadowDom: true,
193
+ });
135
194
  }
136
195
 
137
196
  private static descriptionWithoutStack(description: string): string {
@@ -140,53 +199,30 @@ export class DebuggerPausedMessage {
140
199
  description.substring(0, description.lastIndexOf('\n'));
141
200
  }
142
201
 
143
- private static async createDOMBreakpointHitMessage(details: SDK.DebuggerModel.DebuggerPausedDetails):
144
- Promise<Element> {
145
- const messageWrapper = document.createElement('span');
202
+ private static async createDOMBreakpointHitMessageDetails(details: SDK.DebuggerModel.DebuggerPausedDetails):
203
+ Promise<ViewInput|null> {
146
204
  const domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel.DOMDebuggerModel);
147
205
  if (!details.auxData || !domDebuggerModel) {
148
- return messageWrapper;
206
+ return null;
149
207
  }
150
- const data = domDebuggerModel.resolveDOMBreakpointData((details.auxData as {
208
+ const domBreakpointData = domDebuggerModel.resolveDOMBreakpointData((details.auxData as {
151
209
  type: Protocol.DOMDebugger.DOMBreakpointType,
152
210
  nodeId: Protocol.DOM.NodeId,
153
211
  targetNodeId: Protocol.DOM.NodeId,
154
212
  insertion: boolean,
155
213
  }));
156
- if (!data) {
157
- return messageWrapper;
158
- }
159
214
 
160
- const mainElement = messageWrapper.createChild('div', 'status-main');
161
- const mainIcon = new Icon();
162
- mainIcon.name = 'info';
163
- mainIcon.style.color = 'var(--sys-color-on-yellow-container)';
164
- mainIcon.classList.add('medium');
165
- mainElement.appendChild(mainIcon);
166
- const breakpointType = BreakpointTypeNouns.get(data.type);
167
- mainElement.appendChild(document.createTextNode(
168
- i18nString(UIStrings.pausedOnS, {PH1: breakpointType ? breakpointType() : String(null)})));
215
+ if (!domBreakpointData) {
216
+ return null;
217
+ }
169
218
 
170
- const subElement = messageWrapper.createChild('div', 'status-sub monospace');
171
- const linkifiedNode = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(data.node);
172
- subElement.appendChild(linkifiedNode);
219
+ const breakpointType = BreakpointTypeNouns.get(domBreakpointData.type);
173
220
 
174
- if (data.targetNode) {
175
- const targetNodeLink = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(data.targetNode);
176
- let messageElement;
177
- if (data.insertion) {
178
- if (data.targetNode === data.node) {
179
- messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.childSAdded, {PH1: targetNodeLink});
180
- } else {
181
- messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSAdded, {PH1: targetNodeLink});
182
- }
183
- } else {
184
- messageElement = uiI18n.getFormatLocalizedString(str_, UIStrings.descendantSRemoved, {PH1: targetNodeLink});
185
- }
186
- subElement.appendChild(document.createElement('br'));
187
- subElement.appendChild(messageElement);
188
- }
189
- return messageWrapper;
221
+ return {
222
+ mainText: i18nString(UIStrings.pausedOnS, {PH1: breakpointType ? breakpointType() : String(null)}),
223
+ domBreakpointData,
224
+ errorLike: false,
225
+ };
190
226
  }
191
227
 
192
228
  static #findEventNameForUi(detailsAuxData?: SDK.DebuggerModel.EventListenerPausedDetailsAuxData): string {
@@ -223,86 +259,84 @@ export class DebuggerPausedMessage {
223
259
  details: SDK.DebuggerModel.DebuggerPausedDetails|null,
224
260
  debuggerWorkspaceBinding: Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding,
225
261
  breakpointManager: BreakpointManager.BreakpointManager.BreakpointManager): Promise<void> {
226
- this.contentElement.removeChildren();
227
- this.contentElement.hidden = !details;
228
262
  if (!details) {
263
+ this.#viewInput = null;
264
+ this.requestUpdate();
229
265
  return;
230
266
  }
231
267
 
232
- const status = this.contentElement.createChild('div', 'paused-status');
233
-
234
268
  const errorLike = details.reason === Protocol.Debugger.PausedEventReason.Exception ||
235
269
  details.reason === Protocol.Debugger.PausedEventReason.PromiseRejection ||
236
270
  details.reason === Protocol.Debugger.PausedEventReason.Assert ||
237
271
  details.reason === Protocol.Debugger.PausedEventReason.OOM;
238
- let messageWrapper;
272
+
239
273
  if (details.reason === Protocol.Debugger.PausedEventReason.DOM) {
240
- messageWrapper = await DebuggerPausedMessage.createDOMBreakpointHitMessage(details);
274
+ this.#viewInput = await DebuggerPausedMessage.createDOMBreakpointHitMessageDetails(details);
241
275
  } else if (details.reason === Protocol.Debugger.PausedEventReason.EventListener) {
242
276
  const eventNameForUI = DebuggerPausedMessage.#findEventNameForUi(
243
277
  details.auxData as SDK.DebuggerModel.EventListenerPausedDetailsAuxData);
244
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedOnEventListener), eventNameForUI);
278
+ this.#viewInput = {mainText: i18nString(UIStrings.pausedOnEventListener), subText: eventNameForUI, errorLike};
245
279
  } else if (details.reason === Protocol.Debugger.PausedEventReason.XHR) {
246
280
  const auxData = (details.auxData as PausedDetailsAuxData);
247
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedOnXhrOrFetch), auxData.url || '');
281
+ this.#viewInput = {mainText: i18nString(UIStrings.pausedOnXhrOrFetch), subText: auxData.url || '', errorLike};
248
282
  } else if (details.reason === Protocol.Debugger.PausedEventReason.Exception) {
249
283
  const auxData = (details.auxData as PausedDetailsAuxData);
250
284
  const description = auxData.description || auxData.value || '';
251
285
  const descriptionWithoutStack = DebuggerPausedMessage.descriptionWithoutStack(description);
252
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedOnException), descriptionWithoutStack, description);
286
+ this.#viewInput = {
287
+ mainText: i18nString(UIStrings.pausedOnException),
288
+ subText: descriptionWithoutStack,
289
+ title: description,
290
+ errorLike,
291
+ };
253
292
  } else if (details.reason === Protocol.Debugger.PausedEventReason.PromiseRejection) {
254
293
  const auxData = (details.auxData as PausedDetailsAuxData);
255
294
  const description = auxData.description || auxData.value || '';
256
295
  const descriptionWithoutStack = DebuggerPausedMessage.descriptionWithoutStack(description);
257
- messageWrapper =
258
- buildWrapper(i18nString(UIStrings.pausedOnPromiseRejection), descriptionWithoutStack, description);
296
+ this.#viewInput = {
297
+ mainText: i18nString(UIStrings.pausedOnPromiseRejection),
298
+ subText: descriptionWithoutStack,
299
+ title: description,
300
+ errorLike,
301
+ };
259
302
  } else if (details.reason === Protocol.Debugger.PausedEventReason.Assert) {
260
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedOnAssertion));
303
+ this.#viewInput = {mainText: i18nString(UIStrings.pausedOnAssertion), errorLike};
261
304
  } else if (details.reason === Protocol.Debugger.PausedEventReason.DebugCommand) {
262
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedOnDebuggedFunction));
305
+ this.#viewInput = {mainText: i18nString(UIStrings.pausedOnDebuggedFunction), errorLike};
263
306
  } else if (details.reason === Protocol.Debugger.PausedEventReason.OOM) {
264
- messageWrapper = buildWrapper(i18nString(UIStrings.pausedBeforePotentialOutofmemory));
307
+ this.#viewInput = {mainText: i18nString(UIStrings.pausedBeforePotentialOutofmemory), errorLike};
265
308
  } else if (
266
309
  details.reason === Protocol.Debugger.PausedEventReason.CSPViolation && details.auxData?.['violationType']) {
267
310
  const text = (details.auxData['violationType'] as string);
268
311
  if (text === Protocol.DOMDebugger.CSPViolationType.TrustedtypeSinkViolation) {
269
- messageWrapper =
270
- buildWrapper(i18nString(UIStrings.pausedOnCspViolation), i18nString(UIStrings.trustedTypeSinkViolation));
312
+ this.#viewInput = {
313
+ mainText: i18nString(UIStrings.pausedOnCspViolation),
314
+ subText: i18nString(UIStrings.trustedTypeSinkViolation),
315
+ errorLike,
316
+ };
271
317
  } else if (text === Protocol.DOMDebugger.CSPViolationType.TrustedtypePolicyViolation) {
272
- messageWrapper =
273
- buildWrapper(i18nString(UIStrings.pausedOnCspViolation), i18nString(UIStrings.trustedTypePolicyViolation));
318
+ this.#viewInput = {
319
+ mainText: i18nString(UIStrings.pausedOnCspViolation),
320
+ subText: i18nString(UIStrings.trustedTypePolicyViolation),
321
+ errorLike,
322
+ };
274
323
  }
275
324
  } else if (details.callFrames.length) {
276
325
  const uiLocation = await debuggerWorkspaceBinding.rawLocationToUILocation(details.callFrames[0].location());
277
326
  const breakpoint = uiLocation ? breakpointManager.findBreakpoint(uiLocation) : null;
278
327
  const defaultText = breakpoint ? i18nString(UIStrings.pausedOnBreakpoint) : i18nString(UIStrings.debuggerPaused);
279
- messageWrapper = buildWrapper(defaultText);
328
+ this.#viewInput = {mainText: defaultText, errorLike};
280
329
  } else {
330
+ this.#viewInput = null;
281
331
  console.warn(
282
332
  'ScriptsPanel paused, but callFrames.length is zero.'); // TODO remove this once we understand this case better
283
333
  }
284
334
 
285
- status.classList.toggle('error-reason', errorLike);
286
- if (messageWrapper) {
287
- status.appendChild(messageWrapper);
288
- }
335
+ this.requestUpdate();
336
+ }
289
337
 
290
- function buildWrapper(mainText: string, subText?: string, title?: string): Element {
291
- const messageWrapper = document.createElement('span');
292
- const mainElement = messageWrapper.createChild('div', 'status-main');
293
- const mainIcon = new Icon();
294
- mainIcon.name = errorLike ? 'cross-circle-filled' : 'info';
295
- mainIcon.style.color = errorLike ? 'var(--icon-error)' : 'var(--sys-color-on-yellow-container)';
296
- mainIcon.classList.add('medium');
297
- mainElement.appendChild(mainIcon);
298
- mainElement.appendChild(document.createTextNode(mainText));
299
- if (subText) {
300
- const subElement = messageWrapper.createChild('div', 'status-sub monospace');
301
- subElement.textContent = subText;
302
- UI.Tooltip.Tooltip.install(subElement, title || subText);
303
- }
304
- return messageWrapper;
305
- }
338
+ override performUpdate(): void {
339
+ this.view(this.#viewInput, undefined, this.contentElement);
306
340
  }
307
341
  }
308
342
 
@@ -311,6 +345,7 @@ export const BreakpointTypeNouns = new Map([
311
345
  [Protocol.DOMDebugger.DOMBreakpointType.AttributeModified, i18nLazyString(UIStrings.attributeModifications)],
312
346
  [Protocol.DOMDebugger.DOMBreakpointType.NodeRemoved, i18nLazyString(UIStrings.nodeRemoval)],
313
347
  ]);
348
+
314
349
  interface PausedDetailsAuxData {
315
350
  description?: string;
316
351
  url?: Platform.DevToolsPath.UrlString;
@@ -708,13 +708,21 @@ export class SourcesPanel extends UI.Panel.Panel implements
708
708
  private async updateDebuggerButtonsAndStatus(): Promise<void> {
709
709
  const currentTarget = UI.Context.Context.instance().flavor(SDK.Target.Target);
710
710
  const currentDebuggerModel = currentTarget ? currentTarget.model(SDK.DebuggerModel.DebuggerModel) : null;
711
+
712
+ const paused = this.#paused;
713
+ const details = currentDebuggerModel ? currentDebuggerModel.debuggerPausedDetails() : null;
714
+ await this.debuggerPausedMessage.render(
715
+ details, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),
716
+ Breakpoints.BreakpointManager.BreakpointManager.instance());
717
+ await this.debuggerPausedMessage.updateComplete;
718
+
711
719
  if (!currentDebuggerModel) {
712
720
  this.togglePauseAction.setEnabled(false);
713
721
  this.stepOverAction.setEnabled(false);
714
722
  this.stepIntoAction.setEnabled(false);
715
723
  this.stepOutAction.setEnabled(false);
716
724
  this.stepAction.setEnabled(false);
717
- } else if (this.#paused) {
725
+ } else if (paused) {
718
726
  this.togglePauseAction.setToggled(true);
719
727
  this.togglePauseAction.setEnabled(true);
720
728
  this.stepOverAction.setEnabled(true);
@@ -729,11 +737,6 @@ export class SourcesPanel extends UI.Panel.Panel implements
729
737
  this.stepOutAction.setEnabled(false);
730
738
  this.stepAction.setEnabled(false);
731
739
  }
732
-
733
- const details = currentDebuggerModel ? currentDebuggerModel.debuggerPausedDetails() : null;
734
- await this.debuggerPausedMessage.render(
735
- details, Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(),
736
- Breakpoints.BreakpointManager.BreakpointManager.instance());
737
740
  if (details) {
738
741
  this.updateDebuggerButtonsAndStatusForTest();
739
742
  }
@@ -1228,7 +1231,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
1228
1231
  this.revealDebuggerSidebar.bind(this), undefined, 'debug');
1229
1232
  this.sidebarPaneStack.widget().element.classList.add('y-overflow-only');
1230
1233
  this.sidebarPaneStack.widget().show(vbox.element);
1231
- this.sidebarPaneStack.widget().element.appendChild(this.debuggerPausedMessage.element());
1234
+ this.debuggerPausedMessage.show(this.sidebarPaneStack.widget().element);
1232
1235
  this.sidebarPaneStack.appendApplicableItems('sources.sidebar-top');
1233
1236
 
1234
1237
  if (this.threadsSidebarPane) {
@@ -41,3 +41,11 @@ devtools-icon {
41
41
  left: -1px;
42
42
  top: -1px;
43
43
  }
44
+
45
+ devtools-icon[name="info"] {
46
+ color: var(--sys-color-on-yellow-container);
47
+ }
48
+
49
+ devtools-icon[name="cross-circle-filled"] {
50
+ color: var(--icon-error);
51
+ }
@@ -145,14 +145,15 @@ export class StatusDialog extends UI.Widget.VBox {
145
145
  }
146
146
 
147
147
  remove(): void {
148
- (this.element.parentNode as HTMLElement)?.classList.remove('tinted');
148
+ (this.element.parentNode as HTMLElement)?.classList.remove('opaque', 'tinted');
149
149
  this.stopTimer();
150
150
  this.element.remove();
151
151
  }
152
152
 
153
- showPane(parent: Element): void {
153
+ showPane(parent: Element, mode: 'tinted'|'opaque' = 'opaque'): void {
154
154
  this.show(parent);
155
- parent.classList.add('tinted');
155
+ parent.classList.toggle('tinted', mode === 'tinted');
156
+ parent.classList.toggle('opaque', mode === 'opaque');
156
157
  }
157
158
 
158
159
  enableAndFocusButton(): void {
@@ -423,28 +423,15 @@ export class TimelineFlameChartNetworkDataProvider implements PerfUI.FlameChart.
423
423
 
424
424
  /**
425
425
  * When users zoom in the flamechart, we only want to show them the network
426
- * requests between startTime and endTime. This function will call the
427
- * trackAppender to update the timeline data, and then force to create a new
428
- * PerfUI.FlameChart.FlameChartTimelineData instance to force the flamechart
429
- * to re-render.
426
+ * requests between startTime and endTime.
430
427
  */
431
428
  #updateTimelineData(startTime: Trace.Types.Timing.Milli, endTime: Trace.Types.Timing.Milli): void {
432
429
  if (!this.#networkTrackAppender || !this.#timelineData) {
433
430
  return;
434
431
  }
432
+ // This also has the side-effect of updating this.#timelineData with new
433
+ // information.
435
434
  this.#maxLevel = this.#networkTrackAppender.relayoutEntriesWithinBounds(this.#events, startTime, endTime);
436
-
437
- // TODO(crbug.com/1459225): Remove this recreating code.
438
- // Force to create a new PerfUI.FlameChart.FlameChartTimelineData instance
439
- // to force the flamechart to re-render. This also causes crbug.com/1459225.
440
- this.#timelineData = PerfUI.FlameChart.FlameChartTimelineData.create({
441
- entryLevels: this.#timelineData?.entryLevels,
442
- entryTotalTimes: this.#timelineData?.entryTotalTimes,
443
- entryStartTimes: this.#timelineData?.entryStartTimes,
444
- groups: this.#timelineData?.groups,
445
- initiatorsData: this.#timelineData.initiatorsData,
446
- entryDecorations: this.#timelineData.entryDecorations,
447
- });
448
435
  }
449
436
 
450
437
  /**
@@ -66,10 +66,12 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
66
66
  */
67
67
  export const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly<Record<string, number>> = {
68
68
  [Trace.Types.Events.Name.NAVIGATION_START]: 0,
69
- [Trace.Types.Events.Name.MARK_LOAD]: 1,
70
- [Trace.Types.Events.Name.MARK_FCP]: 2,
71
- [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 3,
72
- [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 4,
69
+ [Trace.Types.Events.Name.SOFT_NAVIGATION_START]: 1,
70
+ [Trace.Types.Events.Name.MARK_LOAD]: 2,
71
+ [Trace.Types.Events.Name.MARK_FCP]: 3,
72
+ [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 4,
73
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 5,
74
+ [Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 6,
73
75
  };
74
76
 
75
77
  // Threshold to match up overlay markers that are off by a tiny amount so they aren't rendered
@@ -648,6 +650,7 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
648
650
  fieldMetricResult = fieldMetricResults.fcp;
649
651
  } else if (event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE) {
650
652
  fieldMetricResult = fieldMetricResults.lcp;
653
+ // Ignoring soft-nav LCP on purpose.
651
654
  }
652
655
 
653
656
  if (!fieldMetricResult) {
@@ -669,7 +672,9 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
669
672
  // Set markers for Navigations, LCP, FCP, DCL, L.
670
673
  const markers = markerEvents.filter(
671
674
  event => event.name === Trace.Types.Events.Name.NAVIGATION_START ||
675
+ event.name === Trace.Types.Events.Name.SOFT_NAVIGATION_START ||
672
676
  event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE ||
677
+ event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION ||
673
678
  event.name === Trace.Types.Events.Name.MARK_FCP ||
674
679
  event.name === Trace.Types.Events.Name.MARK_DOM_CONTENT ||
675
680
  event.name === Trace.Types.Events.Name.MARK_LOAD);
@@ -681,6 +686,7 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
681
686
  marker,
682
687
  parsedTrace.data.Meta.traceBounds,
683
688
  parsedTrace.data.Meta.navigationsByNavigationId,
689
+ parsedTrace.data.Meta.softNavigationsById,
684
690
  parsedTrace.data.Meta.navigationsByFrameId,
685
691
  );
686
692
  // If any of the markers overlap in timing, lets put them on the same marker.
@@ -732,24 +738,11 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
732
738
  entries.push(...Overlays.Overlays.entriesForOverlay(overlay));
733
739
  }
734
740
 
735
- // The insight's `relatedEvents` property likely already includes the events associated with
736
- // an overlay, but just in case not, include both arrays. Duplicates are fine.
737
- let relatedEventsList = this.#activeInsight?.model.relatedEvents;
738
- if (!relatedEventsList) {
739
- relatedEventsList = [];
740
- } else if (relatedEventsList instanceof Map) {
741
- relatedEventsList = Array.from(relatedEventsList.keys());
742
- }
743
- this.#dimInsightRelatedEvents([...entries, ...relatedEventsList]);
744
-
745
741
  if (options.updateTraceWindow) {
746
- // We should only expand the entry track when we are updating the trace window
747
- // (eg. when insight cards are initially opened).
742
+ // We should only expand the entry track when we are updating the trace window (eg. when insight cards are initially opened).
748
743
  // Otherwise the track will open when not intending to.
749
- for (const entry of entries) {
750
- // Ensure that the track for the entries are open.
751
- this.#expandEntryTrack(entry);
752
- }
744
+ this.#bulkExpandGroupsForEntries(entries);
745
+
753
746
  const overlaysBounds = Overlays.Overlays.traceWindowContainingOverlays(this.#currentInsightOverlays);
754
747
  if (overlaysBounds) {
755
748
  // Trace window covering all overlays expanded by 50% so that the overlays cover 2/3 (100/150) of the visible window. (Or use provided override)
@@ -767,11 +760,26 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
767
760
  }
768
761
  }
769
762
 
763
+ // The insight's `relatedEvents` property likely already includes the events associated with
764
+ // an overlay, but just in case not, include both arrays. Duplicates are fine.
765
+ let relatedEventsList = this.#activeInsight?.model.relatedEvents;
766
+ if (!relatedEventsList) {
767
+ relatedEventsList = [];
768
+ } else if (relatedEventsList instanceof Map) {
769
+ relatedEventsList = Array.from(relatedEventsList.keys());
770
+ }
771
+ this.#dimInsightRelatedEvents([...entries, ...relatedEventsList]);
772
+
770
773
  // Reveal entry if we have one.
774
+ // This is wrapped in a rAF to make sure the FlameChart draw from the
775
+ // expansion of any groups is complete - we need all the update() handlers
776
+ // to have run so the FlameChart has been drawn correctly at the right height.
771
777
  if (entries.length !== 0) {
772
778
  const earliestEntry =
773
779
  entries.reduce((earliest, current) => (earliest.ts < current.ts ? earliest : current), entries[0]);
774
- this.revealEventVertically(earliestEntry);
780
+ requestAnimationFrame(() => {
781
+ this.revealEventVertically(earliestEntry);
782
+ });
775
783
  }
776
784
  }
777
785
 
@@ -823,6 +831,41 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
823
831
  }
824
832
  }
825
833
 
834
+ /**
835
+ * Bulk expands the tracks (e.g. groups) that the given entries belong to.
836
+ * Will update them all at once and then do a redraw.
837
+ */
838
+ #bulkExpandGroupsForEntries(entries: Trace.Types.Events.Event[]): void {
839
+ const networkGroupIndexes = new Set<number>();
840
+ const mainGroupIndexes = new Set<number>();
841
+
842
+ for (const entry of entries) {
843
+ const chartName = Overlays.Overlays.chartForEntry(entry);
844
+ const provider = chartName === 'main' ? this.mainDataProvider : this.networkDataProvider;
845
+ const entryIndex = provider.indexForEvent?.(entry) ?? null;
846
+ if (entryIndex === null) {
847
+ continue;
848
+ }
849
+
850
+ const group = provider.groupForEvent?.(entryIndex) ?? null;
851
+ if (!group) {
852
+ continue;
853
+ }
854
+ if (group.expanded) {
855
+ continue;
856
+ }
857
+ const groupIndex = provider.timelineData().groups.indexOf(group);
858
+ if (chartName === 'main') {
859
+ mainGroupIndexes.add(groupIndex);
860
+ } else {
861
+ networkGroupIndexes.add(groupIndex);
862
+ }
863
+ }
864
+
865
+ this.mainFlameChart.bulkExpandGroups([...mainGroupIndexes]);
866
+ this.networkFlameChart.bulkExpandGroups([...networkGroupIndexes]);
867
+ }
868
+
826
869
  /**
827
870
  * Expands the track / group that the given entry is in.
828
871
  */