chrome-devtools-frontend 1.0.1525561 → 1.0.1526203

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 (46) hide show
  1. package/front_end/core/common/Settings.ts +1 -1
  2. package/front_end/core/sdk/PreloadingModel.ts +3 -0
  3. package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
  4. package/front_end/core/sdk/SourceMapScopesInfo.ts +57 -0
  5. package/front_end/generated/InspectorBackendCommands.js +4 -4
  6. package/front_end/generated/SupportedCSSProperties.js +0 -19
  7. package/front_end/generated/protocol-mapping.d.ts +1 -1
  8. package/front_end/generated/protocol-proxy-api.d.ts +1 -1
  9. package/front_end/generated/protocol.ts +9 -8
  10. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +43 -8
  11. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +50 -32
  12. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +29 -29
  13. package/front_end/models/javascript_metadata/NativeFunctions.js +3 -8
  14. package/front_end/models/trace/handlers/UserTimingsHandler.ts +1 -1
  15. package/front_end/models/trace/insights/CLSCulprits.ts +2 -1
  16. package/front_end/models/trace/insights/Cache.ts +2 -1
  17. package/front_end/models/trace/insights/DOMSize.ts +2 -1
  18. package/front_end/models/trace/insights/DocumentLatency.ts +2 -1
  19. package/front_end/models/trace/insights/DuplicatedJavaScript.ts +2 -1
  20. package/front_end/models/trace/insights/FontDisplay.ts +2 -1
  21. package/front_end/models/trace/insights/ForcedReflow.ts +2 -1
  22. package/front_end/models/trace/insights/INPBreakdown.ts +2 -1
  23. package/front_end/models/trace/insights/ImageDelivery.ts +2 -1
  24. package/front_end/models/trace/insights/LCPBreakdown.ts +2 -1
  25. package/front_end/models/trace/insights/LCPDiscovery.ts +2 -1
  26. package/front_end/models/trace/insights/LegacyJavaScript.ts +2 -1
  27. package/front_end/models/trace/insights/ModernHTTP.ts +2 -1
  28. package/front_end/models/trace/insights/NetworkDependencyTree.ts +2 -1
  29. package/front_end/models/trace/insights/RenderBlocking.ts +2 -1
  30. package/front_end/models/trace/insights/SlowCSSSelector.ts +2 -1
  31. package/front_end/models/trace/insights/ThirdParties.ts +2 -1
  32. package/front_end/models/trace/insights/Viewport.ts +2 -1
  33. package/front_end/models/trace/insights/types.ts +2 -1
  34. package/front_end/panels/application/ReportingApiView.ts +8 -7
  35. package/front_end/panels/application/StorageView.ts +2 -1
  36. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -0
  37. package/front_end/panels/console/ConsolePrompt.ts +24 -4
  38. package/front_end/panels/timeline/TimelinePanel.ts +10 -8
  39. package/front_end/panels/timeline/components/ExportTraceOptions.ts +1 -1
  40. package/front_end/third_party/chromium/README.chromium +1 -1
  41. package/front_end/ui/components/buttons/Button.ts +17 -0
  42. package/front_end/ui/legacy/SearchableView.ts +1 -1
  43. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +48 -5
  44. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +2 -2
  45. package/front_end/ui/legacy/components/source_frame/JSONView.ts +28 -0
  46. package/package.json +22 -22
@@ -30,7 +30,7 @@ export const UIStrings = {
30
30
  * @description Description of an insight that recommends avoiding chaining critical requests.
31
31
  */
32
32
  description:
33
- '[Avoid chaining critical requests](https://developer.chrome.com/docs/lighthouse/performance/critical-request-chains) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load.',
33
+ '[Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load.',
34
34
  /**
35
35
  * @description Description of the warning that recommends avoiding chaining critical requests.
36
36
  */
@@ -175,6 +175,7 @@ function finalize(partialModel: PartialInsightModel<NetworkDependencyTreeInsight
175
175
  strings: UIStrings,
176
176
  title: i18nString(UIStrings.title),
177
177
  description: i18nString(UIStrings.description),
178
+ docs: 'https://developer.chrome.com/docs/performance/insights/network-dependency-tree',
178
179
  category: InsightCategory.LCP,
179
180
  state: partialModel.fail ? 'fail' : 'pass',
180
181
  ...partialModel,
@@ -29,7 +29,7 @@ export const UIStrings = {
29
29
  * @description Text to describe that there are requests blocking rendering, which may affect LCP.
30
30
  */
31
31
  description: 'Requests are blocking the page\'s initial render, which may delay LCP. ' +
32
- '[Deferring or inlining](https://web.dev/learn/performance/understanding-the-critical-path#render-blocking_resources) ' +
32
+ '[Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) ' +
33
33
  'can move these network requests out of the critical path.',
34
34
  /**
35
35
  * @description Label to describe a network request (that happens to be render-blocking).
@@ -169,6 +169,7 @@ function finalize(partialModel: PartialInsightModel<RenderBlockingInsightModel>)
169
169
  strings: UIStrings,
170
170
  title: i18nString(UIStrings.title),
171
171
  description: i18nString(UIStrings.description),
172
+ docs: 'https://developer.chrome.com/docs/performance/insights/render-blocking',
172
173
  category: InsightCategory.LCP,
173
174
  state: partialModel.renderBlockingRequests.length > 0 ? 'fail' : 'pass',
174
175
  ...partialModel,
@@ -27,7 +27,7 @@ export const UIStrings = {
27
27
  * @description Text to describe how to improve the performance of CSS selectors.
28
28
  */
29
29
  description:
30
- 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',
30
+ 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/performance/insights/slow-css-selector) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',
31
31
  /**
32
32
  * @description Column name for count of elements that the engine attempted to match against a style rule
33
33
  */
@@ -108,6 +108,7 @@ function finalize(partialModel: PartialInsightModel<SlowCSSSelectorInsightModel>
108
108
  strings: UIStrings,
109
109
  title: i18nString(UIStrings.title),
110
110
  description: i18nString(UIStrings.description),
111
+ docs: 'https://developer.chrome.com/docs/performance/insights/slow-css-selector',
111
112
  category: InsightCategory.ALL,
112
113
  state: partialModel.topSelectorElapsedMs && partialModel.topSelectorMatchAttempts ? 'informative' : 'pass',
113
114
  ...partialModel,
@@ -24,7 +24,7 @@ export const UIStrings = {
24
24
  * This is displayed after a user expands the section to see more. No character length limits.
25
25
  */
26
26
  description: '3rd party code can significantly impact load performance. ' +
27
- '[Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page\'s content.',
27
+ '[Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page\'s content.',
28
28
  /** Label for a table column that displays the name of a third-party provider. */
29
29
  columnThirdParty: '3rd party',
30
30
  /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */
@@ -65,6 +65,7 @@ function finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>):
65
65
  strings: UIStrings,
66
66
  title: i18nString(UIStrings.title),
67
67
  description: i18nString(UIStrings.description),
68
+ docs: 'https://developer.chrome.com/docs/performance/insights/third-parties',
68
69
  category: InsightCategory.ALL,
69
70
  state: partialModel.entitySummaries.find(summary => summary.entity !== partialModel.firstPartyEntity) ?
70
71
  'informative' :
@@ -24,7 +24,7 @@ export const UIStrings = {
24
24
  * @description Text to tell the user how a viewport meta element can improve performance. \xa0 is a non-breaking space
25
25
  */
26
26
  description:
27
- 'Tap interactions may be [delayed by up to 300\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',
27
+ 'Tap interactions may be [delayed by up to 300\xA0ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport is not optimized for mobile.',
28
28
  /**
29
29
  * @description Text for a label describing the portion of an interaction event that was delayed due to a bad mobile viewport.
30
30
  */
@@ -46,6 +46,7 @@ function finalize(partialModel: PartialInsightModel<ViewportInsightModel>): View
46
46
  strings: UIStrings,
47
47
  title: i18nString(UIStrings.title),
48
48
  description: i18nString(UIStrings.description),
49
+ docs: 'https://developer.chrome.com/docs/performance/insights/viewport',
49
50
  category: InsightCategory.INP,
50
51
  state: partialModel.mobileOptimized === false ? 'fail' : 'pass',
51
52
  ...partialModel,
@@ -76,6 +76,7 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
76
76
  strings: UIStrings,
77
77
  title: Common.UIString.LocalizedString,
78
78
  description: Common.UIString.LocalizedString,
79
+ docs: string,
79
80
  category: InsightCategory,
80
81
  state: 'pass' | 'fail' | 'informative',
81
82
  /** Used by RelatedInsightChips.ts */
@@ -101,7 +102,7 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
101
102
  };
102
103
 
103
104
  export type PartialInsightModel<T> =
104
- Omit<T, 'strings'|'title'|'description'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;
105
+ Omit<T, 'strings'|'title'|'description'|'docs'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;
105
106
 
106
107
  /**
107
108
  * Contains insights for a specific navigation. If a trace began after a navigation already started,
@@ -56,12 +56,11 @@ interface ViewInput {
56
56
  onReportSelected: (id: string) => void;
57
57
  }
58
58
 
59
- type View = (input: ViewInput, output: object, target: HTMLElement) => void;
60
-
61
- export const DEFAULT_VIEW: View = (input, _output, target) => {
59
+ export const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLElement): void => {
62
60
  if (input.hasReports || input.hasEndpoints) {
63
61
  // clang-format off
64
62
  render(html`
63
+ <style>${UI.inspectorCommonStyles}</style>
65
64
  <devtools-split-view sidebar-position="second" sidebar-initial-size="150" jslog=${
66
65
  VisualLogging.pane('reporting-api')}>
67
66
  ${input.hasReports ? html`
@@ -73,9 +72,9 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
73
72
  </div>
74
73
  <div slot="sidebar" class="vbox" jslog=${VisualLogging.pane('preview').track({resize: true})}>
75
74
  ${input.focusedReport ? html`
76
- <devtools-widget .widgetConfig=${widgetConfig(
77
- element => SourceFrame.JSONView.JSONView.createViewSync(input.focusedReport?.body || '', element)
78
- )}></devtools-widget>
75
+ <devtools-widget .widgetConfig=${widgetConfig(SourceFrame.JSONView.SearchableJsonView, {
76
+ jsonObject: input.focusedReport.body,
77
+ })}></devtools-widget>
79
78
  ` : html`
80
79
  <devtools-widget .widgetConfig=${widgetConfig(UI.EmptyWidget.EmptyWidget, {
81
80
  header: i18nString(UIStrings.noReportSelected),
@@ -112,6 +111,8 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
112
111
  }
113
112
  };
114
113
 
114
+ type View = typeof DEFAULT_VIEW;
115
+
115
116
  export class ReportingApiView extends UI.Widget.VBox implements
116
117
  SDK.TargetManager.SDKModelObserver<SDK.NetworkManager.NetworkManager> {
117
118
  #endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]>;
@@ -164,7 +165,7 @@ export class ReportingApiView extends UI.Widget.VBox implements
164
165
  focusedReport: this.#focusedReport,
165
166
  onReportSelected: this.#onReportSelected.bind(this),
166
167
  };
167
- this.#view(viewInput, {}, this.element);
168
+ this.#view(viewInput, undefined, this.element);
168
169
  }
169
170
 
170
171
  #onEndpointsChangedForOrigin({data}: {data: Protocol.Network.ReportingApiEndpointsChangedForOriginEvent}): void {
@@ -236,6 +236,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget {
236
236
  this.quotaOverrideCheckbox.addEventListener('click', this.onClickCheckbox.bind(this), false);
237
237
  this.quotaOverrideControlRow = quota.appendRow();
238
238
  this.quotaOverrideEditor = this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor');
239
+ this.quotaOverrideEditor.setAttribute('placeholder', i18nString(UIStrings.pleaseEnterANumber));
239
240
  this.quotaOverrideEditor.setAttribute(
240
241
  'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);
241
242
  this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));
@@ -402,7 +403,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget {
402
403
  this.quotaOverrideControlRow.classList.remove('hidden');
403
404
  this.quotaOverrideCheckbox.checked = true;
404
405
  this.quotaOverrideEditor.value = this.previousOverrideFieldValue;
405
- this.quotaOverrideEditor.focus();
406
+ window.setTimeout(() => this.quotaOverrideEditor.focus(), 500);
406
407
  } else if (this.target && this.securityOrigin) {
407
408
  this.quotaOverrideControlRow.classList.add('hidden');
408
409
  this.quotaOverrideCheckbox.checked = false;
@@ -736,6 +736,8 @@ export function capitalizedAction(action: Protocol.Preload.SpeculationAction): C
736
736
  return i18n.i18n.lockedString('Prefetch');
737
737
  case Protocol.Preload.SpeculationAction.Prerender:
738
738
  return i18n.i18n.lockedString('Prerender');
739
+ case Protocol.Preload.SpeculationAction.PrerenderUntilScript:
740
+ return i18n.i18n.lockedString('PrerenderUntilScript');
739
741
  }
740
742
  }
741
743
 
@@ -343,9 +343,29 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
343
343
  }
344
344
 
345
345
  private editorKeymap(): readonly CodeMirror.KeyBinding[] {
346
- const keymap = [
347
- {key: 'ArrowUp', run: () => this.#editorHistory.moveHistory(Direction.BACKWARD)},
348
- {key: 'ArrowDown', run: () => this.#editorHistory.moveHistory(Direction.FORWARD)},
346
+ const keymap: CodeMirror.KeyBinding[] = [
347
+ {
348
+ // Handle the KeyboardEvent manually.
349
+ any: (_view, event) => {
350
+ // Events with `repeat=true` are excluded from altering the history state because
351
+ // they are often not intended as such. Example:
352
+ // Scrolling through long snippets.
353
+ if (event.repeat) {
354
+ return false;
355
+ }
356
+
357
+ if (event.key === 'ArrowUp') {
358
+ return this.#editorHistory.moveHistory(Direction.BACKWARD);
359
+ }
360
+
361
+ if (event.key === 'ArrowDown') {
362
+ return this.#editorHistory.moveHistory(Direction.FORWARD);
363
+ }
364
+
365
+ return false;
366
+ },
367
+ },
368
+
349
369
  {mac: 'Ctrl-p', run: () => this.#editorHistory.moveHistory(Direction.BACKWARD, true)},
350
370
  {mac: 'Ctrl-n', run: () => this.#editorHistory.moveHistory(Direction.FORWARD, true)},
351
371
  {
@@ -372,7 +392,7 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
372
392
  if (this.isAiCodeCompletionEnabled()) {
373
393
  keymap.push({
374
394
  key: 'Tab',
375
- run: (): boolean => {
395
+ run: () => {
376
396
  const {accepted, suggestion} = TextEditor.Config.acceptAiAutoCompleteSuggestion(this.editor.editor);
377
397
  if (accepted) {
378
398
  this.dispatchEventToListeners(
@@ -310,7 +310,7 @@ let isNode: boolean;
310
310
 
311
311
  /**
312
312
  * Represents the states that the timeline panel can be in.
313
- * If you need to change the panel's view, use the {@see #changeView} method.
313
+ * If you need to change the panel's view, use the {@link TimelinePanel.#changeView} method.
314
314
  * Note that we do not represent the "Loading/Processing" view here. The
315
315
  * StatusPane is managed in the code that handles file import/recording, and
316
316
  * when it is visible it is rendered on top of the UI so obscures what is behind
@@ -787,8 +787,8 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
787
787
  }
788
788
 
789
789
  /**
790
- * Determine if two view modes are equivalent. Useful because if {@see
791
- * #changeView} gets called and the new mode is identical to the current,
790
+ * Determine if two view modes are equivalent. Useful because if
791
+ * {@link TimelinePanel.#changeView} gets called and the new mode is identical to the current,
792
792
  * we can bail without doing any UI updates.
793
793
  */
794
794
  #viewModesEquivalent(m1: ViewMode, m2: ViewMode): boolean {
@@ -2087,14 +2087,14 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2087
2087
 
2088
2088
  /**
2089
2089
  * Called when we update the active trace that is being shown to the user.
2090
- * This is called from {@see changeView} when we change the UI to show a
2090
+ * This is called from {@link TimelinePanel.#changeView} when we change the UI to show a
2091
2091
  * trace - either one the user has just recorded/imported, or one they have
2092
2092
  * navigated to via the dropdown.
2093
2093
  *
2094
2094
  * If you need code to execute whenever the active trace changes, this is the method to use.
2095
- * If you need code to execute ONLY ON NEW TRACES, then use {@see loadingComplete}
2095
+ * If you need code to execute ONLY ON NEW TRACES, then use {@link TimelinePanel.loadingComplete}
2096
2096
  * You should not call this method directly if you want the UI to update; use
2097
- * {@see changeView} to control what is shown to the user.
2097
+ * {@link TimelinePanel.#changeView} to control what is shown to the user.
2098
2098
  */
2099
2099
  #setModelForActiveTrace(): void {
2100
2100
  if (this.#viewMode.mode !== 'VIEWING_TRACE') {
@@ -2249,8 +2249,10 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
2249
2249
  }
2250
2250
  }
2251
2251
 
2252
- UI.Context.Context.instance().setFlavor(
2253
- AiAssistanceModel.AgentFocus, AiAssistanceModel.AgentFocus.fromParsedTrace(parsedTrace));
2252
+ if (parsedTrace.metadata.dataOrigin !== Trace.Types.File.DataOrigin.CPU_PROFILE) {
2253
+ UI.Context.Context.instance().setFlavor(
2254
+ AiAssistanceModel.AgentFocus, AiAssistanceModel.AgentFocus.fromParsedTrace(parsedTrace));
2255
+ }
2254
2256
  }
2255
2257
 
2256
2258
  #onAnnotationModifiedEvent(e: Event): void {
@@ -235,7 +235,7 @@ export class ExportTraceOptions extends HTMLElement {
235
235
  ${checkboxesWithInfoDialog.has(checkboxId) ? html`
236
236
  <devtools-button
237
237
  aria-details=${`export-trace-tooltip-${checkboxId}`}
238
- aria-label=${this.#accessibleLabelForInfoCheckbox(checkboxId)}
238
+ .accessibleLabel=${this.#accessibleLabelForInfoCheckbox(checkboxId)}
239
239
  class="pen-icon"
240
240
  .iconName=${'info'}
241
241
  .variant=${Buttons.Button.Variant.ICON}
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://source.chromium.org/chromium/chromium/src/+/main:components/variations/proto/devtools/
3
3
  Version: N/A
4
- Revision: 21c0e9d79181fd991f782bb74b0eb1c8bce10209
4
+ Revision: 871199b5845026663e1efbe7e1dcc69c6ec1dfb7
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -63,6 +63,10 @@ interface ButtonState {
63
63
  jslogContext?: string;
64
64
  longClickable?: boolean;
65
65
  inverseColorTheme?: boolean;
66
+ /**
67
+ * Sets aria-label on the internal <button> element.
68
+ */
69
+ accessibleLabel?: string;
66
70
  }
67
71
 
68
72
  interface CommonButtonData {
@@ -84,6 +88,10 @@ interface CommonButtonData {
84
88
  jslogContext?: string;
85
89
  longClickable?: boolean;
86
90
  inverseColorTheme?: boolean;
91
+ /**
92
+ * Sets aria-label on the internal <button> element.
93
+ */
94
+ accessibleLabel?: string;
87
95
  }
88
96
 
89
97
  export type ButtonData = CommonButtonData&(|{
@@ -143,6 +151,9 @@ export class Button extends HTMLElement {
143
151
  if ('size' in data && data.size) {
144
152
  this.#props.size = data.size;
145
153
  }
154
+ if (data.accessibleLabel) {
155
+ this.#props.accessibleLabel = data.accessibleLabel;
156
+ }
146
157
 
147
158
  this.#props.active = Boolean(data.active);
148
159
  this.#props.spinner = Boolean('spinner' in data ? data.spinner : false);
@@ -187,6 +198,11 @@ export class Button extends HTMLElement {
187
198
  this.#render();
188
199
  }
189
200
 
201
+ set accessibleLabel(label: string) {
202
+ this.#props.accessibleLabel = label;
203
+ this.#render();
204
+ }
205
+
190
206
  set reducedFocusRing(reducedFocusRing: boolean) {
191
207
  this.#props.reducedFocusRing = reducedFocusRing;
192
208
  this.#render();
@@ -357,6 +373,7 @@ export class Button extends HTMLElement {
357
373
  .disabled=${this.#props.disabled}
358
374
  class=${classMap(classes)}
359
375
  aria-pressed=${ifDefined(this.#props.toggled)}
376
+ aria-label=${ifDefined(this.#props.accessibleLabel)}
360
377
  jslog=${ifDefined(jslog)}>
361
378
  ${hasIcon ? html`
362
379
  <devtools-icon name=${ifDefined(this.#props.toggled ? this.#props.toggledIconName : this.#props.iconName)}>
@@ -139,7 +139,7 @@ function createClearButton(jslogContext: string): Buttons.Button.Button {
139
139
  return button;
140
140
  }
141
141
  export class SearchableView extends VBox {
142
- private searchProvider: Searchable;
142
+ protected searchProvider: Searchable;
143
143
  private replaceProvider: Replaceable|null;
144
144
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
145
145
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5,10 +5,17 @@
5
5
 
6
6
  import type * as Platform from '../../../../core/platform/platform.js';
7
7
  import type * as TextUtils from '../../../../models/text_utils/text_utils.js';
8
- import * as UI from '../../../../ui/legacy/legacy.js';
8
+ import * as UI from '../../legacy.js';
9
9
 
10
10
  import dataGridStyles from './dataGrid.css.js';
11
- import {Align, type ColumnDescriptor, DataType, Events as DataGridEvents} from './DataGrid.js';
11
+ import {
12
+ Align,
13
+ type ColumnDescriptor,
14
+ DataType,
15
+ Events as DataGridEvents,
16
+ Order,
17
+ type ResizeMethod
18
+ } from './DataGrid.js';
12
19
  import {SortableDataGrid, SortableDataGridNode} from './SortableDataGrid.js';
13
20
 
14
21
  const DUMMY_COLUMN_ID = 'dummy'; // SortableDataGrid.create requires at least one column.
@@ -36,12 +43,14 @@ const DUMMY_COLUMN_ID = 'dummy'; // SortableDataGrid.create requires at least o
36
43
  * Under the hood it uses SortableDataGrid, which extends ViewportDataGrid so only
37
44
  * visible rows are layed out and sorting is provided out of the box.
38
45
  *
39
- * @property filters
40
- * @attribute striped
46
+ * @property filters Set of text filters to be applied to the data grid.
47
+ * @attribute inline If true, the data grid will render inline instead of taking a full container height.
48
+ * @attribute resize Column resize method, one of 'nearest' (default), 'first' or 'last'.
49
+ * @attribute striped If true, the data grid will have striped rows.
41
50
  * @attribute displayName
42
51
  */
43
52
  class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
44
- static readonly observedAttributes = ['striped', 'name', 'inline'];
53
+ static readonly observedAttributes = ['striped', 'name', 'inline', 'resize'];
45
54
 
46
55
  #dataGrid = SortableDataGrid.create([DUMMY_COLUMN_ID], [], '') as SortableDataGrid<DataGridElementNode>;
47
56
  #resizeObserver = new ResizeObserver(() => {
@@ -69,6 +78,9 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
69
78
  e => (e.data as DataGridElementNode).configElement.dispatchEvent(new CustomEvent('select')));
70
79
  this.#dataGrid.addEventListener(
71
80
  DataGridEvents.DESELECTED_NODE, () => this.dispatchEvent(new CustomEvent('deselect')));
81
+ this.#dataGrid.addEventListener(
82
+ DataGridEvents.OPENED_NODE,
83
+ e => (e.data as DataGridElementNode).configElement.dispatchEvent(new CustomEvent('open')));
72
84
  this.#dataGrid.addEventListener(DataGridEvents.SORTING_CHANGED, () => this.dispatchEvent(new CustomEvent('sort', {
73
85
  detail: {columnId: this.#dataGrid.sortColumnId(), ascending: this.#dataGrid.isSortOrderAscending()}
74
86
  })));
@@ -111,6 +123,9 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
111
123
  case 'inline':
112
124
  this.#dataGrid.renderInline();
113
125
  break;
126
+ case 'resize':
127
+ this.#dataGrid.setResizeMethod(newValue as ResizeMethod);
128
+ break;
114
129
  }
115
130
  }
116
131
 
@@ -138,6 +153,14 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
138
153
  return this.getAttribute('name');
139
154
  }
140
155
 
156
+ set resizeMethod(resizeMethod: ResizeMethod) {
157
+ this.setAttribute('resize', resizeMethod);
158
+ }
159
+
160
+ get resizeMethod(): ResizeMethod {
161
+ return this.getAttribute('resize') as ResizeMethod;
162
+ }
163
+
141
164
  set filters(filters: TextUtils.TextUtils.ParsedFilter[]) {
142
165
  this.#dataGrid.setFilters(filters);
143
166
  this.#dataGrid.element.setAttribute('aria-rowcount', String(this.#dataGrid.getNumberOfRows()));
@@ -178,11 +201,15 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
178
201
  if (editable) {
179
202
  hasEditableColumn = true;
180
203
  }
204
+ const sort = column.getAttribute('sort') === 'descending' ? Order.Descending :
205
+ column.getAttribute('sort') === 'ascending' ? Order.Ascending :
206
+ undefined;
181
207
  const columnDescriptor = {
182
208
  id,
183
209
  title: title as Platform.UIString.LocalizedString,
184
210
  titleDOMFragment,
185
211
  sortable,
212
+ sort,
186
213
  fixedWidth,
187
214
  width,
188
215
  align,
@@ -235,6 +262,18 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
235
262
  .filter(node => node.querySelector('td') && !hasBooleanAttribute(node, 'placeholder'));
236
263
  }
237
264
 
265
+ #getStyleElements(nodes: NodeList): HTMLElement[] {
266
+ return [...nodes].flatMap(node => {
267
+ if (node instanceof HTMLStyleElement) {
268
+ return [node];
269
+ }
270
+ if (node instanceof HTMLElement) {
271
+ return [...node.querySelectorAll<HTMLStyleElement>('style')];
272
+ }
273
+ return [] as HTMLElement[];
274
+ });
275
+ }
276
+
238
277
  #findNextExistingNode(element: Element): DataGridElementNode|null {
239
278
  for (let e = element.nextElementSibling; e; e = e.nextElementSibling) {
240
279
  const nextNode = DataGridElementNode.get(e);
@@ -270,6 +309,9 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
270
309
  node.setHighlighted(true);
271
310
  }
272
311
  }
312
+ for (const element of this.#getStyleElements(nodes)) {
313
+ this.#shadowRoot.appendChild(element.cloneNode(true));
314
+ }
273
315
  }
274
316
 
275
317
  override removeNodes(nodes: NodeList): void {
@@ -304,6 +346,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
304
346
  dataGridNode.refresh();
305
347
  }
306
348
  }
349
+ this.#dataGrid.dispatchEventToListeners(DataGridEvents.SORTING_CHANGED);
307
350
  }
308
351
 
309
352
  #updateCreationNode(): void {
@@ -23,7 +23,7 @@ import {TimelineGrid} from './TimelineGrid.js';
23
23
  /**
24
24
  * Set as the `details` value on the fake context menu event we dispatch to
25
25
  * trigger a context menu on an event on a keyboard space key press.
26
- * {@see onContextMenu} for more details and explanation.
26
+ * {@link FlameChart.onContextMenu} for more details and explanation.
27
27
  */
28
28
  const KEYBOARD_FAKED_CONTEXT_MENU_DETAIL = -1;
29
29
 
@@ -2347,7 +2347,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin<EventTypes, type
2347
2347
  }
2348
2348
 
2349
2349
  /**
2350
- * Draws decorations onto events. {@see FlameChartDecoration}.
2350
+ * Draws decorations onto events. {@link FlameChartDecoration}.
2351
2351
  */
2352
2352
  #drawDecorations(context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, indexes: number[]): void {
2353
2353
  const {entryTotalTimes, entryStartTimes, entryLevels} = timelineData;
@@ -20,6 +20,7 @@ const UIStrings = {
20
20
  } as const;
21
21
  const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/source_frame/JSONView.ts', UIStrings);
22
22
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
23
+
23
24
  export class JSONView extends UI.Widget.VBox implements UI.SearchableView.Searchable {
24
25
  private initialized: boolean;
25
26
  private readonly parsedJSON: ParsedJSON;
@@ -67,6 +68,10 @@ export class JSONView extends UI.Widget.VBox implements UI.SearchableView.Search
67
68
  return searchableView;
68
69
  }
69
70
 
71
+ setSearchableView(searchableView: UI.SearchableView.SearchableView): void {
72
+ this.searchableView = searchableView;
73
+ }
74
+
70
75
  private static parseJSON(text: string|null): Promise<ParsedJSON|null> {
71
76
  let returnObj: ParsedJSON<string>|null = null;
72
77
  if (text) {
@@ -280,3 +285,26 @@ export class ParsedJSON<T extends unknown = unknown> {
280
285
  this.suffix = suffix;
281
286
  }
282
287
  }
288
+
289
+ export class SearchableJsonView extends UI.SearchableView.SearchableView {
290
+ #jsonView: JSONView;
291
+
292
+ constructor(element: HTMLElement) {
293
+ const jsonView = new JSONView(new ParsedJSON('', '', ''));
294
+ super(jsonView, null, undefined, element);
295
+ this.#jsonView = jsonView;
296
+ this.setPlaceholder(i18nString(UIStrings.find));
297
+ jsonView.setSearchableView(this);
298
+ jsonView.show(this.element);
299
+ jsonView.element.tabIndex = 0;
300
+ }
301
+
302
+ set jsonObject(obj: Object) {
303
+ const jsonView = new JSONView(new ParsedJSON(obj, '', ''));
304
+ this.#jsonView.detach();
305
+ this.#jsonView = jsonView;
306
+ this.searchProvider = jsonView;
307
+ jsonView.show(this.element);
308
+ this.requestUpdate();
309
+ }
310
+ }
package/package.json CHANGED
@@ -36,10 +36,10 @@
36
36
  "devDependencies": {
37
37
  "@rollup/plugin-node-resolve": "16.0.1",
38
38
  "@rollup/plugin-terser": "0.4.4",
39
- "@rollup/wasm-node": "4.46.2",
40
- "@stylistic/eslint-plugin": "5.2.3",
39
+ "@rollup/wasm-node": "4.52.1",
40
+ "@stylistic/eslint-plugin": "5.4.0",
41
41
  "@types/chai": "4.3.15",
42
- "@types/codemirror": "5.60.15",
42
+ "@types/codemirror": "5.60.16",
43
43
  "@types/emscripten": "1.39.4",
44
44
  "@types/estree": "1.0.8",
45
45
  "@types/filesystem": "0.0.36",
@@ -51,20 +51,20 @@
51
51
  "@types/webidl2": "24.4.3",
52
52
  "@types/yargs": "17.0.33",
53
53
  "@types/yargs-unparser": "2.0.3",
54
- "@typescript-eslint/rule-tester": "8.39.1",
55
- "@typescript-eslint/utils": "8.39.1",
54
+ "@typescript-eslint/rule-tester": "8.45.0",
55
+ "@typescript-eslint/utils": "8.45.0",
56
56
  "@web/rollup-plugin-import-meta-assets": "2.3.0",
57
57
  "chai": "4.3.4",
58
- "cssnano": "7.1.0",
58
+ "cssnano": "7.1.1",
59
59
  "cssnano-preset-lite": "4.0.4",
60
60
  "esbuild": "0.25.1",
61
- "eslint": "9.33.0",
61
+ "eslint": "9.36.0",
62
62
  "eslint-plugin-eslint-plugin": "7.0.0",
63
63
  "eslint-plugin-import": "2.32.0",
64
- "eslint-plugin-jsdoc": "51.3.4",
64
+ "eslint-plugin-jsdoc": "60.5.0",
65
65
  "eslint-plugin-mocha": "10.5.0",
66
66
  "glob": "7.1.7",
67
- "globals": "16.3.0",
67
+ "globals": "16.4.0",
68
68
  "js-yaml": "4.1.0",
69
69
  "karma": "6.4.4",
70
70
  "karma-chai": "0.1.0",
@@ -77,30 +77,30 @@
77
77
  "karma-spec-reporter": "0.0.36",
78
78
  "license-checker": "25.0.1",
79
79
  "lit-analyzer": "2.0.3",
80
- "mocha": "11.7.1",
81
- "ora": "8.2.0",
80
+ "mocha": "11.7.2",
81
+ "ora": "9.0.0",
82
82
  "postcss": "8.5.6",
83
- "puppeteer-core": "24.14.0",
84
- "rollup-plugin-sourcemaps2": "0.5.3",
83
+ "puppeteer-core": "24.22.3",
84
+ "rollup-plugin-sourcemaps2": "0.5.4",
85
85
  "sinon": "21.0.0",
86
86
  "source-map-support": "0.5.21",
87
- "stylelint": "16.23.1",
87
+ "stylelint": "16.24.0",
88
88
  "stylelint-config-standard": "39.0.0",
89
89
  "svgo": "3.3.2",
90
- "terser": "5.43.1",
90
+ "terser": "5.44.0",
91
91
  "ts-lit-plugin": "2.0.2",
92
92
  "typescript": "5.9.2",
93
- "typescript-eslint": "8.39.1",
94
- "uuid": "11.1.0",
93
+ "typescript-eslint": "8.45.0",
94
+ "uuid": "13.0.0",
95
95
  "webidl2": "24.5.0",
96
96
  "yargs": "17.7.2"
97
97
  },
98
98
  "overrides": {
99
- "@typescript-eslint/types": "8.39.1",
100
- "eslint": {
101
- "@eslint/plugin-kit": "0.3.4",
102
- "@eslint/core": "0.15.1"
99
+ "@typescript-eslint/types": "8.45.0",
100
+ "@es-joy/jsdoccomment": "0.64.0",
101
+ "stylelint": {
102
+ "flat-cache": "6.1.12"
103
103
  }
104
104
  },
105
- "version": "1.0.1525561"
105
+ "version": "1.0.1526203"
106
106
  }