chrome-devtools-frontend 1.0.1697595 → 1.0.1697998

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 (39) hide show
  1. package/.stylelintignore +2 -0
  2. package/front_end/core/common/VersionController.ts +5 -1
  3. package/front_end/core/sdk/AnimationModel.ts +9 -1
  4. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  5. package/front_end/generated/protocol.ts +8 -2
  6. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +26 -0
  7. package/front_end/models/ai_assistance/ai_assistance.ts +4 -4
  8. package/front_end/models/ai_assistance/skills/performance.md +4 -3
  9. package/front_end/models/ai_assistance/tools/{GetFunctionCode.ts → GetTraceFunctionCode.ts} +26 -13
  10. package/front_end/models/ai_assistance/tools/{GetResourceContent.ts → GetTraceResourceContent.ts} +31 -11
  11. package/front_end/models/ai_assistance/tools/Tool.ts +2 -2
  12. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +6 -6
  13. package/front_end/models/elements/DOMChanges.ts +238 -0
  14. package/front_end/models/elements/elements.ts +2 -0
  15. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -1
  16. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +25 -5
  17. package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +2 -3
  18. package/front_end/panels/elements/ElementsTreeElement.ts +98 -20
  19. package/front_end/panels/elements/ElementsTreeOutline.ts +271 -43
  20. package/front_end/panels/elements/EventListenersWidget.ts +0 -1
  21. package/front_end/panels/event_listeners/EventListenersView.ts +241 -297
  22. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
  23. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -2
  24. package/front_end/panels/network/NetworkConfigView.ts +141 -116
  25. package/front_end/panels/network/NetworkPanel.ts +7 -4
  26. package/front_end/panels/network/RequestHeadersView.ts +1 -1
  27. package/front_end/panels/network/forward/BackendLinking.ts +5 -2
  28. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +7 -2
  29. package/front_end/panels/timeline/TimelineTreeView.ts +11 -1
  30. package/front_end/third_party/chromium/README.chromium +1 -1
  31. package/front_end/ui/comments/CommentOverlayManager.ts +169 -40
  32. package/front_end/ui/comments/CommentThreadWidget.ts +221 -0
  33. package/front_end/ui/comments/CommentsOverlayWidget.ts +124 -12
  34. package/front_end/ui/comments/commentThreadWidget.css +173 -0
  35. package/front_end/ui/comments/comments.ts +2 -0
  36. package/front_end/ui/comments/commentsOverlay.css +6 -0
  37. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +1 -1
  38. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +4 -0
  39. package/package.json +5 -5
@@ -1,7 +1,6 @@
1
1
  // Copyright 2015 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable @devtools/no-imperative-dom-api */
5
4
 
6
5
  import * as Common from '../../core/common/common.js';
7
6
  import * as i18n from '../../core/i18n/i18n.js';
@@ -9,14 +8,18 @@ import type * as Platform from '../../core/platform/platform.js';
9
8
  import * as SDK from '../../core/sdk/sdk.js';
10
9
  import * as Buttons from '../../ui/components/buttons/buttons.js';
11
10
  import * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';
11
+ import objectPropertiesSectionStyles from '../../ui/legacy/components/object_ui/objectPropertiesSection.css.js';
12
12
  import objectValueStyles from '../../ui/legacy/components/object_ui/objectValue.css.js';
13
13
  import * as Components from '../../ui/legacy/components/utils/utils.js';
14
14
  import * as UI from '../../ui/legacy/legacy.js';
15
- import {render} from '../../ui/lit/lit.js';
15
+ import * as Lit from '../../ui/lit/lit.js';
16
16
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
17
17
 
18
18
  import {frameworkEventListeners} from './EventListenersUtils.js';
19
19
  import eventListenersViewStyles from './eventListenersView.css.js';
20
+ const {widget} = UI.Widget;
21
+ const {html, render} = Lit;
22
+ const {repeat} = Lit.Directives;
20
23
 
21
24
  const UIStrings = {
22
25
  /**
@@ -51,49 +54,255 @@ const UIStrings = {
51
54
  const str_ = i18n.i18n.registerUIStrings('panels/event_listeners/EventListenersView.ts', UIStrings);
52
55
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
53
56
 
57
+ interface ViewInput {
58
+ togglePassiveListener(listener: SDK.DOMDebuggerModel.EventListener): void;
59
+ removeListener(listener: SDK.DOMDebuggerModel.EventListener): boolean;
60
+ reveal(object: SDK.RemoteObject.RemoteObject): void;
61
+ linkifier: Components.Linkifier.Linkifier;
62
+ listeners: Map<string, Array<{object: SDK.RemoteObject.RemoteObject, listener: SDK.DOMDebuggerModel.EventListener}>>;
63
+ filter?: {showFramework: boolean, showPassive: boolean, showBlocking: boolean};
64
+ }
65
+
66
+ type View = (input: ViewInput, output: object, target: HTMLElement) => void;
67
+ export const DEFAULT_VIEW: View = (input, output, target) => {
68
+ const types = input.listeners.keys().toArray().sort();
69
+
70
+ const onContextMenu = (event: Event, listener: SDK.DOMDebuggerModel.EventListener,
71
+ object: SDK.RemoteObject.RemoteObject): void => {
72
+ const menu = new UI.ContextMenu.ContextMenu(event);
73
+ if (event.target instanceof HTMLElement && !event.target.closest('.event-listener-tree-subtitle') &&
74
+ event.currentTarget instanceof HTMLElement) {
75
+ const link = event.currentTarget.querySelector('.event-listener-tree-subtitle .devtools-link');
76
+ if (link) {
77
+ menu.appendApplicableItems(link);
78
+ }
79
+ }
80
+ if (object.subtype === 'node') {
81
+ menu.defaultSection().appendItem(i18nString(UIStrings.openInElementsPanel), () => input.reveal(object),
82
+ {jslogContext: 'reveal-in-elements'});
83
+ }
84
+ menu.defaultSection().appendItem(i18nString(UIStrings.deleteEventListener), () => input.removeListener(listener),
85
+ {disabled: !listener.canRemove(), jslogContext: 'delete-event-listener'});
86
+ menu.defaultSection().appendCheckboxItem(i18nString(UIStrings.passive), () => input.togglePassiveListener(listener),
87
+ {
88
+ checked: listener.passive(),
89
+ disabled: !listener.canTogglePassive(),
90
+ jslogContext: 'passive',
91
+ });
92
+ void menu.show();
93
+ };
94
+
95
+ const listenerProperties = (listener: SDK.DOMDebuggerModel.EventListener): Iterable<Lit.TemplateResult> => {
96
+ const runtimeModel = listener.domDebuggerModel().runtimeModel();
97
+ const properties = [
98
+ new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
99
+ runtimeModel.createRemotePropertyFromPrimitiveValue('useCapture', listener.useCapture()), undefined, {
100
+ readOnly: false,
101
+ propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
102
+ }),
103
+ new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
104
+ runtimeModel.createRemotePropertyFromPrimitiveValue('passive', listener.passive()), undefined, {
105
+ readOnly: false,
106
+ propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
107
+ }),
108
+ new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
109
+ runtimeModel.createRemotePropertyFromPrimitiveValue('once', listener.once()), undefined, {
110
+ readOnly: false,
111
+ propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
112
+ }),
113
+ ];
114
+ if (typeof listener.handler() !== 'undefined') {
115
+ properties.push(new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
116
+ new SDK.RemoteObject.RemoteObjectProperty('handler', listener.handler()), undefined, {
117
+ readOnly: false,
118
+ propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
119
+ }));
120
+ }
121
+ return ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement
122
+ .createPropertyNodes({properties}, true, true, undefined)
123
+ .map(node => html`<devtools-tree-wrapper .treeElement=${node}></devtools-tree-wrapper>`);
124
+ };
125
+
126
+ const shouldHide = (listenerOrType: SDK.DOMDebuggerModel.EventListener|string): boolean => {
127
+ if (!input.filter) {
128
+ return false;
129
+ }
130
+ if (typeof listenerOrType === 'string') {
131
+ return input.listeners.get(listenerOrType)?.every(({listener}) => shouldHide(listener)) ?? true;
132
+ }
133
+ const listenerOrigin = listenerOrType.origin();
134
+ if (listenerOrigin === SDK.DOMDebuggerModel.EventListener.Origin.FRAMEWORK_USER && !input.filter.showFramework) {
135
+ return true;
136
+ }
137
+ if (listenerOrigin === SDK.DOMDebuggerModel.EventListener.Origin.FRAMEWORK && input.filter.showFramework) {
138
+ return true;
139
+ }
140
+ if (!input.filter.showPassive && listenerOrType.passive()) {
141
+ return true;
142
+ }
143
+ if (!input.filter.showBlocking && !listenerOrType.passive()) {
144
+ return true;
145
+ }
146
+ return false;
147
+ };
148
+
149
+ const onKeyDown = (event: KeyboardEvent, listener: SDK.DOMDebuggerModel.EventListener,
150
+ object: SDK.RemoteObject.RemoteObject): void => {
151
+ if (event.target !== event.currentTarget) {
152
+ return;
153
+ }
154
+ if (event.key === 'Delete' || event.key === 'Backspace') {
155
+ if (input.removeListener(listener)) {
156
+ event.consume();
157
+ }
158
+ } else if (event.key === 'Enter') {
159
+ input.reveal(object);
160
+ event.consume();
161
+ }
162
+ };
163
+
164
+ const hasVisibleListeners = types.some(type => !shouldHide(type));
165
+
166
+ // clang-format off
167
+ render(html`
168
+ <style>${eventListenersViewStyles}</style>
169
+ ${!hasVisibleListeners ? html`
170
+ <div autofocus class=placeholder><!--emptyHolder-->
171
+ <span class=gray-info-message>${i18nString(UIStrings.noEventListeners)}</span>
172
+ ${widget(UI.EmptyWidget.EmptyWidget, {
173
+ header: i18nString(UIStrings.noEventListeners),
174
+ text: i18nString(UIStrings.eventListenersExplanation),
175
+ })}
176
+ </div>` : html`
177
+ <devtools-tree autofocus class="event-listener-tree monospace" show-selection-on-keyboard-focus .template=${html`
178
+ <ul role=tree>
179
+ <style>${eventListenersViewStyles}</style>
180
+ <style>${objectValueStyles}</style>
181
+ <style>${objectPropertiesSectionStyles}</style>
182
+ ${repeat(types, type => type, type => html`
183
+ <li role=treeitem toggle-on-click aria-label="${type}, event listener" ?hidden=${shouldHide(type)}>
184
+ ${type}
185
+ <ul role=group>
186
+ ${repeat(input.listeners.get(type) ?? [], ({listener}) => listener, ({listener, object}) => html`
187
+ <li role=treeitem
188
+ data-origin=${listener.origin()}
189
+ @contextmenu=${(e: Event) => onContextMenu(e, listener, object)}
190
+ @keydown=${(e: KeyboardEvent) => onKeyDown(e, listener, object)}
191
+ ?hidden=${shouldHide(listener)}>
192
+ <span class=event-listener-details>
193
+ ${ObjectUI.ObjectPropertiesSection.renderPropertyValue(
194
+ object, /* wasThrown */ false, /* showPreview */ false, input.linkifier)}
195
+ <devtools-button
196
+ .iconName=${'bin'}
197
+ .variant=${Buttons.Button.Variant.ICON}
198
+ .size=${Buttons.Button.Size.MICRO}
199
+ .jslogContext=${'delete-event-listener'}
200
+ title=${i18nString(UIStrings.deleteEventListener)}
201
+ @click=${(event: Event) => {input.removeListener(listener); event.consume();}}
202
+ ?hidden=${!listener.canRemove()}></devtools-button>
203
+ ${listener.isScrollBlockingType() && listener.canTogglePassive() ? html`
204
+ <button class=event-listener-button
205
+ jslog=${VisualLogging.action('passive').track({click: true})}
206
+ title=${i18nString(UIStrings.toggleWhetherEventListenerIs)}
207
+ @click=${(e: Event) => {input.togglePassiveListener(listener); e.consume();}}>
208
+ ${i18nString(UIStrings.togglePassive)}
209
+ </button>` : Lit.nothing}
210
+ <span class=event-listener-tree-subtitle>
211
+ ${input.linkifier.linkifyRawLocation(
212
+ listener.location(), listener.sourceURL(), /* FIXME template version */
213
+ undefined, {tabStop: true})}
214
+ </span>
215
+ </span>
216
+ <ul role=group>
217
+ ${listenerProperties(listener)}
218
+ </ul>
219
+ </li>`)}
220
+ </ul>
221
+ </li>`)}
222
+ </ul>
223
+ `}></devtools-tree>`}`,
224
+ // clang-format on
225
+ target);
226
+ };
227
+
54
228
  export class EventListenersView extends UI.Widget.VBox {
55
- changeCallback = (): void => {};
56
- enableDefaultTreeFocus = false;
57
- treeOutline: UI.TreeOutline.TreeOutlineInShadow;
58
- emptyHolder: HTMLDivElement;
59
- objects: Array<SDK.RemoteObject.RemoteObject|null> = [];
60
- filter: {showFramework: boolean, showPassive: boolean, showBlocking: boolean}|undefined;
229
+ #objects: Array<SDK.RemoteObject.RemoteObject|null> = [];
230
+ #filter: {showFramework: boolean, showPassive: boolean, showBlocking: boolean}|undefined;
231
+ #view: View;
232
+ #listeners?:
233
+ Map<string, Array<{object: SDK.RemoteObject.RemoteObject, listener: SDK.DOMDebuggerModel.EventListener}>>;
61
234
  #linkifier = new Components.Linkifier.Linkifier();
62
- readonly #treeItemMap = new Map<string, EventListenersTreeElement>();
63
- constructor(element?: HTMLElement) {
235
+ constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
64
236
  super(element);
65
- this.registerRequiredCSS(eventListenersViewStyles);
66
- this.emptyHolder = this.element.createChild('div', 'placeholder hidden');
67
- this.emptyHolder.createChild('span', 'gray-info-message').textContent = i18nString(UIStrings.noEventListeners);
68
- const emptyWidget = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.noEventListeners),
69
- i18nString(UIStrings.eventListenersExplanation));
70
- emptyWidget.show(this.emptyHolder);
237
+ this.#view = view;
238
+ }
71
239
 
72
- this.treeOutline = new UI.TreeOutline.TreeOutlineInShadow();
73
- this.treeOutline.setComparator(EventListenersTreeElement.comparator);
74
- this.treeOutline.element.classList.add('event-listener-tree', 'monospace');
75
- this.treeOutline.setShowSelectionOnKeyboardFocus(true);
76
- this.treeOutline.setFocusable(true);
77
- this.treeOutline.registerRequiredCSS(eventListenersViewStyles, objectValueStyles);
78
- this.element.appendChild(this.treeOutline.element);
240
+ get objects(): Array<SDK.RemoteObject.RemoteObject|null> {
241
+ return this.#objects;
79
242
  }
80
243
 
81
- override focus(): void {
82
- if (!this.enableDefaultTreeFocus) {
244
+ set objects(val: Array<SDK.RemoteObject.RemoteObject|null>) {
245
+ if (this.#objects === val) {
83
246
  return;
84
247
  }
85
- if (!this.emptyHolder.classList.contains('hidden')) {
86
- this.treeOutline.forceSelect();
87
- } else {
88
- this.emptyHolder.focus();
248
+ this.#listeners = undefined;
249
+ this.#objects = val;
250
+ this.requestUpdate();
251
+ }
252
+ get filter(): {showFramework: boolean, showPassive: boolean, showBlocking: boolean}|undefined {
253
+ return this.#filter;
254
+ }
255
+
256
+ set filter(val: {showFramework: boolean, showPassive: boolean, showBlocking: boolean}|undefined) {
257
+ if (this.#filter === val) {
258
+ return;
89
259
  }
260
+ this.#filter = val;
261
+ this.requestUpdate();
90
262
  }
91
263
 
92
264
  override async performUpdate(): Promise<void> {
93
- await this.addObjects(this.objects);
94
- if (this.filter) {
95
- this.showFrameworkListeners(this.filter.showFramework, this.filter.showPassive, this.filter.showBlocking);
265
+ if (!this.#listeners && this.#objects) {
266
+ this.#listeners =
267
+ await EventListenersView.#loadListeners(this.#objects.filter((o): o is NonNullable<typeof o> => !!o));
96
268
  }
269
+ const input: ViewInput = {
270
+ listeners: this.#listeners ?? new Map(),
271
+ filter: this.#filter,
272
+ togglePassiveListener: (listener: SDK.DOMDebuggerModel.EventListener) => {
273
+ void listener.togglePassive().then(() => {
274
+ this.requestUpdate();
275
+ });
276
+ },
277
+ removeListener: (listener: SDK.DOMDebuggerModel.EventListener) => {
278
+ if (!listener.canRemove()) {
279
+ return false;
280
+ }
281
+ void listener.remove();
282
+ if (this.#listeners) {
283
+ const list = this.#listeners.get(listener.type());
284
+ if (list) {
285
+ const index = list.findIndex(item => item.listener === listener);
286
+ if (index !== -1) {
287
+ list.splice(index, 1);
288
+ if (list.length === 0) {
289
+ this.#listeners.delete(listener.type());
290
+ }
291
+ }
292
+ }
293
+ }
294
+ this.requestUpdate();
295
+ return true;
296
+ },
297
+ reveal: (object: SDK.RemoteObject.RemoteObject) => {
298
+ if (object.subtype === 'node') {
299
+ void Common.Revealer.reveal(object);
300
+ }
301
+ },
302
+ linkifier: this.#linkifier,
303
+ };
304
+ this.#view(input, {}, this.contentElement);
305
+ this.eventListenersArrivedForTest();
97
306
  }
98
307
 
99
308
  static async #loadListeners(objects: SDK.RemoteObject.RemoteObject[]): Promise<
@@ -138,271 +347,6 @@ export class EventListenersView extends UI.Widget.VBox {
138
347
  }
139
348
  }
140
349
 
141
- async addObjects(objects: Array<SDK.RemoteObject.RemoteObject|null>): Promise<void> {
142
- // Remove existing event listeners and reset linkifier first.
143
- const eventTypes = this.treeOutline.rootElement().children();
144
- for (const eventType of eventTypes) {
145
- eventType.removeChildren();
146
- }
147
- this.#linkifier.reset();
148
-
149
- const listeners = await EventListenersView.#loadListeners(objects.filter((o): o is NonNullable<typeof o> => !!o));
150
-
151
- for (const [type, groupedListeners] of listeners) {
152
- const treeItem = this.getOrCreateTreeElementForType(type);
153
- for (const {object, listener} of groupedListeners) {
154
- treeItem.addObjectEventListener(listener, object);
155
- }
156
- }
157
-
158
- this.addEmptyHolderIfNeeded();
159
- this.eventListenersArrivedForTest();
160
- }
161
-
162
- showFrameworkListeners(showFramework: boolean, showPassive: boolean, showBlocking: boolean): void {
163
- const eventTypes = this.treeOutline.rootElement().children();
164
- for (const eventType of eventTypes) {
165
- let hiddenEventType = true;
166
- for (const listenerElement of eventType.children()) {
167
- const objectListenerElement = listenerElement as ObjectEventListenerBar;
168
- const listenerOrigin = objectListenerElement.eventListener().origin();
169
- let hidden = false;
170
- if (listenerOrigin === SDK.DOMDebuggerModel.EventListener.Origin.FRAMEWORK_USER && !showFramework) {
171
- hidden = true;
172
- }
173
- if (listenerOrigin === SDK.DOMDebuggerModel.EventListener.Origin.FRAMEWORK && showFramework) {
174
- hidden = true;
175
- }
176
- if (!showPassive && objectListenerElement.eventListener().passive()) {
177
- hidden = true;
178
- }
179
- if (!showBlocking && !objectListenerElement.eventListener().passive()) {
180
- hidden = true;
181
- }
182
- objectListenerElement.hidden = hidden;
183
- hiddenEventType = hiddenEventType && hidden;
184
- }
185
- eventType.hidden = hiddenEventType;
186
- }
187
- }
188
-
189
- private getOrCreateTreeElementForType(type: string): EventListenersTreeElement {
190
- let treeItem = this.#treeItemMap.get(type);
191
- if (!treeItem) {
192
- treeItem = new EventListenersTreeElement(type, this.#linkifier, this.changeCallback);
193
- this.#treeItemMap.set(type, treeItem);
194
- treeItem.hidden = true;
195
- this.treeOutline.appendChild(treeItem);
196
- }
197
- this.emptyHolder.classList.add('hidden');
198
- return treeItem;
199
- }
200
-
201
- addEmptyHolderIfNeeded(): void {
202
- let allHidden = true;
203
- let firstVisibleChild: UI.TreeOutline.TreeElement|null = null;
204
- for (const eventType of this.treeOutline.rootElement().children()) {
205
- eventType.hidden = !eventType.firstChild();
206
- allHidden = allHidden && eventType.hidden;
207
- if (!firstVisibleChild && !eventType.hidden) {
208
- firstVisibleChild = eventType;
209
- }
210
- }
211
- if (allHidden && this.emptyHolder.classList.contains('hidden')) {
212
- this.emptyHolder.classList.remove('hidden');
213
- }
214
- if (firstVisibleChild) {
215
- firstVisibleChild.select(true /* omitFocus */);
216
- }
217
-
218
- this.treeOutline.setFocusable(Boolean(firstVisibleChild));
219
- }
220
-
221
350
  private eventListenersArrivedForTest(): void {
222
351
  }
223
352
  }
224
-
225
- export class EventListenersTreeElement extends UI.TreeOutline.TreeElement {
226
- override toggleOnClick: boolean;
227
- private readonly linkifier: Components.Linkifier.Linkifier;
228
- private readonly changeCallback: () => void;
229
- constructor(type: string, linkifier: Components.Linkifier.Linkifier, changeCallback: () => void) {
230
- super(type);
231
- this.toggleOnClick = true;
232
- this.linkifier = linkifier;
233
- this.changeCallback = changeCallback;
234
- UI.ARIAUtils.setLabel(this.listItemElement, `${type}, event listener`);
235
- }
236
-
237
- static comparator(element1: UI.TreeOutline.TreeElement, element2: UI.TreeOutline.TreeElement): number {
238
- if (element1.title === element2.title) {
239
- return 0;
240
- }
241
- return element1.title > element2.title ? 1 : -1;
242
- }
243
-
244
- addObjectEventListener(eventListener: SDK.DOMDebuggerModel.EventListener,
245
- object: SDK.RemoteObject.RemoteObject): void {
246
- const treeElement = new ObjectEventListenerBar(eventListener, object, this.linkifier, this.changeCallback);
247
- this.appendChild(treeElement as UI.TreeOutline.TreeElement);
248
- }
249
- }
250
-
251
- export class ObjectEventListenerBar extends UI.TreeOutline.TreeElement {
252
- #eventListener: SDK.DOMDebuggerModel.EventListener;
253
- editable: boolean;
254
- private readonly changeCallback: () => void;
255
- private valueTitle?: Element;
256
- constructor(eventListener: SDK.DOMDebuggerModel.EventListener, object: SDK.RemoteObject.RemoteObject,
257
- linkifier: Components.Linkifier.Linkifier, changeCallback: () => void) {
258
- super('', true);
259
- this.#eventListener = eventListener;
260
- this.editable = false;
261
- this.setTitle(object, linkifier);
262
- this.changeCallback = changeCallback;
263
- }
264
-
265
- override async onpopulate(): Promise<void> {
266
- const properties = [];
267
- const eventListener = this.#eventListener;
268
- const runtimeModel = eventListener.domDebuggerModel().runtimeModel();
269
- properties.push(new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
270
- runtimeModel.createRemotePropertyFromPrimitiveValue('useCapture', eventListener.useCapture()), undefined, {
271
- readOnly: false,
272
- propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
273
- }));
274
- properties.push(new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
275
- runtimeModel.createRemotePropertyFromPrimitiveValue('passive', eventListener.passive()), undefined, {
276
- readOnly: false,
277
- propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
278
- }));
279
- properties.push(new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
280
- runtimeModel.createRemotePropertyFromPrimitiveValue('once', eventListener.once()), undefined, {
281
- readOnly: false,
282
- propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
283
- }));
284
- if (typeof eventListener.handler() !== 'undefined') {
285
- properties.push(new ObjectUI.ObjectPropertiesSection.ObjectTreeNode(
286
- new SDK.RemoteObject.RemoteObjectProperty('handler', eventListener.handler()), undefined, {
287
- readOnly: false,
288
- propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
289
- }));
290
- }
291
- ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement.populateWithProperties(this, {properties}, true, true,
292
- undefined);
293
- }
294
-
295
- private setTitle(object: SDK.RemoteObject.RemoteObject, linkifier: Components.Linkifier.Linkifier): void {
296
- const title = this.listItemElement.createChild('span', 'event-listener-details');
297
-
298
- const propertyValue = ObjectUI.ObjectPropertiesSection.renderPropertyValue(
299
- object, /* wasThrown */ false, /* showPreview */ false, linkifier, /* isSyntheticProperty */ false,
300
- /* variableName */ undefined, /* includeNullOrUndefined */ undefined, /* useCustomPreview */ false, element => {
301
- this.valueTitle = element;
302
- });
303
- // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
304
- render(propertyValue, title);
305
-
306
- if (this.#eventListener.canRemove()) {
307
- const deleteButton = new Buttons.Button.Button();
308
- deleteButton.data = {
309
- variant: Buttons.Button.Variant.ICON,
310
- size: Buttons.Button.Size.MICRO,
311
- iconName: 'bin',
312
- jslogContext: 'delete-event-listener',
313
- };
314
- UI.Tooltip.Tooltip.install(deleteButton, i18nString(UIStrings.deleteEventListener));
315
- deleteButton.addEventListener('click', event => {
316
- this.removeListener();
317
- event.consume();
318
- }, false);
319
- title.appendChild(deleteButton);
320
- }
321
-
322
- if (this.#eventListener.isScrollBlockingType() && this.#eventListener.canTogglePassive()) {
323
- const passiveButton = title.createChild('button', 'event-listener-button');
324
- passiveButton.textContent = i18nString(UIStrings.togglePassive);
325
- passiveButton.setAttribute('jslog', `${VisualLogging.action('passive').track({click: true})}`);
326
- UI.Tooltip.Tooltip.install(passiveButton, i18nString(UIStrings.toggleWhetherEventListenerIs));
327
- passiveButton.addEventListener('click', event => {
328
- this.togglePassiveListener();
329
- event.consume();
330
- }, false);
331
- title.appendChild(passiveButton);
332
- }
333
-
334
- const subtitle = title.createChild('span', 'event-listener-tree-subtitle');
335
- const linkElement = linkifier.linkifyRawLocation(this.#eventListener.location(), this.#eventListener.sourceURL(),
336
- undefined, {tabStop: true});
337
- subtitle.appendChild(linkElement);
338
-
339
- this.listItemElement.addEventListener('contextmenu', event => {
340
- const menu = new UI.ContextMenu.ContextMenu(event);
341
- if (event.target !== linkElement) {
342
- menu.appendApplicableItems(linkElement);
343
- }
344
- if (object.subtype === 'node') {
345
- menu.defaultSection().appendItem(i18nString(UIStrings.openInElementsPanel),
346
- () => Common.Revealer.reveal(object), {jslogContext: 'reveal-in-elements'});
347
- }
348
- menu.defaultSection().appendItem(
349
- i18nString(UIStrings.deleteEventListener), this.removeListener.bind(this),
350
- {disabled: !this.#eventListener.canRemove(), jslogContext: 'delete-event-listener'});
351
- menu.defaultSection().appendCheckboxItem(i18nString(UIStrings.passive), this.togglePassiveListener.bind(this), {
352
- checked: this.#eventListener.passive(),
353
- disabled: !this.#eventListener.canTogglePassive(),
354
- jslogContext: 'passive',
355
- });
356
- void menu.show();
357
- });
358
- }
359
-
360
- private removeListener(): void {
361
- this.removeListenerBar();
362
- void this.#eventListener.remove();
363
- }
364
-
365
- private togglePassiveListener(): void {
366
- void this.#eventListener.togglePassive().then(() => this.changeCallback());
367
- }
368
-
369
- private removeListenerBar(): void {
370
- const parent = this.parent;
371
- if (!parent) {
372
- return;
373
- }
374
- parent.removeChild(this);
375
- if (!parent.childCount()) {
376
- parent.collapse();
377
- }
378
- let allHidden = true;
379
- for (const child of parent.children()) {
380
- if (!child.hidden) {
381
- allHidden = false;
382
- }
383
- }
384
- parent.hidden = allHidden;
385
- }
386
-
387
- eventListener(): SDK.DOMDebuggerModel.EventListener {
388
- return this.#eventListener;
389
- }
390
-
391
- override onenter(): boolean {
392
- if (this.valueTitle) {
393
- (this.valueTitle as HTMLElement).click();
394
- return true;
395
- }
396
-
397
- return false;
398
- }
399
-
400
- override ondelete(): boolean {
401
- if (this.#eventListener.canRemove()) {
402
- this.removeListener();
403
- return true;
404
- }
405
-
406
- return false;
407
- }
408
- }
@@ -319,7 +319,7 @@ export class LinearMemoryInspectorController extends SDK.TargetManager.SDKModelO
319
319
  _event: Event, contextMenu: UI.ContextMenu.ContextMenu,
320
320
  target: ObjectUI.ObjectPropertiesSection.ObjectPropertyTreeElement): void {
321
321
  if (target.property.object?.isLinearMemoryInspectable()) {
322
- const expression = target.path();
322
+ const expression = target.property.path;
323
323
  const object = target.property.object;
324
324
  contextMenu.debugSection().appendItem(
325
325
  i18nString(UIStrings.openInMemoryInspectorPanel),
@@ -58,6 +58,14 @@ const UIStrings = {
58
58
  * @description Label for a textbox that sets the packet loss percentage for real-time networks in the throttling settings tab.
59
59
  */
60
60
  packetLoss: 'Packet Loss',
61
+ /**
62
+ * @description Label for a textbox that sets the low-tier mobile device CPU throttling in the throttling settings tab.
63
+ */
64
+ calibratedLowTierMobile: 'Low-tier mobile device',
65
+ /**
66
+ * @description Label for a textbox that sets the mid-tier mobile device CPU throttling in the throttling settings tab.
67
+ */
68
+ calibratedMidTierMobile: 'Mid-tier mobile device',
61
69
  /**
62
70
  * @description Label for a textbox that sets the maximum packet queue length for real-time networks in the throttling settings tab.
63
71
  */
@@ -241,11 +249,11 @@ export class CPUThrottlingCard {
241
249
  descriptionEl.textContent = i18nString(UIStrings.cpuCalibrationDescription);
242
250
 
243
251
  this.lowTierMobileDeviceEl = this.element.createChild('div', 'cpu-preset-section');
244
- this.lowTierMobileDeviceEl.append('Low-tier mobile device');
252
+ this.lowTierMobileDeviceEl.append(i18nString(UIStrings.calibratedLowTierMobile));
245
253
  this.lowTierMobileDeviceEl.createChild('div', 'cpu-preset-result');
246
254
 
247
255
  this.midTierMobileDeviceEl = this.element.createChild('div', 'cpu-preset-section');
248
- this.midTierMobileDeviceEl.append('Mid-tier mobile device');
256
+ this.midTierMobileDeviceEl.append(i18nString(UIStrings.calibratedMidTierMobile));
249
257
  this.midTierMobileDeviceEl.createChild('div', 'cpu-preset-result');
250
258
 
251
259
  this.calibrateEl = this.element.createChild('div', 'cpu-preset-section cpu-preset-calibrate');