chrome-devtools-frontend 1.0.1537268 → 1.0.1538310

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 (98) hide show
  1. package/.env.template +10 -0
  2. package/docs/get_the_code.md +27 -0
  3. package/eslint.config.mjs +151 -149
  4. package/front_end/core/common/SettingRegistration.ts +10 -7
  5. package/front_end/core/common/Settings.ts +3 -0
  6. package/front_end/core/host/AidaClient.ts +1 -0
  7. package/front_end/core/host/UserMetrics.ts +3 -1
  8. package/front_end/core/root/Runtime.ts +8 -0
  9. package/front_end/core/sdk/sdk-meta.ts +8 -2
  10. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +4 -3
  11. package/front_end/generated/SupportedCSSProperties.js +1 -0
  12. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +23 -7
  13. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +110 -5
  14. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +50 -45
  15. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +151 -0
  16. package/front_end/models/ai_code_generation/ai_code_generation.ts +6 -0
  17. package/front_end/models/ai_code_generation/debug.ts +30 -0
  18. package/front_end/models/cpu_profile/ProfileTreeModel.ts +7 -7
  19. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +1 -1
  20. package/front_end/panels/application/PreloadingTreeElement.ts +10 -2
  21. package/front_end/panels/application/StorageView.ts +3 -2
  22. package/front_end/panels/application/components/BackForwardCacheView.ts +34 -51
  23. package/front_end/panels/application/components/OriginTrialTreeView.ts +141 -170
  24. package/front_end/panels/application/components/backForwardCacheView.css +4 -0
  25. package/front_end/panels/application/components/originTrialTreeView.css +37 -7
  26. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +2 -2
  27. package/front_end/panels/application/preloading/components/PreloadingString.ts +30 -1
  28. package/front_end/panels/autofill/AutofillView.ts +1 -1
  29. package/front_end/panels/console/ConsoleView.ts +11 -9
  30. package/front_end/panels/coverage/CoverageView.ts +1 -2
  31. package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +1 -1
  32. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
  33. package/front_end/panels/elements/ElementStatePaneWidget.ts +1 -1
  34. package/front_end/panels/elements/EventListenersWidget.ts +1 -2
  35. package/front_end/panels/elements/PropertiesWidget.ts +1 -1
  36. package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +1 -0
  37. package/front_end/panels/network/NetworkConfigView.ts +2 -1
  38. package/front_end/panels/network/NetworkItemView.ts +1 -1
  39. package/front_end/panels/network/NetworkPanel.ts +5 -4
  40. package/front_end/panels/network/NetworkWaterfallColumn.ts +5 -6
  41. package/front_end/panels/network/RequestCookiesView.ts +2 -1
  42. package/front_end/panels/network/RequestTimingView.ts +404 -348
  43. package/front_end/panels/network/networkTimingTable.css +22 -2
  44. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -2
  45. package/front_end/panels/sensors/SensorsView.ts +4 -3
  46. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +8 -6
  47. package/front_end/panels/settings/KeybindsSettingsTab.ts +3 -2
  48. package/front_end/panels/settings/SettingsScreen.ts +2 -1
  49. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  50. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +2 -1
  51. package/front_end/panels/sources/SourcesPanel.ts +2 -1
  52. package/front_end/panels/sources/sources-meta.ts +8 -1
  53. package/front_end/panels/timeline/TimelinePanel.ts +4 -3
  54. package/front_end/panels/timeline/TimelineUIUtils.ts +4 -20
  55. package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -0
  56. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +42 -3
  57. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +2 -0
  58. package/front_end/panels/timeline/components/networkRequestTooltip.css +19 -0
  59. package/front_end/third_party/chromium/README.chromium +1 -1
  60. package/front_end/ui/components/adorners/Adorner.ts +3 -1
  61. package/front_end/ui/components/buttons/Button.docs.ts +195 -0
  62. package/front_end/ui/components/icon_button/IconButton.ts +1 -0
  63. package/front_end/ui/components/settings/SettingCheckbox.ts +50 -14
  64. package/front_end/ui/components/settings/settingCheckbox.css +6 -1
  65. package/front_end/ui/components/spinners/Spinners.docs.ts +13 -0
  66. package/front_end/ui/components/tooltips/Tooltip.docs.ts +76 -0
  67. package/front_end/ui/legacy/FilterBar.ts +1 -2
  68. package/front_end/ui/legacy/RadioButton.docs.ts +41 -0
  69. package/front_end/ui/legacy/SelectMenu.docs.ts +98 -0
  70. package/front_end/ui/legacy/Toolbar.ts +4 -6
  71. package/front_end/ui/legacy/Treeoutline.ts +15 -0
  72. package/front_end/ui/legacy/UIUtils.ts +117 -1
  73. package/front_end/ui/legacy/Widget.ts +68 -38
  74. package/front_end/ui/legacy/XLink.ts +1 -0
  75. package/front_end/ui/legacy/components/inline_editor/Swatches.ts +1 -0
  76. package/front_end/ui/legacy/components/perf_ui/BrickBreaker.ts +1 -0
  77. package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +125 -0
  78. package/front_end/ui/legacy/components/settings_ui/settings_ui.ts +8 -0
  79. package/front_end/ui/legacy/legacy.ts +0 -2
  80. package/front_end/ui/legacy/popover.css +12 -11
  81. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  82. package/package.json +1 -1
  83. package/front_end/models/trace/lantern/testing/MetricTestUtils.ts +0 -62
  84. package/front_end/models/trace/lantern/testing/testing.ts +0 -5
  85. package/front_end/panels/application/components/badge.css +0 -25
  86. package/front_end/ui/components/docs/button/basic.html +0 -44
  87. package/front_end/ui/components/docs/button/basic.ts +0 -175
  88. package/front_end/ui/components/docs/radio_button/basic.html +0 -23
  89. package/front_end/ui/components/docs/radio_button/basic.ts +0 -50
  90. package/front_end/ui/components/docs/select_menu/basic.html +0 -19
  91. package/front_end/ui/components/docs/select_menu/basic.ts +0 -95
  92. package/front_end/ui/components/docs/select_menu/wide-option.html +0 -38
  93. package/front_end/ui/components/docs/select_menu/wide-option.ts +0 -43
  94. package/front_end/ui/components/docs/spinners/basic.html +0 -17
  95. package/front_end/ui/components/docs/spinners/basic.ts +0 -22
  96. package/front_end/ui/components/docs/tooltip/basic.html +0 -20
  97. package/front_end/ui/components/docs/tooltip/basic.ts +0 -82
  98. package/front_end/ui/legacy/SettingsUI.ts +0 -240
@@ -36,7 +36,7 @@
36
36
 
37
37
  import './Toolbar.js';
38
38
 
39
- import type * as Common from '../../core/common/common.js';
39
+ import * as Common from '../../core/common/common.js';
40
40
  import * as Host from '../../core/host/host.js';
41
41
  import * as i18n from '../../core/i18n/i18n.js';
42
42
  import * as Platform from '../../core/platform/platform.js';
@@ -1480,6 +1480,7 @@ export class DevToolsIconLabel extends HTMLElement {
1480
1480
  }
1481
1481
  }
1482
1482
 
1483
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
1483
1484
  customElements.define('dt-icon-label', DevToolsIconLabel);
1484
1485
 
1485
1486
  export class DevToolsSmallBubble extends HTMLElement {
@@ -1498,6 +1499,7 @@ export class DevToolsSmallBubble extends HTMLElement {
1498
1499
  }
1499
1500
  }
1500
1501
 
1502
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
1501
1503
  customElements.define('dt-small-bubble', DevToolsSmallBubble);
1502
1504
 
1503
1505
  export class DevToolsCloseButton extends HTMLElement {
@@ -1536,6 +1538,7 @@ export class DevToolsCloseButton extends HTMLElement {
1536
1538
  }
1537
1539
  }
1538
1540
 
1541
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
1539
1542
  customElements.define('dt-close-button', DevToolsCloseButton);
1540
1543
 
1541
1544
  export function bindInput(
@@ -2353,3 +2356,116 @@ export function copyTextToClipboard(text: string, alert?: string): void {
2353
2356
  export function getDevToolsBoundingElement(): HTMLElement {
2354
2357
  return InspectorView.maybeGetInspectorViewInstance()?.element || document.body;
2355
2358
  }
2359
+
2360
+ /**
2361
+ * @deprecated Prefer {@link bindToSetting} as this function leaks the checkbox via the setting listener.
2362
+ */
2363
+ export const bindCheckbox = function(
2364
+ input: CheckboxLabel, setting: Common.Settings.Setting<boolean>, metric?: UserMetricOptions): void {
2365
+ const setValue = bindCheckboxImpl(input, setting.set.bind(setting), metric);
2366
+ setting.addChangeListener(event => setValue(event.data));
2367
+ setValue(setting.get());
2368
+ };
2369
+
2370
+ export const bindCheckboxImpl = function(
2371
+ input: CheckboxLabel, apply: (value: boolean) => void, metric?: UserMetricOptions): (value: boolean) => void {
2372
+ input.addEventListener('change', onInputChanged, false);
2373
+
2374
+ function onInputChanged(): void {
2375
+ apply(input.checked);
2376
+
2377
+ if (input.checked && metric?.enable) {
2378
+ Host.userMetrics.actionTaken(metric.enable);
2379
+ }
2380
+
2381
+ if (!input.checked && metric?.disable) {
2382
+ Host.userMetrics.actionTaken(metric.disable);
2383
+ }
2384
+
2385
+ if (metric?.toggle) {
2386
+ Host.userMetrics.actionTaken(metric.toggle);
2387
+ }
2388
+ }
2389
+
2390
+ return function setValue(value: boolean): void {
2391
+ if (value !== input.checked) {
2392
+ input.checked = value;
2393
+ }
2394
+ };
2395
+ };
2396
+
2397
+ export const bindToSetting =
2398
+ (settingOrName: string|Common.Settings.Setting<boolean|string>|Common.Settings.RegExpSetting,
2399
+ stringValidator?: (newSettingValue: string) => boolean): ReturnType<typeof Directives.ref> => {
2400
+ const setting = typeof settingOrName === 'string' ?
2401
+ Common.Settings.Settings.instance().moduleSetting(settingOrName) :
2402
+ settingOrName;
2403
+
2404
+ // We can't use `setValue` as the change listener directly, otherwise we won't
2405
+ // be able to remove it again.
2406
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2407
+ let setValue: (value: any) => void;
2408
+ function settingChanged(): void {
2409
+ setValue(setting.get());
2410
+ }
2411
+
2412
+ if (setting.type() === Common.Settings.SettingType.BOOLEAN || typeof setting.defaultValue === 'boolean') {
2413
+ return Directives.ref(e => {
2414
+ if (e === undefined) {
2415
+ setting.removeChangeListener(settingChanged);
2416
+ return;
2417
+ }
2418
+
2419
+ setting.addChangeListener(settingChanged);
2420
+ setValue =
2421
+ bindCheckboxImpl(e as CheckboxLabel, (setting as Common.Settings.Setting<boolean>).set.bind(setting));
2422
+ setValue(setting.get());
2423
+ });
2424
+ }
2425
+
2426
+ if (setting.type() === Common.Settings.SettingType.REGEX || setting instanceof Common.Settings.RegExpSetting) {
2427
+ return Directives.ref(e => {
2428
+ if (e === undefined) {
2429
+ setting.removeChangeListener(settingChanged);
2430
+ return;
2431
+ }
2432
+
2433
+ setting.addChangeListener(settingChanged);
2434
+ setValue = bindInput(e as HTMLInputElement, setting.set.bind(setting), (value: string) => {
2435
+ try {
2436
+ new RegExp(value);
2437
+ return true;
2438
+ } catch {
2439
+ return false;
2440
+ }
2441
+ }, /* numeric */ false);
2442
+ setValue(setting.get());
2443
+ });
2444
+ }
2445
+
2446
+ if (typeof setting.defaultValue === 'string') {
2447
+ return Directives.ref(e => {
2448
+ if (e === undefined) {
2449
+ setting.removeChangeListener(settingChanged);
2450
+ return;
2451
+ }
2452
+
2453
+ setting.addChangeListener(settingChanged);
2454
+ setValue = bindInput(
2455
+ e as HTMLInputElement, setting.set.bind(setting), stringValidator ?? (() => true), /* numeric */ false);
2456
+ setValue(setting.get());
2457
+ });
2458
+ }
2459
+
2460
+ throw new Error(`Cannot infer type for setting '${setting.name}'`);
2461
+ };
2462
+
2463
+ /**
2464
+ * Track toggle action as a whole or
2465
+ * track on and off action separately.
2466
+ */
2467
+ export interface UserMetricOptions {
2468
+ toggle?: Host.UserMetrics.Action;
2469
+ enable?: Host.UserMetrics.Action;
2470
+ disable?: Host.UserMetrics.Action;
2471
+ }
@@ -35,7 +35,7 @@ import * as Platform from '../../core/platform/platform.js';
35
35
  import * as Geometry from '../../models/geometry/geometry.js';
36
36
  import * as Lit from '../../ui/lit/lit.js';
37
37
 
38
- import {createShadowRootWithCoreStyles} from './UIUtils.js';
38
+ import {cloneCustomElement, createShadowRootWithCoreStyles} from './UIUtils.js';
39
39
 
40
40
  // Remember the original DOM mutation methods here, since we
41
41
  // will override them below to sanity check the Widget system.
@@ -68,6 +68,64 @@ export function widgetConfig<F extends WidgetFactory<Widget>, ParamKeys extends
68
68
  return new WidgetConfig(widgetClass, widgetParams);
69
69
  }
70
70
 
71
+ let currentUpdateQueue: Map<Widget, PromiseWithResolvers<void>>|null = null;
72
+ const currentlyProcessed = new Set<Widget>();
73
+ let nextUpdateQueue = new Map<Widget, PromiseWithResolvers<void>>();
74
+ let pendingAnimationFrame: number|null = null;
75
+
76
+ function enqueueIntoNextUpdateQueue(widget: Widget): Promise<void> {
77
+ const scheduledUpdate = nextUpdateQueue.get(widget) ?? Promise.withResolvers<void>();
78
+ nextUpdateQueue.delete(widget);
79
+ nextUpdateQueue.set(widget, scheduledUpdate);
80
+ if (pendingAnimationFrame === null) {
81
+ pendingAnimationFrame = requestAnimationFrame(runNextUpdate);
82
+ }
83
+ return scheduledUpdate.promise;
84
+ }
85
+
86
+ function enqueueWidgetUpdate(widget: Widget): Promise<void> {
87
+ if (currentUpdateQueue) {
88
+ if (currentlyProcessed.has(widget)) {
89
+ return enqueueIntoNextUpdateQueue(widget);
90
+ }
91
+ const scheduledUpdate = currentUpdateQueue.get(widget) ?? Promise.withResolvers<void>();
92
+ currentUpdateQueue.delete(widget);
93
+ currentUpdateQueue.set(widget, scheduledUpdate);
94
+ return scheduledUpdate.promise;
95
+ }
96
+ return enqueueIntoNextUpdateQueue(widget);
97
+ }
98
+
99
+ function cancelUpdate(widget: Widget): void {
100
+ if (currentUpdateQueue) {
101
+ const scheduledUpdate = currentUpdateQueue.get(widget);
102
+ if (scheduledUpdate) {
103
+ scheduledUpdate.resolve();
104
+ currentUpdateQueue.delete(widget);
105
+ }
106
+ }
107
+ const scheduledUpdate = nextUpdateQueue.get(widget);
108
+ if (scheduledUpdate) {
109
+ scheduledUpdate.resolve();
110
+ nextUpdateQueue.delete(widget);
111
+ }
112
+ }
113
+
114
+ function runNextUpdate(): void {
115
+ pendingAnimationFrame = null;
116
+ currentUpdateQueue = nextUpdateQueue;
117
+ nextUpdateQueue = new Map();
118
+ for (const [widget, {resolve}] of currentUpdateQueue) {
119
+ currentlyProcessed.add(widget);
120
+ void (async () => {
121
+ await widget.performUpdate();
122
+ resolve();
123
+ })();
124
+ }
125
+ currentUpdateQueue = null;
126
+ currentlyProcessed.clear();
127
+ }
128
+
71
129
  export class WidgetElement<WidgetT extends Widget> extends HTMLElement {
72
130
  #widgetClass?: WidgetFactory<WidgetT>;
73
131
  #widgetParams?: Partial<WidgetT>;
@@ -169,12 +227,14 @@ export class WidgetElement<WidgetT extends Widget> extends HTMLElement {
169
227
  }
170
228
 
171
229
  override cloneNode(deep: boolean): Node {
172
- const clone = super.cloneNode(deep) as WidgetElement<WidgetT>;
230
+ const clone = cloneCustomElement(this, deep);
173
231
  if (!this.#widgetClass) {
174
232
  throw new Error('No widgetClass defined');
175
233
  }
176
- clone.#widgetClass = this.#widgetClass;
177
- clone.#widgetParams = this.#widgetParams;
234
+ clone.widgetConfig = {
235
+ widgetClass: this.#widgetClass,
236
+ widgetParams: this.#widgetParams,
237
+ };
178
238
  return clone;
179
239
  }
180
240
  }
@@ -218,8 +278,7 @@ function decrementWidgetCounter(parentElement: Element, childElement: Element):
218
278
  // The resolved `updateComplete` promise, which is used as a marker for the
219
279
  // Widget's `#updateComplete` private property to indicate that there's no
220
280
  // pending update.
221
- const UPDATE_COMPLETE = Promise.resolve(true);
222
- const UPDATE_COMPLETE_RESOLVE = (_result: boolean): void => {};
281
+ const UPDATE_COMPLETE = Promise.resolve();
223
282
 
224
283
  /**
225
284
  * Additional options passed to the `Widget` constructor to configure the
@@ -277,8 +336,6 @@ export class Widget {
277
336
  #invalidationsRequested?: boolean;
278
337
  #externallyManaged?: boolean;
279
338
  #updateComplete = UPDATE_COMPLETE;
280
- #updateCompleteResolve = UPDATE_COMPLETE_RESOLVE;
281
- #updateRequestID = 0;
282
339
 
283
340
  /**
284
341
  * Constructs a new `Widget` with the given `options`.
@@ -617,14 +674,7 @@ export class Widget {
617
674
  return;
618
675
  }
619
676
 
620
- // Cancel any pending update.
621
- if (this.#updateRequestID !== 0) {
622
- cancelAnimationFrame(this.#updateRequestID);
623
- this.#updateCompleteResolve(true);
624
- this.#updateCompleteResolve = UPDATE_COMPLETE_RESOLVE;
625
- this.#updateComplete = UPDATE_COMPLETE;
626
- this.#updateRequestID = 0;
627
- }
677
+ cancelUpdate(this);
628
678
 
629
679
  // hideOnDetach means that we should never remove element from dom - content
630
680
  // has iframes and detaching it will hurt.
@@ -876,21 +926,6 @@ export class Widget {
876
926
  performUpdate(): Promise<void>|void {
877
927
  }
878
928
 
879
- async #performUpdateCallback(): Promise<boolean> {
880
- // Mark this update cycle as complete by assigning
881
- // the marker sentinel.
882
- this.#updateComplete = UPDATE_COMPLETE;
883
- this.#updateCompleteResolve = UPDATE_COMPLETE_RESOLVE;
884
- this.#updateRequestID = 0;
885
-
886
- // Run the actual update logic.
887
- await this.performUpdate();
888
-
889
- // Resolve the `updateComplete` with `true` if no
890
- // new update was triggered during this cycle.
891
- return this.#updateComplete === UPDATE_COMPLETE;
892
- }
893
-
894
929
  /**
895
930
  * Schedules an asynchronous update for this widget.
896
931
  *
@@ -898,12 +933,7 @@ export class Widget {
898
933
  * frame.
899
934
  */
900
935
  requestUpdate(): void {
901
- if (this.#updateComplete === UPDATE_COMPLETE) {
902
- this.#updateComplete = new Promise((resolve, reject) => {
903
- this.#updateCompleteResolve = resolve;
904
- this.#updateRequestID = requestAnimationFrame(() => this.#performUpdateCallback().then(resolve, reject));
905
- });
906
- }
936
+ this.#updateComplete = enqueueWidgetUpdate(this);
907
937
  }
908
938
 
909
939
  /**
@@ -931,7 +961,7 @@ export class Widget {
931
961
  * updating, the value is `true` if there are no more pending updates,
932
962
  * and `false` if the update cycle triggered another update.
933
963
  */
934
- get updateComplete(): Promise<boolean> {
964
+ get updateComplete(): Promise<void> {
935
965
  return this.#updateComplete;
936
966
  }
937
967
  }
@@ -153,4 +153,5 @@ export class ContextMenuProvider implements Provider<Node> {
153
153
  }
154
154
  }
155
155
 
156
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
156
157
  customElements.define('x-link', XLink);
@@ -38,6 +38,7 @@ export class CSSShadowSwatch extends HTMLElement {
38
38
  }
39
39
  }
40
40
 
41
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
41
42
  customElements.define('css-shadow-swatch', CSSShadowSwatch);
42
43
 
43
44
  declare global {
@@ -602,4 +602,5 @@ declare global {
602
602
  }
603
603
  }
604
604
 
605
+ // eslint-disable-next-line @devtools/enforce-custom-element-prefix
605
606
  customElements.define('brick-breaker', BrickBreaker);
@@ -0,0 +1,125 @@
1
+ // Copyright 2014 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ /* eslint-disable @devtools/no-imperative-dom-api */
6
+
7
+ import * as Common from '../../../../core/common/common.js';
8
+ import * as i18n from '../../../../core/i18n/i18n.js';
9
+ import * as Platform from '../../../../core/platform/platform.js';
10
+ import * as Settings from '../../../components/settings/settings.js';
11
+ import * as VisualLogging from '../../../visual_logging/visual_logging.js';
12
+ import * as UI from '../../legacy.js';
13
+
14
+ const UIStrings = {
15
+ /**
16
+ * @description Note when a setting change will require the user to reload DevTools
17
+ */
18
+ srequiresReload: '*Requires reload',
19
+ /**
20
+ * @description Message to display if a setting change requires a reload of DevTools
21
+ */
22
+ oneOrMoreSettingsHaveChanged: 'One or more settings have changed which requires a reload to take effect',
23
+ } as const;
24
+ const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/settings_ui/SettingsUI.ts', UIStrings);
25
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
26
+
27
+ export function createSettingCheckbox(
28
+ name: Common.UIString.LocalizedString, setting: Common.Settings.Setting<boolean>,
29
+ tooltip?: string): UI.UIUtils.CheckboxLabel {
30
+ const label = UI.UIUtils.CheckboxLabel.create(name, undefined, undefined, setting.name);
31
+ label.name = name;
32
+ UI.UIUtils.bindCheckbox(label, setting);
33
+ if (tooltip) {
34
+ UI.Tooltip.Tooltip.install(label, tooltip);
35
+ }
36
+ return label;
37
+ }
38
+
39
+ const createSettingSelect = function(
40
+ name: string, options: Common.Settings.SimpleSettingOption[], requiresReload: boolean|null,
41
+ setting: Common.Settings.Setting<unknown>, subtitle?: string): HTMLElement {
42
+ const container = document.createElement('div');
43
+ const settingSelectElement = container.createChild('p');
44
+ settingSelectElement.classList.add('settings-select');
45
+ const label = settingSelectElement.createChild('label');
46
+ const select = settingSelectElement.createChild('select');
47
+ label.textContent = name;
48
+ if (subtitle) {
49
+ container.classList.add('chrome-select-label');
50
+ label.createChild('p').textContent = subtitle;
51
+ }
52
+ select.setAttribute('jslog', `${VisualLogging.dropDown().track({change: true}).context(setting.name)}`);
53
+ UI.ARIAUtils.bindLabelToControl(label, select);
54
+
55
+ for (const option of options) {
56
+ if (option.text && typeof option.value === 'string') {
57
+ select.add(
58
+ UI.UIUtils.createOption(option.text, option.value, Platform.StringUtilities.toKebabCase(option.value)));
59
+ }
60
+ }
61
+
62
+ let reloadWarning: HTMLElement|(Element | null) = (null as Element | null);
63
+ if (requiresReload) {
64
+ reloadWarning = container.createChild('p', 'reload-warning hidden');
65
+ reloadWarning.textContent = i18nString(UIStrings.srequiresReload);
66
+ UI.ARIAUtils.markAsAlert(reloadWarning);
67
+ }
68
+
69
+ const {deprecation} = setting;
70
+ if (deprecation) {
71
+ const warning = new Settings.SettingDeprecationWarning.SettingDeprecationWarning();
72
+ warning.data = deprecation;
73
+ label.appendChild(warning);
74
+ }
75
+
76
+ setting.addChangeListener(settingChanged);
77
+ settingChanged();
78
+ select.addEventListener('change', selectChanged, false);
79
+ return container;
80
+
81
+ function settingChanged(): void {
82
+ const newValue = setting.get();
83
+ for (let i = 0; i < options.length; i++) {
84
+ if (options[i].value === newValue) {
85
+ select.selectedIndex = i;
86
+ }
87
+ }
88
+ select.disabled = setting.disabled();
89
+ }
90
+
91
+ function selectChanged(): void {
92
+ // Don't use event.target.value to avoid conversion of the value to string.
93
+ setting.set(options[select.selectedIndex].value);
94
+ if (reloadWarning) {
95
+ reloadWarning.classList.remove('hidden');
96
+ UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(
97
+ i18nString(UIStrings.oneOrMoreSettingsHaveChanged));
98
+ }
99
+ }
100
+ };
101
+
102
+ export const createControlForSetting = function(
103
+ setting: Common.Settings.Setting<unknown>, subtitle?: string): HTMLElement|null {
104
+ const uiTitle = setting.title();
105
+ switch (setting.type()) {
106
+ case Common.Settings.SettingType.BOOLEAN: {
107
+ const component = new Settings.SettingCheckbox.SettingCheckbox();
108
+ component.data = {
109
+ setting: setting as Common.Settings.Setting<boolean>,
110
+ };
111
+ component.onchange = () => {
112
+ if (setting.reloadRequired()) {
113
+ UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(
114
+ i18nString(UIStrings.oneOrMoreSettingsHaveChanged));
115
+ }
116
+ };
117
+ return component;
118
+ }
119
+ case Common.Settings.SettingType.ENUM:
120
+ return createSettingSelect(uiTitle, setting.options(), setting.reloadRequired(), setting, subtitle);
121
+ default:
122
+ console.error('Invalid setting type: ' + setting.type());
123
+ return null;
124
+ }
125
+ };
@@ -0,0 +1,8 @@
1
+
2
+ // Copyright 2025 The Chromium Authors
3
+ // Use of this source code is governed by a BSD-style license that can be
4
+ // found in the LICENSE file.
5
+
6
+ import * as SettingsUI from './SettingsUI.js';
7
+
8
+ export {SettingsUI};
@@ -33,7 +33,6 @@ import * as ReportView from './ReportView.js';
33
33
  import * as ResizerWidget from './ResizerWidget.js';
34
34
  import * as RootView from './RootView.js';
35
35
  import * as SearchableView from './SearchableView.js';
36
- import * as SettingsUI from './SettingsUI.js';
37
36
  import * as ShortcutRegistry from './ShortcutRegistry.js';
38
37
  import * as SoftContextMenu from './SoftContextMenu.js';
39
38
  import * as SoftDropDown from './SoftDropDown.js';
@@ -85,7 +84,6 @@ export {
85
84
  ResizerWidget,
86
85
  RootView,
87
86
  SearchableView,
88
- SettingsUI,
89
87
  ShortcutRegistry,
90
88
  SoftContextMenu,
91
89
  SoftDropDown,
@@ -3,17 +3,18 @@
3
3
  * Use of this source code is governed by a BSD-style license that can be
4
4
  * found in the LICENSE file.
5
5
  */
6
-
7
- .widget {
8
- display: flex;
9
- font: var(--sys-typescale-body4-regular);
10
- box-shadow: var(--sys-elevation-level2);
11
- color: var(--sys-color-on-surface);
12
- background-color: var(--sys-color-base-container-elevated);
13
- border-radius: var(--sys-shape-corner-small);
14
- padding: var(--sys-size-4);
15
- user-select: text;
16
- overflow: auto;
6
+ @scope to (.widget > *) {
7
+ .widget {
8
+ display: flex;
9
+ font: var(--sys-typescale-body4-regular);
10
+ box-shadow: var(--sys-elevation-level2);
11
+ color: var(--sys-color-on-surface);
12
+ background-color: var(--sys-color-base-container-elevated);
13
+ border-radius: var(--sys-shape-corner-small);
14
+ padding: var(--sys-size-4);
15
+ user-select: text;
16
+ overflow: auto;
17
+ }
17
18
  }
18
19
 
19
20
  .squiggles-content {
@@ -681,6 +681,7 @@ export const knownContextValues = new Set([
681
681
  'ca',
682
682
  'cache-control',
683
683
  'cache-disabled',
684
+ 'cache-disabled-documentation',
684
685
  'cache-disabled-true',
685
686
  'cache-storage',
686
687
  'cache-storage-data',
@@ -2647,6 +2648,7 @@ export const knownContextValues = new Set([
2647
2648
  'network.clear',
2648
2649
  'network.config',
2649
2650
  'network.enable-remote-file-loading',
2651
+ 'network.enable-remote-file-loading-documentation',
2650
2652
  'network.enable-request-blocking',
2651
2653
  'network.group-by-frame',
2652
2654
  'network.group-by-frame-false',
@@ -4128,6 +4130,7 @@ export const knownContextValues = new Set([
4128
4130
  'warning',
4129
4131
  'wasm',
4130
4132
  'wasm-auto-stepping',
4133
+ 'wasm-auto-stepping-documentation',
4131
4134
  'wasm-auto-stepping-false',
4132
4135
  'watch',
4133
4136
  'watch-test-expression',
package/package.json CHANGED
@@ -102,5 +102,5 @@
102
102
  "flat-cache": "6.1.12"
103
103
  }
104
104
  },
105
- "version": "1.0.1537268"
105
+ "version": "1.0.1538310"
106
106
  }
@@ -1,62 +0,0 @@
1
- // Copyright 2024 The Chromium Authors
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
-
5
- // Unsure why this lint is failing, given `lantern/metrics/SpeedIndex.test.ts` does the same
6
- // and is fine. Maybe `*.test.*` files are excluded from this rule?
7
- // eslint-disable-next-line @devtools/es-modules-import
8
- import * as TraceLoader from '../../../../testing/TraceLoader.js';
9
- import * as Trace from '../../trace.js';
10
- import * as Lantern from '../lantern.js';
11
-
12
- function toLanternTrace(traceEvents: readonly Trace.Types.Events.Event[]): Lantern.Types.Trace {
13
- return {
14
- traceEvents: traceEvents as unknown as Lantern.Types.TraceEvent[],
15
- };
16
- }
17
-
18
- async function runTraceProcessor(context: Mocha.Suite|Mocha.Context, trace: Lantern.Types.Trace) {
19
- TraceLoader.TraceLoader.setTestTimeout(context);
20
-
21
- const processor = Trace.Processor.TraceProcessor.createWithAllHandlers();
22
- await processor.parse(trace.traceEvents as Trace.Types.Events.Event[], {isCPUProfile: false, isFreshRecording: true});
23
- if (!processor.data) {
24
- throw new Error('No data');
25
- }
26
- return processor.data;
27
- }
28
-
29
- async function getComputationDataFromFixture(context: Mocha.Suite|Mocha.Context, {trace, settings, url}: {
30
- trace: Lantern.Types.Trace,
31
- settings?: Lantern.Types.Simulation.Settings,
32
- url?: Lantern.Types.Simulation.URL,
33
- }) {
34
- settings = settings ?? {} as Lantern.Types.Simulation.Settings;
35
- if (!settings.throttlingMethod) {
36
- settings.throttlingMethod = 'simulate';
37
- }
38
- const data = await runTraceProcessor(context, trace);
39
- const requests = Trace.LanternComputationData.createNetworkRequests(trace, data);
40
- const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
41
- if (!networkAnalysis) {
42
- throw new Error('no networkAnalysis');
43
- }
44
-
45
- const frameId = data.Meta.mainFrameId;
46
- const navigationId = data.Meta.mainFrameNavigations[0].args.data?.navigationId;
47
- if (!navigationId) {
48
- throw new Error('no navigation id found');
49
- }
50
-
51
- return {
52
- simulator: Lantern.Simulation.Simulator.createSimulator({...settings, networkAnalysis}),
53
- graph: Trace.LanternComputationData.createGraph(requests, trace, data, url),
54
- processedNavigation: Trace.LanternComputationData.createProcessedNavigation(data, frameId, navigationId),
55
- };
56
- }
57
-
58
- export {
59
- getComputationDataFromFixture,
60
- runTraceProcessor as runTrace,
61
- toLanternTrace,
62
- };
@@ -1,5 +0,0 @@
1
- // Copyright 2024 The Chromium Authors
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
-
5
- export * from './MetricTestUtils.js';
@@ -1,25 +0,0 @@
1
- /*
2
- * Copyright 2021 The Chromium Authors
3
- * Use of this source code is governed by a BSD-style license that can be
4
- * found in the LICENSE file.
5
- */
6
-
7
- :host .badge-error {
8
- --override-adorner-text-color: var(--sys-color-error-bright);
9
- --override-adorner-border-color: var(--sys-color-error-bright);
10
- }
11
-
12
- :host .badge-success {
13
- --override-adorner-text-color: var(--sys-color-tertiary);
14
- --override-adorner-border-color: var(--sys-color-tertiary);
15
- }
16
-
17
- :host .badge-secondary {
18
- --override-adorner-text-color: var(--sys-color-token-subtle);
19
- --override-adorner-border-color: var(--sys-color-token-subtle);
20
- }
21
-
22
- /* Use mono-space source code font to assist reading of adorner content */
23
- :host devtools-adorner {
24
- font-family: var(--source-code-font-family);
25
- }