chrome-devtools-frontend 1.0.1568864 → 1.0.1569477

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 (35) hide show
  1. package/front_end/core/common/ParsedURL.ts +3 -0
  2. package/front_end/core/host/AidaClient.ts +1 -0
  3. package/front_end/core/root/Runtime.ts +4 -8
  4. package/front_end/entrypoints/main/MainImpl.ts +17 -20
  5. package/front_end/generated/SupportedCSSProperties.js +14 -14
  6. package/front_end/models/ai_assistance/agents/PatchAgent.ts +4 -1
  7. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +12 -0
  8. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +12 -2
  9. package/front_end/models/ai_assistance/agents/StylingAgent.ts +4 -1
  10. package/front_end/models/stack_trace/StackTraceImpl.ts +12 -2
  11. package/front_end/models/stack_trace/StackTraceModel.ts +9 -1
  12. package/front_end/models/trace/Styles.ts +11 -8
  13. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +3 -2
  14. package/front_end/models/trace/types/TraceEvents.ts +19 -10
  15. package/front_end/panels/common/AiCodeGenerationTeaser.ts +1 -1
  16. package/front_end/panels/elements/ElementsPanel.ts +6 -3
  17. package/front_end/panels/elements/ElementsSidebarPane.ts +5 -2
  18. package/front_end/panels/elements/MetricsSidebarPane.ts +192 -177
  19. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  20. package/front_end/panels/elements/metricsSidebarPane.css +3 -11
  21. package/front_end/panels/settings/SettingsScreen.ts +8 -38
  22. package/front_end/panels/settings/settingsScreen.css +0 -4
  23. package/front_end/panels/sources/BreakpointEditDialog.ts +203 -138
  24. package/front_end/panels/sources/DebuggerPlugin.ts +15 -7
  25. package/front_end/panels/timeline/TimelineUIUtils.ts +9 -3
  26. package/front_end/panels/timeline/TimingsTrackAppender.ts +1 -0
  27. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +3 -1
  28. package/front_end/panels/timeline/timelineFlameChartView.css +1 -0
  29. package/front_end/third_party/chromium/README.chromium +1 -1
  30. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +23 -1
  31. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +16 -4
  32. package/front_end/ui/kit/link/Link.ts +14 -8
  33. package/front_end/ui/kit/link/link.css +1 -1
  34. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  35. package/package.json +1 -1
@@ -1,8 +1,6 @@
1
1
  // Copyright 2021 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
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
4
 
7
5
  /*
8
6
  * Copyright (C) 2007 Apple Inc. All rights reserved.
@@ -45,6 +43,144 @@ import metricsSidebarPaneStyles from './metricsSidebarPane.css.js';
45
43
 
46
44
  const {live} = Directives;
47
45
 
46
+ interface ViewInput {
47
+ style: Map<string, string>;
48
+ highlightedMode: string;
49
+ node: SDK.DOMModel.DOMNode|null;
50
+ contentWidth: string;
51
+ contentHeight: string;
52
+ onHighlightNode: (showHighlight: boolean, mode: string) => void;
53
+ onStartEditing: (target: Element, box: string, styleProperty: string, computedStyle: Map<string, string>) => void;
54
+ }
55
+
56
+ type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
57
+
58
+ const DEFAULT_VIEW: View = (input, output, target) => {
59
+ const {style, highlightedMode, node, contentWidth, contentHeight, onHighlightNode, onStartEditing} = input;
60
+
61
+ function createBoxPartElement(style: Map<string, string>, name: string, side: string, suffix: string): LitTemplate {
62
+ const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;
63
+ let value = style.get(propertyName);
64
+
65
+ if (value === '' || (name !== 'position' && value === 'unset')) {
66
+ value = '\u2012';
67
+ } else if (name === 'position' && value === 'auto') {
68
+ value = '\u2012';
69
+ }
70
+ value = value?.replace(/px$/, '');
71
+ value = value ? Platform.NumberUtilities.toFixedIfFloating(value) : value;
72
+ // clang-format off
73
+ return html`<div class=${side} jslog=${VisualLogging.value(propertyName).track({
74
+ dblclick: true, keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown', change: true,
75
+ })}
76
+ @dblclick=${(e: Event) => onStartEditing(e.currentTarget as Element, name, propertyName, style)}
77
+ .innerText=${live(value ?? '')}>
78
+ </div>`;
79
+ // clang-format on
80
+ }
81
+
82
+ // Display types for which margin is ignored.
83
+ const noMarginDisplayType = new Set<string>([
84
+ 'table-cell',
85
+ 'table-column',
86
+ 'table-column-group',
87
+ 'table-footer-group',
88
+ 'table-header-group',
89
+ 'table-row',
90
+ 'table-row-group',
91
+ ]);
92
+
93
+ // Display types for which padding is ignored.
94
+ const noPaddingDisplayType = new Set<string>([
95
+ 'table-column',
96
+ 'table-column-group',
97
+ 'table-footer-group',
98
+ 'table-header-group',
99
+ 'table-row',
100
+ 'table-row-group',
101
+ ]);
102
+
103
+ // Position types for which top, left, bottom and right are ignored.
104
+ const noPositionType = new Set<string>(['static']);
105
+
106
+ const boxes = ['content', 'padding', 'border', 'margin', 'position'];
107
+ const boxColors = [
108
+ Common.Color.PageHighlight.Content,
109
+ Common.Color.PageHighlight.Padding,
110
+ Common.Color.PageHighlight.Border,
111
+ Common.Color.PageHighlight.Margin,
112
+ Common.Color.Legacy.fromRGBA([0, 0, 0, 0]),
113
+ ];
114
+ const boxLabels = ['content', 'padding', 'border', 'margin', 'position'];
115
+ let previousBox: LitTemplate = nothing;
116
+ for (let i = 0; i < boxes.length; ++i) {
117
+ const name = boxes[i];
118
+ const display = style.get('display');
119
+ const position = style.get('position');
120
+ if (!display || !position) {
121
+ continue;
122
+ }
123
+ if (name === 'margin' && noMarginDisplayType.has(display)) {
124
+ continue;
125
+ }
126
+ if (name === 'padding' && noPaddingDisplayType.has(display)) {
127
+ continue;
128
+ }
129
+ if (name === 'position' && noPositionType.has(position)) {
130
+ continue;
131
+ }
132
+
133
+ const shouldHighlight = !node || highlightedMode === 'all' || name === highlightedMode;
134
+ const backgroundColor = boxColors[i].asString(Common.Color.Format.RGBA) || '';
135
+
136
+ const suffix = (name === 'border' ? '-width' : '');
137
+ // clang-format off
138
+ const box: LitTemplate = html`
139
+ <div
140
+ class="${name} ${shouldHighlight ? 'highlighted' : ''}"
141
+ style="background-color: ${shouldHighlight ? backgroundColor : ''}"
142
+ jslog=${VisualLogging.metricsBox().context(name).track({hover: true})}
143
+ @mouseover=${(e: Event) => {e.consume(); onHighlightNode(true, name === 'position' ? 'all' : name);}}>
144
+ ${name === 'content' ? html`
145
+ <span jslog=${VisualLogging.value('width').track({
146
+ dblclick: true,
147
+ keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',
148
+ change: true,
149
+ })}
150
+ @dblclick=${(e: Event) => onStartEditing(e.currentTarget as Element, 'width', 'width', style)}
151
+ .innerText=${live(contentWidth)}>
152
+ </span>
153
+ <span> × </span>
154
+ <span jslog=${VisualLogging.value('height').track({
155
+ dblclick: true,
156
+ keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',
157
+ change: true,
158
+ })}
159
+ @dblclick=${(e: Event) => onStartEditing(e.currentTarget as Element, 'height', 'height', style)}
160
+ .innerText=${live(contentHeight)}>
161
+ </span>` : html`
162
+ <div class="label">${boxLabels[i]}</div>
163
+ ${createBoxPartElement(style, name, 'top', suffix)}
164
+ <br>
165
+ ${createBoxPartElement(style, name, 'left', suffix)}
166
+ ${previousBox}
167
+ ${createBoxPartElement(style, name, 'right', suffix)}
168
+ <br>
169
+ ${createBoxPartElement(style, name, 'bottom', suffix)}`}
170
+ </div>`;
171
+ // clang-format on
172
+
173
+ previousBox = box;
174
+ }
175
+ // clang-format off
176
+ render(html`
177
+ <div class="metrics ${!node ? 'collapsed' : ''}" @mouseover=${(e: Event) => { e.consume(); onHighlightNode(true, 'all'); }}
178
+ @mouseleave=${(e: Event) => { e.consume(); onHighlightNode(false, 'all'); }}>
179
+ ${previousBox}
180
+ </div>`, target);
181
+ // clang-format on
182
+ };
183
+
48
184
  export class MetricsSidebarPane extends ElementsSidebarPane {
49
185
  originalPropertyData: SDK.CSSProperty.CSSProperty|null;
50
186
  previousPropertyDataCandidate: SDK.CSSProperty.CSSProperty|null;
@@ -52,9 +188,10 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
52
188
  private highlightMode: string;
53
189
  private computedStyle: Map<string, string>|null;
54
190
  private isEditingMetrics?: boolean;
191
+ private view: View;
55
192
 
56
- constructor(computedStyleModel: ComputedStyleModel) {
57
- super(computedStyleModel);
193
+ constructor(computedStyleModel: ComputedStyleModel, view = DEFAULT_VIEW) {
194
+ super(computedStyleModel, {jslog: `${VisualLogging.pane('styles-metrics')}`});
58
195
  this.registerRequiredCSS(metricsSidebarPaneStyles);
59
196
 
60
197
  this.originalPropertyData = null;
@@ -62,7 +199,7 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
62
199
  this.inlineStyle = null;
63
200
  this.highlightMode = '';
64
201
  this.computedStyle = null;
65
- this.contentElement.setAttribute('jslog', `${VisualLogging.pane('styles-metrics')}`);
202
+ this.view = view;
66
203
  }
67
204
 
68
205
  override async performUpdate(): Promise<void> {
@@ -76,8 +213,17 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
76
213
  const node = this.node();
77
214
  const cssModel = this.cssModel();
78
215
  if (!node || node.nodeType() !== Node.ELEMENT_NODE || !cssModel) {
79
- this.contentElement.removeChildren();
80
- this.element.classList.add('collapsed');
216
+ this.view(
217
+ {
218
+ style: new Map(),
219
+ highlightedMode: '',
220
+ node: null,
221
+ contentWidth: '',
222
+ contentHeight: '',
223
+ onHighlightNode: () => {},
224
+ onStartEditing: () => {},
225
+ },
226
+ undefined, this.contentElement);
81
227
  return await Promise.resolve();
82
228
  }
83
229
 
@@ -109,16 +255,6 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
109
255
  this.requestUpdate();
110
256
  }
111
257
 
112
- /**
113
- * Toggle the visibility of the Metrics pane. This toggle allows external
114
- * callers to control the visibility of this pane, but toggling this on does
115
- * not guarantee the pane will always show up, because the pane's visibility
116
- * is also controlled by the internal condition that style cannot be empty.
117
- */
118
- toggleVisibility(isVisible: boolean): void {
119
- this.element.classList.toggle('invisible', !isVisible);
120
- }
121
-
122
258
  private getPropertyValueAsPx(style: Map<string, string>, propertyName: string): number {
123
259
  const propertyValue = style.get(propertyName);
124
260
  if (!propertyValue) {
@@ -141,8 +277,7 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
141
277
  return {left, top, right, bottom};
142
278
  }
143
279
 
144
- private highlightDOMNode(showHighlight: boolean, mode: string, event: Event): void {
145
- event.consume();
280
+ private highlightDOMNode(showHighlight: boolean, mode: string): void {
146
281
  const node = this.node();
147
282
  if (showHighlight && node) {
148
283
  if (this.highlightMode === mode) {
@@ -160,175 +295,55 @@ export class MetricsSidebarPane extends ElementsSidebarPane {
160
295
  }
161
296
  }
162
297
 
163
- private updateMetrics(style: Map<string, string>, highlightedMode = 'all'): void {
164
- // Updating with computed style.
165
- const self = this;
166
-
167
- function createBoxPartElement(
168
- this: MetricsSidebarPane, style: Map<string, string>, name: string, side: string, suffix: string): LitTemplate {
169
- const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;
170
- let value = style.get(propertyName);
171
-
172
- if (value === '' || (name !== 'position' && value === 'unset')) {
173
- value = '\u2012';
174
- } else if (name === 'position' && value === 'auto') {
175
- value = '\u2012';
176
- }
177
- value = value?.replace(/px$/, '');
178
- value = value ? Platform.NumberUtilities.toFixedIfFloating(value) : value;
179
- // clang-format off
180
- return html`<div class=${side} jslog=${VisualLogging.value(propertyName).track({
181
- dblclick: true, keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown', change: true,
182
- })}
183
- @dblclick=${(e: Event) => this.startEditing(e.currentTarget, name, propertyName, style)}
184
- .innerText=${live(value ?? '')}>
185
- </div>`;
186
- // clang-format on
298
+ private getContentAreaWidthPx(style: Map<string, string>): string {
299
+ let width = style.get('width');
300
+ if (!width) {
301
+ return '';
187
302
  }
303
+ width = width.replace(/px$/, '');
304
+ const widthValue = Number(width);
305
+ if (!isNaN(widthValue) && style.get('box-sizing') === 'border-box') {
306
+ const borderBox = this.getBox(style, 'border');
307
+ const paddingBox = this.getBox(style, 'padding');
188
308
 
189
- function getContentAreaWidthPx(style: Map<string, string>): string {
190
- let width = style.get('width');
191
- if (!width) {
192
- return '';
193
- }
194
- width = width.replace(/px$/, '');
195
- const widthValue = Number(width);
196
- if (!isNaN(widthValue) && style.get('box-sizing') === 'border-box') {
197
- const borderBox = self.getBox(style, 'border');
198
- const paddingBox = self.getBox(style, 'padding');
199
-
200
- width = (widthValue - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right).toString();
201
- }
202
-
203
- return Platform.NumberUtilities.toFixedIfFloating(width);
309
+ width = (widthValue - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right).toString();
204
310
  }
205
311
 
206
- function getContentAreaHeightPx(style: Map<string, string>): string {
207
- let height = style.get('height');
208
- if (!height) {
209
- return '';
210
- }
211
- height = height.replace(/px$/, '');
212
- const heightValue = Number(height);
213
- if (!isNaN(heightValue) && style.get('box-sizing') === 'border-box') {
214
- const borderBox = self.getBox(style, 'border');
215
- const paddingBox = self.getBox(style, 'padding');
312
+ return Platform.NumberUtilities.toFixedIfFloating(width);
313
+ }
216
314
 
217
- height = (heightValue - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom).toString();
218
- }
315
+ private getContentAreaHeightPx(style: Map<string, string>): string {
316
+ let height = style.get('height');
317
+ if (!height) {
318
+ return '';
319
+ }
320
+ height = height.replace(/px$/, '');
321
+ const heightValue = Number(height);
322
+ if (!isNaN(heightValue) && style.get('box-sizing') === 'border-box') {
323
+ const borderBox = this.getBox(style, 'border');
324
+ const paddingBox = this.getBox(style, 'padding');
219
325
 
220
- return Platform.NumberUtilities.toFixedIfFloating(height);
326
+ height = (heightValue - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom).toString();
221
327
  }
222
328
 
223
- // Display types for which margin is ignored.
224
- const noMarginDisplayType = new Set<string>([
225
- 'table-cell',
226
- 'table-column',
227
- 'table-column-group',
228
- 'table-footer-group',
229
- 'table-header-group',
230
- 'table-row',
231
- 'table-row-group',
232
- ]);
233
-
234
- // Display types for which padding is ignored.
235
- const noPaddingDisplayType = new Set<string>([
236
- 'table-column',
237
- 'table-column-group',
238
- 'table-footer-group',
239
- 'table-header-group',
240
- 'table-row',
241
- 'table-row-group',
242
- ]);
243
-
244
- // Position types for which top, left, bottom and right are ignored.
245
- const noPositionType = new Set<string>(['static']);
246
-
247
- const boxes = ['content', 'padding', 'border', 'margin', 'position'];
248
- const boxColors = [
249
- Common.Color.PageHighlight.Content,
250
- Common.Color.PageHighlight.Padding,
251
- Common.Color.PageHighlight.Border,
252
- Common.Color.PageHighlight.Margin,
253
- Common.Color.Legacy.fromRGBA([0, 0, 0, 0]),
254
- ];
255
- const boxLabels = ['content', 'padding', 'border', 'margin', 'position'];
256
- let previousBox: LitTemplate = nothing;
257
- for (let i = 0; i < boxes.length; ++i) {
258
- const name = boxes[i];
259
- const display = style.get('display');
260
- const position = style.get('position');
261
- if (!display || !position) {
262
- continue;
263
- }
264
- if (name === 'margin' && noMarginDisplayType.has(display)) {
265
- continue;
266
- }
267
- if (name === 'padding' && noPaddingDisplayType.has(display)) {
268
- continue;
269
- }
270
- if (name === 'position' && noPositionType.has(position)) {
271
- continue;
272
- }
329
+ return Platform.NumberUtilities.toFixedIfFloating(height);
330
+ }
273
331
 
274
- const node = this.node();
275
- const shouldHighlight = !node || highlightedMode === 'all' || name === highlightedMode;
276
- const backgroundColor = boxColors[i].asString(Common.Color.Format.RGBA) || '';
277
-
278
- const suffix = (name === 'border' ? '-width' : '');
279
- // clang-format off
280
- const box: LitTemplate = html`
281
- <div
282
- class="${name} ${shouldHighlight ? 'highlighted' : ''}"
283
- style="background-color: ${shouldHighlight ? backgroundColor : ''}"
284
- jslog=${VisualLogging.metricsBox().context(name).track({hover: true})}
285
- @mouseover=${this.highlightDOMNode.bind(this, true, name === 'position' ? 'all' : name)}>
286
- ${name === 'content' ? html`
287
- <span jslog=${VisualLogging.value('width').track({
288
- dblclick: true,
289
- keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',
290
- change: true,
291
- })}
292
- @dblclick=${(e: Event) => this.startEditing(e.currentTarget, 'width', 'width', style)}
293
- .innerText=${live(getContentAreaWidthPx(style))}>
294
- </span>
295
- <span> × </span>
296
- <span jslog=${VisualLogging.value('height').track({
297
- dblclick: true,
298
- keydown: 'Enter|Escape|ArrowUp|ArrowDown|PageUp|PageDown',
299
- change: true,
300
- })}
301
- @dblclick=${(e: Event) => this.startEditing(e.currentTarget, 'height', 'height', style)}
302
- .innerText=${live(getContentAreaHeightPx(style))}>
303
- </span>` : html`
304
- <div class="label">${boxLabels[i]}</div>
305
- ${createBoxPartElement.call(this, style, name, 'top', suffix)}
306
- <br>
307
- ${createBoxPartElement.call(this, style, name, 'left', suffix)}
308
- ${previousBox}
309
- ${createBoxPartElement.call(this, style, name, 'right', suffix)}
310
- <br>
311
- ${createBoxPartElement.call(this, style, name, 'bottom', suffix)}`}
312
- </div>`;
313
- // clang-format on
314
-
315
- previousBox = box;
316
- }
317
- // clang-format off
318
- render(html`
319
- <div class="metrics" @mouseover=${this.highlightDOMNode.bind(this, false, 'all')}
320
- @mouseleave=${this.highlightDOMNode.bind(this, false, 'all')}>
321
- ${previousBox}
322
- </div>`, this.contentElement);
323
- // clang-format on
324
- this.element.classList.remove('collapsed');
332
+ private updateMetrics(style: Map<string, string>, highlightedMode = 'all'): void {
333
+ this.view(
334
+ {
335
+ style,
336
+ highlightedMode,
337
+ node: this.node(),
338
+ contentWidth: this.getContentAreaWidthPx(style),
339
+ contentHeight: this.getContentAreaHeightPx(style),
340
+ onHighlightNode: this.highlightDOMNode.bind(this),
341
+ onStartEditing: this.startEditing.bind(this),
342
+ },
343
+ undefined, this.contentElement);
325
344
  }
326
345
 
327
- startEditing(target: EventTarget|null, box: string, styleProperty: string, computedStyle: Map<string, string>): void {
328
- if (!(target instanceof Element)) {
329
- return;
330
- }
331
- const targetElement = target as Element;
346
+ startEditing(targetElement: Element, box: string, styleProperty: string, computedStyle: Map<string, string>): void {
332
347
  if (UI.UIUtils.isBeingEdited(targetElement)) {
333
348
  return;
334
349
  }
@@ -205,7 +205,7 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
205
205
  #updateComputedStylesAbortController?: AbortController;
206
206
 
207
207
  constructor(computedStyleModel: ComputedStyleModel) {
208
- super(computedStyleModel, true /* delegatesFocus */);
208
+ super(computedStyleModel, {delegatesFocus: true});
209
209
  this.setMinimumSize(96, 26);
210
210
  this.registerRequiredCSS(stylesSidebarPaneStyles);
211
211
  Common.Settings.Settings.instance().moduleSetting('text-editor-indent').addChangeListener(this.requestUpdate, this);
@@ -8,7 +8,7 @@
8
8
  font-size: 10px;
9
9
  text-align: center;
10
10
  white-space: nowrap;
11
- min-height: var(--metrics-height);
11
+ height: var(--metrics-height);
12
12
  display: flex;
13
13
  flex-direction: column;
14
14
  align-items: center;
@@ -26,19 +26,11 @@
26
26
 
27
27
  :host {
28
28
  --metrics-height: 190px;
29
-
30
- height: var(--metrics-height);
31
- contain: strict;
32
- }
33
-
34
- :host(.invisible) {
35
- visibility: hidden;
36
- height: 0;
37
29
  }
38
30
 
39
- :host(.collapsed) {
40
- visibility: collapse;
31
+ .metrics.collapsed {
41
32
  height: 0;
33
+ padding: 0;
42
34
  }
43
35
  /* The font we use on Windows takes up more vertical space, so adjust
44
36
  * the height of the metrics sidebar pane accordingly.
@@ -27,11 +27,6 @@ import type {KeybindsSettingsTab} from './KeybindsSettingsTab.js';
27
27
  import settingsScreenStyles from './settingsScreen.css.js';
28
28
 
29
29
  const UIStrings = {
30
-
31
- /**
32
- * @description Card header in Experiments settings tab that list all available unstable experiments that can be turned on or off.
33
- */
34
- unstableExperiments: 'Unstable experiments',
35
30
  /**
36
31
  * @description Name of the Settings view
37
32
  */
@@ -61,10 +56,6 @@ const UIStrings = {
61
56
  */
62
57
  greenDevUnstable:
63
58
  'Warning: All these features are prototype and very unstable. They exist for user testing and are not designed to be relied on.',
64
- /**
65
- * @description Message text content in Settings Screen of the Settings
66
- */
67
- theseExperimentsAreParticularly: 'Warning: These experiments are particularly unstable. Enable at your own risk.',
68
59
  /**
69
60
  * @description Message to display if a setting change requires a reload of DevTools
70
61
  */
@@ -392,7 +383,6 @@ export class GenericSettingsTab extends UI.Widget.VBox implements SettingsTab {
392
383
 
393
384
  export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTab {
394
385
  #experimentsSection: Card|undefined;
395
- #unstableExperimentsSection: Card|undefined;
396
386
  private readonly experimentToControl = new Map<Root.Runtime.Experiment, HTMLElement>();
397
387
  private readonly containerElement: HTMLElement;
398
388
 
@@ -427,45 +417,28 @@ export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTa
427
417
  if (this.#experimentsSection) {
428
418
  this.#experimentsSection.remove();
429
419
  }
430
- if (this.#unstableExperimentsSection) {
431
- this.#unstableExperimentsSection.remove();
432
- }
433
- const experiments = Root.Runtime.experiments.allConfigurableExperiments().sort();
434
- const unstableExperiments = experiments.filter(e => e.unstable && e.title.toLowerCase().includes(filterText));
435
- const stableExperiments = experiments.filter(e => !e.unstable && e.title.toLowerCase().includes(filterText));
436
- if (stableExperiments.length) {
420
+ const experiments = Root.Runtime.experiments.allConfigurableExperiments().sort((a, b) => {
421
+ return a.title.localeCompare(b.title);
422
+ });
423
+ const filteredExperiments = experiments.filter(e => e.title.toLowerCase().includes(filterText));
424
+ if (filteredExperiments.length) {
437
425
  const experimentsBlock = document.createElement('div');
438
426
  experimentsBlock.classList.add('settings-experiments-block');
439
427
  const warningMessage = i18nString(UIStrings.theseExperimentsCouldBeUnstable);
440
428
  const warningSection = this.createExperimentsWarningSubsection(warningMessage);
441
- for (const experiment of stableExperiments) {
429
+ for (const experiment of filteredExperiments) {
442
430
  experimentsBlock.appendChild(this.createExperimentCheckbox(experiment));
443
431
  }
444
432
  this.#experimentsSection =
445
433
  createSettingsCard(i18nString(UIStrings.experiments), warningSection, experimentsBlock);
446
434
  this.containerElement.appendChild(this.#experimentsSection);
447
- }
448
- if (unstableExperiments.length) {
449
- const experimentsBlock = document.createElement('div');
450
- experimentsBlock.classList.add('settings-experiments-block');
451
- const warningMessage = i18nString(UIStrings.theseExperimentsAreParticularly);
452
- for (const experiment of unstableExperiments) {
453
- experimentsBlock.appendChild(this.createExperimentCheckbox(experiment));
454
- }
455
- this.#unstableExperimentsSection = createSettingsCard(
456
- i18nString(UIStrings.unstableExperiments), this.createExperimentsWarningSubsection(warningMessage),
457
- experimentsBlock);
458
- this.containerElement.appendChild(this.#unstableExperimentsSection);
459
- }
460
- if (!stableExperiments.length && !unstableExperiments.length) {
435
+ UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.experimentsFound, {n: filteredExperiments.length}));
436
+ } else {
461
437
  const warning = document.createElement('span');
462
438
  warning.textContent = i18nString(UIStrings.noResults);
463
439
  UI.ARIAUtils.LiveAnnouncer.alert(warning.textContent);
464
440
  this.#experimentsSection = createSettingsCard(i18nString(UIStrings.experiments), warning);
465
441
  this.containerElement.appendChild(this.#experimentsSection);
466
- } else {
467
- UI.ARIAUtils.LiveAnnouncer.alert(
468
- i18nString(UIStrings.experimentsFound, {n: stableExperiments.length + unstableExperiments.length}));
469
442
  }
470
443
  }
471
444
 
@@ -495,9 +468,6 @@ export class ExperimentsSettingsTab extends UI.Widget.VBox implements SettingsTa
495
468
  const p = document.createElement('p');
496
469
  this.experimentToControl.set(experiment, p);
497
470
  p.classList.add('settings-experiment');
498
- if (experiment.unstable && !experiment.isEnabled()) {
499
- p.classList.add('settings-experiment-unstable');
500
- }
501
471
  p.appendChild(checkbox);
502
472
 
503
473
  const experimentLink = experiment.docLink;
@@ -146,10 +146,6 @@ devtools-button.link-icon {
146
146
  white-space: normal;
147
147
  }
148
148
 
149
- .settings-experiment-unstable {
150
- color: var(--sys-color-token-subtle);
151
- }
152
-
153
149
  .settings-experiment .feedback-link {
154
150
  color: var(--sys-color-primary);
155
151
  text-decoration-line: underline;