chrome-devtools-frontend 1.0.1618066 → 1.0.1621064

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 (54) hide show
  1. package/docs/checklist/README.md +8 -7
  2. package/eslint.config.mjs +7 -0
  3. package/front_end/core/sdk/NetworkManager.ts +23 -2
  4. package/front_end/core/sdk/ServerSentEventsProtocol.ts +1 -1
  5. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +119 -13
  6. package/front_end/generated/InspectorBackendCommands.ts +6 -6
  7. package/front_end/generated/SupportedCSSProperties.js +100 -100
  8. package/front_end/generated/protocol-mapping.d.ts +1 -9
  9. package/front_end/generated/protocol-proxy-api.d.ts +1 -9
  10. package/front_end/generated/protocol.ts +5 -0
  11. package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +512 -0
  12. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +65 -85
  13. package/front_end/models/ai_assistance/agents/StylingAgent.ts +9 -16
  14. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  15. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +21 -4
  16. package/front_end/models/bindings/SymbolizedError.ts +69 -2
  17. package/front_end/models/javascript_metadata/NativeFunctions.js +2 -2
  18. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +11 -3
  19. package/front_end/models/stack_trace/ErrorStackParser.ts +18 -0
  20. package/front_end/panels/ai_assistance/components/ChatMessage.ts +84 -2
  21. package/front_end/panels/ai_assistance/components/WalkthroughUtils.ts +1 -1
  22. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +9 -2
  23. package/front_end/panels/application/WebMCPView.ts +212 -89
  24. package/front_end/panels/application/webMCPView.css +260 -199
  25. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +9 -5
  26. package/front_end/panels/changes/ChangesSidebar.ts +2 -2
  27. package/front_end/panels/changes/ChangesView.ts +4 -7
  28. package/front_end/panels/console/ConsoleViewMessage.ts +1 -19
  29. package/front_end/panels/coverage/CoverageView.ts +4 -5
  30. package/front_end/panels/elements/ElementsPanel.ts +9 -12
  31. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  32. package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +19 -20
  33. package/front_end/panels/elements/components/ElementsBreadcrumbsUtils.ts +29 -29
  34. package/front_end/panels/elements/components/QueryContainer.ts +5 -6
  35. package/front_end/panels/elements/components/components.ts +0 -2
  36. package/front_end/panels/emulation/MediaQueryInspector.ts +4 -7
  37. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +47 -66
  38. package/front_end/panels/network/RequestConditionsDrawer.ts +6 -4
  39. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +6 -9
  40. package/front_end/panels/protocol_monitor/JSONEditor.ts +2 -2
  41. package/front_end/panels/search/SearchView.ts +4 -7
  42. package/front_end/panels/sources/DebuggerPausedMessage.ts +18 -22
  43. package/front_end/panels/sources/ThreadsSidebarPane.ts +2 -4
  44. package/front_end/panels/web_audio/WebAudioView.ts +5 -4
  45. package/front_end/third_party/chromium/README.chromium +1 -1
  46. package/front_end/ui/components/icon_button/iconButton.css +1 -0
  47. package/front_end/ui/components/lists/list.css +4 -0
  48. package/front_end/ui/legacy/ViewRegistration.ts +2 -2
  49. package/front_end/ui/legacy/Widget.ts +9 -2
  50. package/front_end/ui/legacy/components/utils/Linkifier.ts +32 -11
  51. package/front_end/ui/visual_logging/KnownContextValues.ts +17 -0
  52. package/package.json +1 -1
  53. package/front_end/Images/src/dots-circle.svg +0 -10
  54. package/front_end/panels/elements/components/Helper.ts +0 -35
@@ -544,16 +544,15 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
544
544
  }
545
545
 
546
546
  if (selectedNode) {
547
- const activeNode = ElementsComponents.Helper.legacyNodeToElementsComponentsNode(selectedNode);
548
- const crumbs = [activeNode];
547
+ const crumbs = [selectedNode];
549
548
 
550
549
  for (let current: (SDK.DOMModel.DOMNode|null) = selectedNode.parentNode; current; current = current.parentNode) {
551
- crumbs.push(ElementsComponents.Helper.legacyNodeToElementsComponentsNode(current));
550
+ crumbs.push(current);
552
551
  }
553
552
 
554
553
  this.breadcrumbs.data = {
555
554
  crumbs,
556
- selectedNode: ElementsComponents.Helper.legacyNodeToElementsComponentsNode(selectedNode),
555
+ selectedNode,
557
556
  };
558
557
 
559
558
  if (this.accessibilityTreeView) {
@@ -938,16 +937,14 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
938
937
  */
939
938
 
940
939
  // Get the current set of active crumbs
941
- const activeNode = ElementsComponents.Helper.legacyNodeToElementsComponentsNode(selectedNode);
942
- const existingCrumbs = [activeNode];
940
+ const existingCrumbs = [selectedNode];
943
941
  for (let current: (SDK.DOMModel.DOMNode|null) = selectedNode.parentNode; current; current = current.parentNode) {
944
- existingCrumbs.push(ElementsComponents.Helper.legacyNodeToElementsComponentsNode(current));
942
+ existingCrumbs.push(current);
945
943
  }
946
944
 
947
945
  /* Get the change nodes from the event & convert them to breadcrumb nodes */
948
- const newNodes = nodes.map(ElementsComponents.Helper.legacyNodeToElementsComponentsNode);
949
- const nodesThatHaveChangedMap = new Map<number, ElementsComponents.Helper.DOMNode>();
950
- newNodes.forEach(crumb => nodesThatHaveChangedMap.set(crumb.id, crumb));
946
+ const nodesThatHaveChangedMap = new Map<Protocol.DOM.NodeId, SDK.DOMModel.DOMNode>();
947
+ nodes.forEach(crumb => nodesThatHaveChangedMap.set(crumb.id, crumb));
951
948
 
952
949
  /* Loop over our existing crumbs, and if any have an ID that matches an ID from the new nodes
953
950
  * that we have, use the new node, rather than the one we had, because it's changed.
@@ -959,12 +956,12 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
959
956
 
960
957
  this.breadcrumbs.data = {
961
958
  crumbs: newSetOfCrumbs,
962
- selectedNode: activeNode,
959
+ selectedNode,
963
960
  };
964
961
  }
965
962
 
966
963
  private crumbNodeSelected(event: ElementsComponents.ElementsBreadcrumbs.NodeSelectedEvent): void {
967
- this.selectDOMNode(event.legacyDomNode, true);
964
+ this.selectDOMNode(event.node, true);
968
965
  }
969
966
 
970
967
  private leaveUserAgentShadowDOM(node: SDK.DOMModel.DOMNode): SDK.DOMModel.DOMNode {
@@ -1181,7 +1181,7 @@ export class StylePropertiesSection {
1181
1181
 
1182
1182
  const containerElement = new ElementsComponents.QueryContainer.QueryContainer();
1183
1183
  containerElement.data = {
1184
- container: ElementsComponents.Helper.legacyNodeToElementsComponentsNode(container.containerNode),
1184
+ container: container.containerNode,
1185
1185
  queryName: containerQuery.name,
1186
1186
  onContainerLinkClick: event => {
1187
1187
  event.preventDefault();
@@ -7,7 +7,7 @@ import '../../../ui/kit/kit.js';
7
7
  import '../../../ui/components/node_text/node_text.js';
8
8
 
9
9
  import * as i18n from '../../../core/i18n/i18n.js';
10
- import type * as SDK from '../../../core/sdk/sdk.js';
10
+ import * as SDK from '../../../core/sdk/sdk.js';
11
11
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
12
12
  import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
13
13
  import * as Lit from '../../../ui/lit/lit.js';
@@ -15,7 +15,6 @@ import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
15
15
 
16
16
  import elementsBreadcrumbsStyles from './elementsBreadcrumbs.css.js';
17
17
  import {crumbsToRender, type UserScrollPosition} from './ElementsBreadcrumbsUtils.js';
18
- import type {DOMNode} from './Helper.js';
19
18
 
20
19
  const {html} = Lit;
21
20
 
@@ -39,25 +38,25 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
39
38
 
40
39
  export class NodeSelectedEvent extends Event {
41
40
  static readonly eventName = 'breadcrumbsnodeselected';
42
- legacyDomNode: SDK.DOMModel.DOMNode;
41
+ node: SDK.DOMModel.DOMNode;
43
42
 
44
- constructor(node: DOMNode) {
43
+ constructor(node: SDK.DOMModel.DOMNode) {
45
44
  super(NodeSelectedEvent.eventName, {});
46
- this.legacyDomNode = node.legacyDomNode;
45
+ this.node = node;
47
46
  }
48
47
  }
49
48
 
50
49
  export interface ElementsBreadcrumbsData {
51
- selectedNode: DOMNode|null;
52
- crumbs: DOMNode[];
50
+ selectedNode: SDK.DOMModel.DOMNode|null;
51
+ crumbs: SDK.DOMModel.DOMNode[];
53
52
  }
54
53
 
55
54
  export class ElementsBreadcrumbs extends HTMLElement {
56
55
  readonly #shadow = this.attachShadow({mode: 'open'});
57
56
  readonly #resizeObserver = new ResizeObserver(() => this.#checkForOverflowOnResize());
58
57
 
59
- #crumbsData: readonly DOMNode[] = [];
60
- #selectedDOMNode: Readonly<DOMNode>|null = null;
58
+ #crumbsData: readonly SDK.DOMModel.DOMNode[] = [];
59
+ #selectedDOMNode: SDK.DOMModel.DOMNode|null = null;
61
60
  #overflowing = false;
62
61
  #userScrollPosition: UserScrollPosition = 'start';
63
62
  #isObservingResize = false;
@@ -75,7 +74,7 @@ export class ElementsBreadcrumbs extends HTMLElement {
75
74
  this.#resizeObserver.disconnect();
76
75
  }
77
76
 
78
- #onCrumbClick(node: DOMNode): (event: Event) => void {
77
+ #onCrumbClick(node: SDK.DOMModel.DOMNode): (event: Event) => void {
79
78
  return (event: Event): void => {
80
79
  event.preventDefault();
81
80
  this.dispatchEvent(new NodeSelectedEvent(node));
@@ -121,20 +120,20 @@ export class ElementsBreadcrumbs extends HTMLElement {
121
120
  void this.#updateScrollState(crumbWindow);
122
121
  }
123
122
 
124
- #onCrumbMouseMove(node: DOMNode): () => void {
125
- return (): void => node.highlightNode();
123
+ #onCrumbMouseMove(node: SDK.DOMModel.DOMNode): () => void {
124
+ return (): void => node.highlight();
126
125
  }
127
126
 
128
- #onCrumbMouseLeave(node: DOMNode): () => void {
129
- return (): void => node.clearHighlight();
127
+ #onCrumbMouseLeave(): void {
128
+ SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();
130
129
  }
131
130
 
132
- #onCrumbFocus(node: DOMNode): () => void {
133
- return (): void => node.highlightNode();
131
+ #onCrumbFocus(node: SDK.DOMModel.DOMNode): () => void {
132
+ return (): void => node.highlight();
134
133
  }
135
134
 
136
- #onCrumbBlur(node: DOMNode): () => void {
137
- return (): void => node.clearHighlight();
135
+ #onCrumbBlur(): void {
136
+ SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();
138
137
  }
139
138
 
140
139
  #engageResizeObserver(): void {
@@ -306,9 +305,9 @@ export class ElementsBreadcrumbs extends HTMLElement {
306
305
  jslog=${VisualLogging.item().track({click:true, resize:true})}
307
306
  @click=${this.#onCrumbClick(crumb.node)}
308
307
  @mousemove=${this.#onCrumbMouseMove(crumb.node)}
309
- @mouseleave=${this.#onCrumbMouseLeave(crumb.node)}
308
+ @mouseleave=${this.#onCrumbMouseLeave}
310
309
  @focus=${this.#onCrumbFocus(crumb.node)}
311
- @blur=${this.#onCrumbBlur(crumb.node)}
310
+ @blur=${this.#onCrumbBlur}
312
311
  >
313
312
  <devtools-node-text data-node-title=${crumb.title.main} .data=${{
314
313
  nodeTitle: crumb.title.main,
@@ -3,8 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as i18n from '../../../core/i18n/i18n.js';
6
-
7
- import type {DOMNode} from './Helper.js';
6
+ import type * as SDK from '../../../core/sdk/sdk.js';
8
7
 
9
8
  const UIStrings = {
10
9
  /**
@@ -21,8 +20,7 @@ export type UserScrollPosition = 'start'|'middle'|'end';
21
20
  export interface Crumb {
22
21
  title: CrumbTitle;
23
22
  selected: boolean;
24
- node: DOMNode;
25
- originalNode: unknown;
23
+ node: SDK.DOMModel.DOMNode;
26
24
  }
27
25
 
28
26
  export interface CrumbTitle {
@@ -30,25 +28,25 @@ export interface CrumbTitle {
30
28
  extras: {id?: string, classes?: string[]};
31
29
  }
32
30
 
33
- export const crumbsToRender = (crumbs: readonly DOMNode[], selectedNode: Readonly<DOMNode>|null): Crumb[] => {
34
- if (!selectedNode) {
35
- return [];
36
- }
31
+ export const crumbsToRender =
32
+ (crumbs: readonly SDK.DOMModel.DOMNode[], selectedNode: SDK.DOMModel.DOMNode|null): Crumb[] => {
33
+ if (!selectedNode) {
34
+ return [];
35
+ }
37
36
 
38
- return crumbs
39
- .filter(crumb => {
40
- return crumb.nodeType !== Node.DOCUMENT_NODE;
41
- })
42
- .map(crumb => {
43
- return {
44
- title: determineElementTitle(crumb),
45
- selected: crumb.id === selectedNode.id,
46
- node: crumb,
47
- originalNode: crumb.legacyDomNode,
48
- };
49
- })
50
- .reverse();
51
- };
37
+ return crumbs
38
+ .filter(crumb => {
39
+ return crumb.nodeType() !== Node.DOCUMENT_NODE;
40
+ })
41
+ .map(crumb => {
42
+ return {
43
+ title: determineElementTitle(crumb),
44
+ selected: crumb.id === selectedNode.id,
45
+ node: crumb,
46
+ };
47
+ })
48
+ .reverse();
49
+ };
52
50
 
53
51
  const makeCrumbTitle = (main: string, extras = {}): CrumbTitle => {
54
52
  return {
@@ -57,13 +55,15 @@ const makeCrumbTitle = (main: string, extras = {}): CrumbTitle => {
57
55
  };
58
56
  };
59
57
 
60
- export const determineElementTitle = (domNode: DOMNode): CrumbTitle => {
61
- switch (domNode.nodeType) {
58
+ export const determineElementTitle = (domNode: SDK.DOMModel.DOMNode): CrumbTitle => {
59
+ const nodeType = domNode.nodeType();
60
+ switch (nodeType) {
62
61
  case Node.ELEMENT_NODE: {
63
- if (domNode.pseudoType) {
64
- return makeCrumbTitle('::' + domNode.pseudoType);
62
+ const pseudoType = domNode.pseudoType();
63
+ if (pseudoType) {
64
+ return makeCrumbTitle('::' + pseudoType);
65
65
  }
66
- const crumbTitle = makeCrumbTitle(domNode.nodeNameNicelyCased);
66
+ const crumbTitle = makeCrumbTitle(domNode.nodeNameInCorrectCase());
67
67
 
68
68
  const id = domNode.getAttribute('id');
69
69
  if (id) {
@@ -86,8 +86,8 @@ export const determineElementTitle = (domNode: DOMNode): CrumbTitle => {
86
86
  case Node.DOCUMENT_TYPE_NODE:
87
87
  return makeCrumbTitle('<!doctype>');
88
88
  case Node.DOCUMENT_FRAGMENT_NODE:
89
- return makeCrumbTitle(domNode.shadowRootType ? '#shadow-root' : domNode.nodeNameNicelyCased);
89
+ return makeCrumbTitle(domNode.shadowRootType() ? '#shadow-root' : domNode.nodeNameInCorrectCase());
90
90
  default:
91
- return makeCrumbTitle(domNode.nodeNameNicelyCased);
91
+ return makeCrumbTitle(domNode.nodeNameInCorrectCase());
92
92
  }
93
93
  };
@@ -10,7 +10,6 @@ import * as SDK from '../../../core/sdk/sdk.js';
10
10
  import * as Lit from '../../../ui/lit/lit.js';
11
11
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
12
12
 
13
- import type {DOMNode} from './Helper.js';
14
13
  import queryContainerStyles from './queryContainer.css.js';
15
14
 
16
15
  const {render, html} = Lit;
@@ -24,7 +23,7 @@ export class QueriedSizeRequestedEvent extends Event {
24
23
  }
25
24
 
26
25
  export interface QueryContainerData {
27
- container: DOMNode;
26
+ container: SDK.DOMModel.DOMNode;
28
27
  queryName?: string;
29
28
  onContainerLinkClick: (event: Event) => void;
30
29
  }
@@ -32,7 +31,7 @@ export interface QueryContainerData {
32
31
  export class QueryContainer extends HTMLElement {
33
32
  readonly #shadow = this.attachShadow({mode: 'open'});
34
33
  #queryName?: string;
35
- #container?: DOMNode;
34
+ #container?: SDK.DOMModel.DOMNode;
36
35
  #onContainerLinkClick?: (event: Event) => void;
37
36
  #isContainerLinkHovered = false;
38
37
  #queriedSizeDetails?: SDK.CSSContainerQuery.ContainerQueriedSizeDetails;
@@ -50,13 +49,13 @@ export class QueryContainer extends HTMLElement {
50
49
  }
51
50
 
52
51
  async #onContainerLinkMouseEnter(): Promise<void> {
53
- this.#container?.highlightNode('container-outline');
52
+ this.#container?.highlight('container-outline');
54
53
  this.#isContainerLinkHovered = true;
55
54
  this.dispatchEvent(new QueriedSizeRequestedEvent());
56
55
  }
57
56
 
58
57
  #onContainerLinkMouseLeave(): void {
59
- this.#container?.clearHighlight();
58
+ SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();
60
59
  this.#isContainerLinkHovered = false;
61
60
  this.#render();
62
61
  }
@@ -72,7 +71,7 @@ export class QueryContainer extends HTMLElement {
72
71
  classesToDisplay = this.#container.getAttribute('class')?.split(/\s+/).filter(Boolean);
73
72
  }
74
73
 
75
- const nodeTitle = this.#queryName || this.#container.nodeNameNicelyCased;
74
+ const nodeTitle = this.#queryName || this.#container.nodeNameInCorrectCase();
76
75
 
77
76
  // Disabled until https://crbug.com/1079231 is fixed.
78
77
  // clang-format off
@@ -14,7 +14,6 @@ import * as CSSVariableValueView from './CSSVariableValueView.js';
14
14
  import * as ElementsBreadcrumbs from './ElementsBreadcrumbs.js';
15
15
  import * as ElementsBreadcrumbsUtils from './ElementsBreadcrumbsUtils.js';
16
16
  import * as ElementsTreeExpandButton from './ElementsTreeExpandButton.js';
17
- import * as Helper from './Helper.js';
18
17
  import * as QueryContainer from './QueryContainer.js';
19
18
  import * as StylePropertyEditor from './StylePropertyEditor.js';
20
19
 
@@ -31,7 +30,6 @@ export {
31
30
  ElementsBreadcrumbs,
32
31
  ElementsBreadcrumbsUtils,
33
32
  ElementsTreeExpandButton,
34
- Helper,
35
33
  QueryContainer,
36
34
  StylePropertyEditor,
37
35
  };
@@ -39,7 +39,7 @@ export interface MediaQueryMarker {
39
39
  locations: SDK.CSSModel.CSSLocation[];
40
40
  }
41
41
 
42
- export const DEFAULT_VIEW = (input: ViewInput, _output: object, target: HTMLElement): void => {
42
+ export const DEFAULT_VIEW = (input: ViewInput, _output: object, target: DocumentFragment): void => {
43
43
  const createBarClassMap = (marker: MediaQueryMarker): Record<string, boolean> => ({
44
44
  'media-inspector-bar': true,
45
45
  'media-inspector-marker-inactive': !marker.active,
@@ -65,7 +65,7 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: object, target: HTMLElem
65
65
  `)}
66
66
  </div>
67
67
  `).toArray()}
68
- </div>`, target);
68
+ </div>`, target, {container: {attributes: {jslog: `${VisualLogging.mediaInspectorView().track({click: true})}`}}});
69
69
  // clang-format on
70
70
  };
71
71
 
@@ -155,7 +155,7 @@ function renderLabel(
155
155
  // clang-format on
156
156
  }
157
157
 
158
- export class MediaQueryInspector extends UI.Widget.Widget implements
158
+ export class MediaQueryInspector extends UI.Widget.Widget<ShadowRoot> implements
159
159
  SDK.TargetManager.SDKModelObserver<SDK.CSSModel.CSSModel> {
160
160
  private readonly view: typeof DEFAULT_VIEW;
161
161
  private readonly mediaThrottler: Common.Throttler.Throttler;
@@ -168,10 +168,7 @@ export class MediaQueryInspector extends UI.Widget.Widget implements
168
168
  constructor(
169
169
  getWidthCallback: () => number, setWidthCallback: (arg0: number) => void,
170
170
  mediaThrottler: Common.Throttler.Throttler, view = DEFAULT_VIEW) {
171
- super({
172
- jslog: `${VisualLogging.mediaInspectorView().track({click: true})}`,
173
- useShadowDom: true,
174
- });
171
+ super({useShadowDom: 'pure'});
175
172
  this.view = view;
176
173
  this.mediaThrottler = mediaThrottler;
177
174
 
@@ -15,7 +15,7 @@ import * as PanelsCommon from '../common/common.js';
15
15
  import {ThrottlingManager} from './ThrottlingManager.js';
16
16
  import type {NetworkThrottlingConditionsGroup} from './ThrottlingPresets.js';
17
17
 
18
- const {render, html, Directives, nothing} = Lit;
18
+ const {render, html, Directives} = Lit;
19
19
 
20
20
  const UIStrings = {
21
21
  /**
@@ -70,7 +70,7 @@ interface ViewInput {
70
70
  onSelect: (conditions: SDK.NetworkManager.ThrottlingConditions) => void;
71
71
  onAddCustomConditions: () => void;
72
72
  }
73
- export type ViewFunction = (input: ViewInput, output: object, target: HTMLElement) => void;
73
+ export type ViewFunction = (input: ViewInput, output: object, target: HTMLSelectElement) => void;
74
74
 
75
75
  export const DEFAULT_VIEW: ViewFunction = (input, output, target) => {
76
76
  // The title is usually an i18nLazyString except for custom values that are stored in the local storage in the form of a string.
@@ -110,12 +110,7 @@ export const DEFAULT_VIEW: ViewFunction = (input, output, target) => {
110
110
 
111
111
  render(
112
112
  // clang-format off
113
- html`<select
114
- ?disabled=${input.disabled}
115
- aria-label=${input.title ?? nothing}
116
- jslog=${VisualLogging.dropDown().track({change: true}).context(input.jslogContext)}
117
- @change=${onSelect}>
118
- ${input.throttlingGroups.map(
113
+ html`${input.throttlingGroups.map(
119
114
  group =>
120
115
  html`<optgroup
121
116
  label=${group.title}>
@@ -149,40 +144,52 @@ export const DEFAULT_VIEW: ViewFunction = (input, output, target) => {
149
144
  jslog=${VisualLogging.action('add').track({click: true})}>
150
145
  ${i18nString(UIStrings.add)}
151
146
  </option>
152
- </optgroup>
153
- </select>`, // clang-format on
154
- target);
147
+ </optgroup>`, // clang-format on
148
+ target, {
149
+ container: {
150
+ listeners: {change: onSelect},
151
+ attributes: {
152
+ disabled: input.disabled,
153
+ 'aria-label': input.title,
154
+ jslog: `${VisualLogging.dropDown(input.jslogContext).track({change: true})}`
155
+ }
156
+ }
157
+ });
155
158
  };
156
159
 
157
160
  export const enum Events {
158
- CONDITIONS_CHANGED = 'conditionsChanged',
161
+ CONDITIONS_CHANGED = 'ConditionsChanged',
159
162
  }
160
163
 
161
164
  export interface EventTypes {
162
165
  [Events.CONDITIONS_CHANGED]: SDK.NetworkManager.ThrottlingConditions;
163
166
  }
164
167
 
165
- export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
168
+ export class NetworkThrottlingSelect extends Common.ObjectWrapper.eventMixin<EventTypes, typeof UI.Widget.Widget>(
169
+ UI.Widget.Widget) {
166
170
  #recommendedConditions: SDK.NetworkManager.Conditions|null = null;
167
- readonly #element: HTMLElement;
168
171
  #jslogContext?: string;
169
172
  #currentConditions: SDK.NetworkManager.ThrottlingConditions|undefined;
170
- readonly #title?: string;
173
+ #title?: string;
171
174
  readonly #view: ViewFunction;
172
175
  #variant: NetworkThrottlingSelect.Variant = NetworkThrottlingSelect.Variant.GLOBAL_CONDITIONS;
173
176
  #disabled = false;
174
177
 
175
178
  static createForGlobalConditions(element: HTMLElement, title: string): NetworkThrottlingSelect {
176
179
  ThrottlingManager.instance(); // Instantiate the throttling manager to connect network manager with the setting
177
- const select = new NetworkThrottlingSelect(element, {
180
+ const selectElement = element.createChild('select');
181
+ const select = new NetworkThrottlingSelect(selectElement, {
178
182
  title,
179
183
  jslogContext: SDK.NetworkManager.activeNetworkThrottlingKeySetting().name,
180
184
  currentConditions: SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions()
181
185
  });
182
- select.addEventListener(
183
- Events.CONDITIONS_CHANGED,
184
- ev => !('block' in ev.data) &&
185
- SDK.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(ev.data));
186
+ select.show(element, undefined, /* suppressOrphanWidgetError= */ true);
187
+ select.addEventListener(Events.CONDITIONS_CHANGED, event => {
188
+ const conditions = event.data;
189
+ if (!('block' in conditions)) {
190
+ SDK.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(conditions);
191
+ }
192
+ });
186
193
  SDK.NetworkManager.MultitargetNetworkManager.instance().addEventListener(
187
194
  SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, () => {
188
195
  select.currentConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions();
@@ -203,22 +210,21 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
203
210
  }
204
211
 
205
212
  constructor(
206
- element: HTMLElement, options: {
213
+ element?: HTMLElement, options: {
207
214
  title?: string,
208
215
  jslogContext?: string,
209
216
  currentConditions?: SDK.NetworkManager.Conditions,
210
217
  includeBlocking?: true,
211
218
  } = {},
212
219
  view = DEFAULT_VIEW) {
213
- super();
214
- SDK.NetworkManager.customUserNetworkConditionsSetting().addChangeListener(this.#performUpdate, this);
215
- this.#element = element;
220
+ super(element);
221
+ SDK.NetworkManager.customUserNetworkConditionsSetting().addChangeListener(this.requestUpdate, this);
216
222
  this.#jslogContext = options.jslogContext;
217
223
  this.#currentConditions = options.currentConditions;
218
224
  this.#title = options.title;
219
225
  this.#view = view;
220
226
 
221
- this.#performUpdate();
227
+ this.performUpdate();
222
228
  }
223
229
 
224
230
  get disabled(): boolean {
@@ -226,7 +232,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
226
232
  }
227
233
  set disabled(disabled: boolean) {
228
234
  this.#disabled = disabled;
229
- this.#performUpdate();
235
+ this.requestUpdate();
230
236
  }
231
237
 
232
238
  get recommendedConditions(): SDK.NetworkManager.Conditions|null {
@@ -234,7 +240,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
234
240
  }
235
241
  set recommendedConditions(recommendedConditions: SDK.NetworkManager.Conditions|null) {
236
242
  this.#recommendedConditions = recommendedConditions;
237
- this.#performUpdate();
243
+ this.requestUpdate();
238
244
  }
239
245
 
240
246
  get currentConditions(): SDK.NetworkManager.ThrottlingConditions|undefined {
@@ -242,7 +248,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
242
248
  }
243
249
  set currentConditions(currentConditions: SDK.NetworkManager.ThrottlingConditions|undefined) {
244
250
  this.#currentConditions = currentConditions;
245
- this.#performUpdate();
251
+ this.requestUpdate();
246
252
  }
247
253
 
248
254
  get jslogContext(): string|undefined {
@@ -250,7 +256,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
250
256
  }
251
257
  set jslogContext(jslogContext: string|undefined) {
252
258
  this.#jslogContext = jslogContext;
253
- this.#performUpdate();
259
+ this.requestUpdate();
254
260
  }
255
261
 
256
262
  get variant(): NetworkThrottlingSelect.Variant {
@@ -258,11 +264,19 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
258
264
  }
259
265
  set variant(variant: NetworkThrottlingSelect.Variant) {
260
266
  this.#variant = variant;
261
- this.#performUpdate();
267
+ this.requestUpdate();
268
+ }
269
+
270
+ get title(): string|undefined {
271
+ return this.#title;
272
+ }
273
+
274
+ set title(title: string|undefined) {
275
+ this.#title = title;
276
+ this.requestUpdate();
262
277
  }
263
278
 
264
- // FIXME Should use requestUpdate once we merge this with the widget
265
- #performUpdate(): void {
279
+ override performUpdate(): void {
266
280
  const customNetworkConditionsSetting = SDK.NetworkManager.customUserNetworkConditionsSetting();
267
281
  const customNetworkConditions = customNetworkConditionsSetting.get();
268
282
  const onAddCustomConditions = (): void => {
@@ -315,7 +329,7 @@ export class NetworkThrottlingSelect extends Common.ObjectWrapper.ObjectWrapper<
315
329
  throttlingGroups,
316
330
  customConditionsGroup,
317
331
  };
318
- this.#view(viewInput, {}, this.#element);
332
+ this.#view(viewInput, {}, this.contentElement as HTMLSelectElement);
319
333
  }
320
334
  }
321
335
  export namespace NetworkThrottlingSelect {
@@ -324,36 +338,3 @@ export namespace NetworkThrottlingSelect {
324
338
  INDIVIDUAL_REQUEST_CONDITIONS = 'individual-request-conditions',
325
339
  }
326
340
  }
327
-
328
- export class NetworkThrottlingSelectorWidget extends UI.Widget.VBox {
329
- #select: NetworkThrottlingSelect;
330
- #conditionsChangedHandler?: ((conditions: SDK.NetworkManager.ThrottlingConditions) => void);
331
- constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
332
- super(element, {useShadowDom: true});
333
- this.#select = new NetworkThrottlingSelect(this.contentElement, {}, view);
334
- this.#select.addEventListener(Events.CONDITIONS_CHANGED, ({data}) => this.#conditionsChangedHandler?.(data));
335
- }
336
-
337
- get disabled(): boolean {
338
- return this.#select.disabled;
339
- }
340
- set disabled(disabled: boolean) {
341
- this.#select.disabled = disabled;
342
- }
343
-
344
- set variant(variant: NetworkThrottlingSelect.Variant) {
345
- this.#select.variant = variant;
346
- }
347
-
348
- set jslogContext(context: string) {
349
- this.#select.jslogContext = context;
350
- }
351
-
352
- set currentConditions(currentConditions: SDK.NetworkManager.ThrottlingConditions|undefined) {
353
- this.#select.currentConditions = currentConditions;
354
- }
355
-
356
- set onConditionsChanged(handler: (conditions: SDK.NetworkManager.ThrottlingConditions) => void) {
357
- this.#conditionsChangedHandler = handler;
358
- }
359
- }
@@ -268,18 +268,20 @@ function renderItem(
268
268
  aria-details=url-pattern-${index}>
269
269
  ${constructorStringOrWildcardURL}
270
270
  </div>
271
- <devtools-widget
271
+ <select
272
272
  class=conditions-selector
273
273
  title=${i18nString(UIStrings.requestConditionsLabel)}
274
+ @ConditionsChanged=${(e: CustomEvent<SDK.NetworkManager.ThrottlingConditions>) => {
275
+ onConditionsChanged(condition, e.detail);
276
+ }}
274
277
  ${widget(
275
- MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelectorWidget, {
278
+ MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect, {
276
279
  variant:
277
280
  MobileThrottling.NetworkThrottlingSelector.NetworkThrottlingSelect.Variant.INDIVIDUAL_REQUEST_CONDITIONS,
278
281
  jslogContext: 'request-conditions',
279
282
  disabled: !editable,
280
- onConditionsChanged: conditions => onConditionsChanged(condition, conditions),
281
283
  currentConditions: condition.conditions,
282
- })}></devtools-widget>
284
+ })}></select>
283
285
  <devtools-widget
284
286
  ?disabled=${!editable || !originalOrUpgradedURLPattern}
285
287
  ${widget(AffectedCountWidget, {condition, lookUpRequestCount})}></devtools-widget>`;
@@ -75,8 +75,8 @@ interface PerformanceMonitorOutput {
75
75
  width: number;
76
76
  }
77
77
 
78
- type PerformanceMonitorView = (input: PerformanceMonitorInput, output: PerformanceMonitorOutput, target: HTMLElement) =>
79
- void;
78
+ type PerformanceMonitorView =
79
+ (input: PerformanceMonitorInput, output: PerformanceMonitorOutput, target: DocumentFragment) => void;
80
80
 
81
81
  const DEFAULT_VIEW: PerformanceMonitorView = (input, output, target) => {
82
82
  // clang-format off
@@ -102,11 +102,11 @@ const DEFAULT_VIEW: PerformanceMonitorView = (input, output, target) => {
102
102
  <div class="perfmon-chart-suspend-overlay fill">
103
103
  <div>${i18nString(UIStrings.paused)}</div>
104
104
  </div>` : ''}`,
105
- target);
105
+ target, {container: {attributes: {jslog: `${VisualLogging.pane('performance.monitor').track({resize: true})}`}}});
106
106
  // clang-format on
107
107
  };
108
108
 
109
- export class PerformanceMonitorImpl extends UI.Widget.HBox implements
109
+ export class PerformanceMonitorImpl extends UI.Widget.HBox<ShadowRoot> implements
110
110
  SDK.TargetManager.SDKModelObserver<SDK.PerformanceMetricsModel.PerformanceMetricsModel> {
111
111
  private view: PerformanceMonitorView;
112
112
  private chartInfos: ChartInfo[] = [];
@@ -127,10 +127,7 @@ export class PerformanceMonitorImpl extends UI.Widget.HBox implements
127
127
  private graphRenderingContext: CanvasRenderingContext2D|null = null;
128
128
 
129
129
  constructor(pollIntervalMs = 500, view = DEFAULT_VIEW) {
130
- super({
131
- jslog: `${VisualLogging.panel('performance.monitor').track({resize: true})}`,
132
- useShadowDom: true,
133
- });
130
+ super({useShadowDom: 'pure'});
134
131
  this.view = view;
135
132
  this.registerRequiredCSS(performanceMonitorStyles);
136
133
 
@@ -504,7 +501,7 @@ export class PerformanceMonitorImpl extends UI.Widget.HBox implements
504
501
 
505
502
  private createChartInfos(): ChartInfo[] {
506
503
  const themeSupport = ThemeSupport.ThemeSupport.instance();
507
- const elementForStyles = this.contentElement;
504
+ const elementForStyles = this.contentElement.firstElementChild;
508
505
 
509
506
  const defaults: Partial<ChartInfo> = {};
510
507