chrome-devtools-frontend 1.0.1656291 → 1.0.1657110

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 (63) hide show
  1. package/AUTHORS +2 -0
  2. package/docs/get_the_code.md +6 -6
  3. package/front_end/Tests.js +1 -1
  4. package/front_end/core/common/Settings.ts +0 -8
  5. package/front_end/core/host/Platform.ts +4 -0
  6. package/front_end/core/sdk/CSSMetadata.ts +11 -0
  7. package/front_end/core/sdk/CSSModel.ts +3 -0
  8. package/front_end/core/sdk/DOMModel.ts +44 -13
  9. package/front_end/core/sdk/DebuggerModel.ts +5 -4
  10. package/front_end/core/sdk/EmulationModel.ts +6 -4
  11. package/front_end/core/sdk/NetworkManager.ts +21 -14
  12. package/front_end/core/sdk/RuntimeModel.ts +1 -1
  13. package/front_end/core/sdk/SourceMapCache.ts +2 -4
  14. package/front_end/core/sdk/SourceMapManager.ts +8 -7
  15. package/front_end/core/sdk/TargetManager.ts +10 -0
  16. package/front_end/design_system_tokens.css +6 -0
  17. package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -11
  18. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
  19. package/front_end/entrypoints/main/GlobalAiButton.ts +29 -35
  20. package/front_end/entrypoints/main/MainImpl.ts +1 -1
  21. package/front_end/entrypoints/main/SimpleApp.ts +0 -13
  22. package/front_end/entrypoints/main/main-meta.ts +2 -2
  23. package/front_end/entrypoints/node_app/app/NodeConnectionsPanel.ts +2 -3
  24. package/front_end/foundation/Universe.ts +44 -0
  25. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  26. package/front_end/generated/protocol.ts +5 -5
  27. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +2 -1
  28. package/front_end/models/crux-manager/CrUXManager.ts +16 -11
  29. package/front_end/models/emulation/DeviceModeModel.ts +43 -24
  30. package/front_end/models/live-metrics/LiveMetrics.ts +47 -23
  31. package/front_end/models/project_settings/ProjectSettingsModel.ts +2 -37
  32. package/front_end/models/workspace/FileManager.ts +9 -6
  33. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -1
  34. package/front_end/panels/application/ServiceWorkersView.ts +177 -163
  35. package/front_end/panels/application/components/StorageMetadataView.ts +7 -2
  36. package/front_end/panels/application/serviceWorkersView.css +8 -0
  37. package/front_end/panels/common/BadgeNotification.ts +1 -1
  38. package/front_end/panels/console/ConsoleInsightTeaser.ts +2 -1
  39. package/front_end/panels/elements/ElementsPanel.ts +35 -28
  40. package/front_end/panels/elements/ElementsTreeElement.ts +208 -143
  41. package/front_end/panels/elements/ElementsTreeOutline.ts +3 -2
  42. package/front_end/panels/elements/components/AdornerManager.ts +1 -0
  43. package/front_end/panels/elements/elements-meta.ts +3 -2
  44. package/front_end/panels/emulation/DeviceModeToolbar.ts +19 -19
  45. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -1
  46. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +13 -12
  47. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +8 -7
  48. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +6 -7
  49. package/front_end/panels/mobile_throttling/mobile_throttling-meta.ts +3 -2
  50. package/front_end/panels/settings/components/SyncSection.ts +2 -1
  51. package/front_end/panels/timeline/AppenderUtils.ts +12 -4
  52. package/front_end/panels/timeline/ThreadAppender.ts +3 -3
  53. package/front_end/panels/timeline/TimelinePanel.ts +5 -5
  54. package/front_end/panels/timeline/timelineFlameChartView.css +2 -1
  55. package/front_end/third_party/chromium/README.chromium +1 -1
  56. package/front_end/third_party/chromium/ahem/ahem.js +792 -0
  57. package/front_end/tsconfig.json +7 -1
  58. package/front_end/ui/legacy/ActionRegistration.ts +1 -1
  59. package/front_end/ui/legacy/InspectorView.ts +1 -1
  60. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +109 -23
  61. package/front_end/ui/legacy/theme_support/ThemeSupport.ts +2 -2
  62. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  63. package/package.json +1 -1
@@ -214,13 +214,25 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
214
214
  private cssStyleTrackerByCSSModel: Map<SDK.CSSModel.CSSModel, SDK.CSSModel.CSSPropertyTracker>;
215
215
  #domTreeWidget: DOMTreeWidget;
216
216
  #computedStyleModel: ComputedStyle.ComputedStyleModel.ComputedStyleModel;
217
+ readonly #targetManager: SDK.TargetManager.TargetManager;
218
+ readonly #settings: Common.Settings.Settings;
219
+
220
+ get settings(): Common.Settings.Settings {
221
+ return this.#settings;
222
+ }
223
+
224
+ get targetManager(): SDK.TargetManager.TargetManager {
225
+ return this.#targetManager;
226
+ }
217
227
 
218
228
  getTreeOutlineForTesting(): ElementsTreeOutline|undefined {
219
229
  return this.#domTreeWidget.getTreeOutlineForTesting();
220
230
  }
221
231
 
222
- constructor() {
232
+ constructor(targetManager?: SDK.TargetManager.TargetManager, settings?: Common.Settings.Settings) {
223
233
  super('elements');
234
+ this.#targetManager = targetManager ?? SDK.TargetManager.TargetManager.instance();
235
+ this.#settings = settings ?? Common.Settings.Settings.instance();
224
236
  this.registerRequiredCSS(elementsPanelStyles);
225
237
 
226
238
  this.splitWidget = new UI.SplitWidget.SplitWidget(true, true, 'elements-panel-split-view-state', 325, 325);
@@ -251,12 +263,10 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
251
263
  this.domTreeContainer.id = 'elements-content';
252
264
  this.domTreeContainer.tabIndex = -1;
253
265
  // FIXME: crbug.com/425984
254
- if (Common.Settings.Settings.instance().moduleSetting('dom-word-wrap').get()) {
266
+ if (this.#settings.moduleSetting('dom-word-wrap').get()) {
255
267
  this.domTreeContainer.classList.add('elements-wrap');
256
268
  }
257
- Common.Settings.Settings.instance()
258
- .moduleSetting('dom-word-wrap')
259
- .addChangeListener(this.domWordWrapSettingChanged.bind(this));
269
+ this.#settings.moduleSetting('dom-word-wrap').addChangeListener(this.domWordWrapSettingChanged.bind(this));
260
270
 
261
271
  crumbsContainer.id = 'elements-crumbs';
262
272
  this.accessibilityTreeView = new AccessibilityTreeView(new TreeOutline.TreeOutline.TreeOutline<AXTreeNodeData>());
@@ -286,9 +296,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
286
296
 
287
297
  this.metricsWidget = new MetricsSidebarPane(this.#computedStyleModel);
288
298
 
289
- Common.Settings.Settings.instance()
290
- .moduleSetting('sidebar-position')
291
- .addChangeListener(this.updateSidebarPosition.bind(this));
299
+ this.#settings.moduleSetting('sidebar-position').addChangeListener(this.updateSidebarPosition.bind(this));
292
300
  this.updateSidebarPosition();
293
301
 
294
302
  this.cssStyleTrackerByCSSModel = new Map();
@@ -296,8 +304,8 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
296
304
 
297
305
  this.pendingNodeReveal = false;
298
306
 
299
- this.adornerManager = new ElementsComponents.AdornerManager.AdornerManager(
300
- Common.Settings.Settings.instance().moduleSetting('adorner-settings'));
307
+ this.adornerManager =
308
+ new ElementsComponents.AdornerManager.AdornerManager(this.#settings.moduleSetting('adorner-settings'));
301
309
  this.adornersByName = new Map();
302
310
 
303
311
  this.#domTreeWidget = new DOMTreeWidget();
@@ -306,14 +314,12 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
306
314
  this.#domTreeWidget.onSelectedNodeChanged = this.selectedNodeChanged.bind(this);
307
315
  this.#domTreeWidget.onElementsTreeUpdated = this.updateBreadcrumbIfNeeded.bind(this);
308
316
  this.#domTreeWidget.onDocumentUpdated = this.documentUpdated.bind(this);
309
- this.#domTreeWidget.setWordWrap(Common.Settings.Settings.instance().moduleSetting('dom-word-wrap').get());
310
-
311
- SDK.TargetManager.TargetManager.instance().observeModels(SDK.DOMModel.DOMModel, this, {scoped: true});
312
- SDK.TargetManager.TargetManager.instance().addEventListener(
313
- SDK.TargetManager.Events.NAME_CHANGED, event => this.targetNameChanged(event.data));
314
- Common.Settings.Settings.instance()
315
- .moduleSetting('show-ua-shadow-dom')
316
- .addChangeListener(this.showUAShadowDOMChanged.bind(this));
317
+ this.#domTreeWidget.setWordWrap(this.#settings.moduleSetting('dom-word-wrap').get());
318
+
319
+ this.#targetManager.observeModels(SDK.DOMModel.DOMModel, this, {scoped: true});
320
+ this.#targetManager.addEventListener(SDK.TargetManager.Events.NAME_CHANGED,
321
+ event => this.targetNameChanged(event.data));
322
+ this.#settings.moduleSetting('show-ua-shadow-dom').addChangeListener(this.showUAShadowDOMChanged.bind(this));
317
323
  PanelCommon.ExtensionServer.ExtensionServer.instance().addEventListener(
318
324
  PanelCommon.ExtensionServer.Events.SidebarPaneAdded, this.extensionSidebarPaneAdded, this);
319
325
  }
@@ -378,10 +384,12 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
378
384
 
379
385
  static instance(opts: {
380
386
  forceNew: boolean|null,
387
+ targetManager?: SDK.TargetManager.TargetManager,
388
+ settings?: Common.Settings.Settings,
381
389
  }|undefined = {forceNew: null}): ElementsPanel {
382
- const {forceNew} = opts;
390
+ const {forceNew, targetManager, settings} = opts || {};
383
391
  if (!elementsPanelInstance || forceNew) {
384
- elementsPanelInstance = new ElementsPanel();
392
+ elementsPanelInstance = new ElementsPanel(targetManager, settings);
385
393
  }
386
394
 
387
395
  return elementsPanelInstance;
@@ -734,7 +742,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
734
742
  this.currentSearchResultIndex = -1;
735
743
  delete this.searchResults;
736
744
 
737
- SDK.DOMModel.DOMModel.cancelSearch();
745
+ SDK.DOMModel.DOMModel.cancelSearch(this.#targetManager);
738
746
  }
739
747
 
740
748
  performSearch(searchConfig: UI.SearchableView.SearchConfig, shouldJump: boolean, jumpBackwards?: boolean): void {
@@ -753,8 +761,8 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
753
761
 
754
762
  this.searchConfig = searchConfig;
755
763
 
756
- const showUAShadowDOM = Common.Settings.Settings.instance().moduleSetting('show-ua-shadow-dom').get();
757
- const domModels = SDK.TargetManager.TargetManager.instance().models(SDK.DOMModel.DOMModel, {scoped: true});
764
+ const showUAShadowDOM = this.#settings.moduleSetting('show-ua-shadow-dom').get();
765
+ const domModels = this.#targetManager.models(SDK.DOMModel.DOMModel, {scoped: true});
758
766
  const promises = domModels.map(domModel => domModel.performSearch(whitespaceTrimmedQuery, showUAShadowDOM));
759
767
  void Promise.all(promises).then(resultCounts => {
760
768
  this.searchResults = [];
@@ -952,9 +960,8 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
952
960
  const {showPanel = true, focusNode = false, highlightInOverlay = true} = opts ?? {};
953
961
  this.omitDefaultSelection = true;
954
962
 
955
- const node = Common.Settings.Settings.instance().moduleSetting('show-ua-shadow-dom').get() ?
956
- nodeToReveal :
957
- this.leaveUserAgentShadowDOM(nodeToReveal);
963
+ const node = this.#settings.moduleSetting('show-ua-shadow-dom').get() ? nodeToReveal :
964
+ this.leaveUserAgentShadowDOM(nodeToReveal);
958
965
  if (highlightInOverlay) {
959
966
  node.highlightForTwoSeconds();
960
967
  }
@@ -1167,7 +1174,7 @@ export class ElementsPanel extends UI.Panel.Panel implements UI.SearchableView.S
1167
1174
  return;
1168
1175
  } // We can't reparent extension iframes.
1169
1176
 
1170
- const position = Common.Settings.Settings.instance().moduleSetting('sidebar-position').get();
1177
+ const position = this.#settings.moduleSetting('sidebar-position').get();
1171
1178
  let splitMode = SplitMode.HORIZONTAL;
1172
1179
  if (position === 'right' || (position === 'auto' && this.splitWidget.element.offsetWidth > 680)) {
1173
1180
  splitMode = SplitMode.VERTICAL;
@@ -1508,7 +1515,7 @@ export class ElementsActionDelegate implements UI.ActionRegistration.ActionDeleg
1508
1515
  ElementsPanel.instance().toggleAccessibilityTree();
1509
1516
  return true;
1510
1517
  case 'elements.toggle-word-wrap': {
1511
- const setting = Common.Settings.Settings.instance().moduleSetting<boolean>('dom-word-wrap');
1518
+ const setting = ElementsPanel.instance().settings.moduleSetting<boolean>('dom-word-wrap');
1512
1519
  setting.set(!setting.get());
1513
1520
  return true;
1514
1521
  }
@@ -45,6 +45,7 @@ import * as SDK from '../../core/sdk/sdk.js';
45
45
  import * as Protocol from '../../generated/protocol.js';
46
46
  import * as AIAssistance from '../../models/ai_assistance/ai_assistance.js';
47
47
  import * as Badges from '../../models/badges/badges.js';
48
+ import * as Bindings from '../../models/bindings/bindings.js';
48
49
  import type * as Elements from '../../models/elements/elements.js';
49
50
  import type * as IssuesManager from '../../models/issues_manager/issues_manager.js';
50
51
  import * as TextUtils from '../../models/text_utils/text_utils.js';
@@ -302,6 +303,11 @@ const UIStrings = {
302
303
  * @description Label of an adorner next to the html node in the Elements panel.
303
304
  */
304
305
  viewSourceCode: 'View source code',
306
+ /**
307
+ * @description Label of an adorner in the Elements panel. When clicked, it reveals
308
+ * the definition of the custom element in the Sources panel.
309
+ */
310
+ showCustomElementDefinition: 'Show custom element definition',
305
311
  /**
306
312
  * @description Context menu item in Elements panel to assess visibility of an element via AI.
307
313
  */
@@ -444,6 +450,8 @@ export interface ViewInput {
444
450
  onViewSourceAdornerClick: () => void;
445
451
  onSlotAdornerClick: (e: Event) => void;
446
452
  showSlotAdorner: boolean;
453
+ showCustomElementAdorner: boolean;
454
+ onCustomElementAdornerClick: (e: Event) => void;
447
455
  slotName?: string;
448
456
  showStartingStyleAdorner: boolean;
449
457
  startingStyleAdornerActive: boolean;
@@ -961,7 +969,8 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
961
969
  const hasAdorners = !!input.adProvenance || input.showContainerAdorner || input.showFlexAdorner ||
962
970
  input.showGridAdorner || input.showGridLanesAdorner || input.showMediaAdorner || input.showPopoverAdorner ||
963
971
  input.showTopLayerAdorner || input.showViewSourceAdorner || input.showScrollAdorner ||
964
- input.showScrollSnapAdorner || input.showSlotAdorner || input.showStartingStyleAdorner;
972
+ input.showScrollSnapAdorner || input.showSlotAdorner || input.showStartingStyleAdorner ||
973
+ input.showCustomElementAdorner;
965
974
  const gutterContainerClasses = {
966
975
  'has-decorations': input.decorations.length || input.descendantDecorations.length,
967
976
  'gutter-container': true,
@@ -1004,6 +1013,18 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
1004
1013
  ${adornerRef()}>
1005
1014
  <span>${ElementsComponents.AdornerManager.RegisteredAdorners.VIEW_SOURCE}</span>
1006
1015
  </devtools-adorner>` : nothing}
1016
+ ${input.showCustomElementAdorner ? html`<devtools-adorner
1017
+ class="custom-element clickable"
1018
+ role=button
1019
+ tabindex=0
1020
+ .name=${ElementsComponents.AdornerManager.RegisteredAdorners.CUSTOM_ELEMENT}
1021
+ jslog=${VisualLogging.adorner(ElementsComponents.AdornerManager.RegisteredAdorners.CUSTOM_ELEMENT).track({ click: true })}
1022
+ aria-label=${i18nString(UIStrings.showCustomElementDefinition)}
1023
+ @click=${input.onCustomElementAdornerClick}
1024
+ @keydown=${handleAdornerKeydown(input.onCustomElementAdornerClick)}
1025
+ ${adornerRef()}>
1026
+ <span>${ElementsComponents.AdornerManager.RegisteredAdorners.CUSTOM_ELEMENT}</span>
1027
+ </devtools-adorner>` : nothing}
1007
1028
  ${input.showContainerAdorner ? html`<devtools-adorner
1008
1029
  class=clickable
1009
1030
  role=button
@@ -1333,50 +1354,53 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1333
1354
  return;
1334
1355
  }
1335
1356
  const output: ViewOutput = {};
1336
- DEFAULT_VIEW(
1337
- {
1338
- node: !clearNode ? this.nodeInternal : null,
1339
- isClosingTag: this.isClosingTag(),
1340
- expanded: this.expanded,
1341
- isExpandable: this.isExpandable(),
1342
- isXMLMimeType: Boolean(this.treeOutline?.isXMLMimeType),
1343
- updateRecord: this.#updateRecord,
1344
- onHighlightSearchResults: () => this.#highlightSearchResults(),
1345
- onExpand: () => this.expand(),
1346
-
1347
- containerAdornerActive: this.#containerAdornerActive,
1348
- adProvenance: this.nodeInternal.adProvenance(),
1349
- adTooltipId: this.#adTooltipId,
1350
- target: this.nodeInternal.domModel().target(),
1351
- showContainerAdorner: Boolean(this.#layout?.containerType) && !this.isClosingTag(),
1352
- containerType: this.#layout?.containerType,
1353
- showFlexAdorner: Boolean(this.#layout?.isFlex) && !this.isClosingTag(),
1354
- flexAdornerActive: this.#flexAdornerActive,
1355
- showGridAdorner: Boolean(this.#layout?.isGrid) && !this.isClosingTag(),
1356
- showGridLanesAdorner: Boolean(this.#layout?.isGridLanes) && !this.isClosingTag(),
1357
- showMediaAdorner: this.node().isMediaNode() && !this.isClosingTag(),
1358
- showPopoverAdorner: Boolean(Root.Runtime.hostConfig.devToolsAllowPopoverForcing?.enabled) &&
1359
- Boolean(this.node().attributes().find(attr => attr.name === 'popover')) && !this.isClosingTag(),
1360
- showTopLayerAdorner: this.node().topLayerIndex() !== -1 && !this.isClosingTag(),
1361
- gridAdornerActive: this.#gridAdornerActive,
1362
- popoverAdornerActive: this.#popoverAdornerActive,
1363
- isSubgrid: Boolean(this.#layout?.isSubgrid),
1364
- showViewSourceAdorner: this.nodeInternal.isRootNode() && isOpeningTag(this.tagTypeContext),
1365
- showScrollAdorner: ((this.node().nodeName() === 'HTML' && this.node().ownerDocument?.isScrollable()) ||
1366
- (this.node().nodeName() !== '#document' && this.node().isScrollable())) &&
1367
- !this.isClosingTag(),
1368
- decorations: this.#decorations,
1369
- descendantDecorations: this.expanded ? [] : this.#descendantDecorations,
1370
- decorationsTooltip: this.#decorationsTooltip,
1371
- indent: this.computeLeftIndent(),
1372
- showScrollSnapAdorner: Boolean(this.#layout?.hasScroll) && !this.isClosingTag(),
1373
- scrollSnapAdornerActive: this.#scrollSnapAdornerActive,
1374
- showSlotAdorner: Boolean(this.nodeInternal.assignedSlot) && !this.isClosingTag(),
1375
- showStartingStyleAdorner: this.nodeInternal.affectedByStartingStyles() && !this.isClosingTag(),
1376
- startingStyleAdornerActive: this.#startingStyleAdornerActive,
1377
- onStartingStyleAdornerClick:
1378
- this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onStartingStyleAdornerClick(event),
1379
- onSlotAdornerClick: () => {
1357
+ DEFAULT_VIEW({
1358
+ node: !clearNode ? this.nodeInternal : null,
1359
+ isClosingTag: this.isClosingTag(),
1360
+ expanded: this.expanded,
1361
+ isExpandable: this.isExpandable(),
1362
+ isXMLMimeType: Boolean(this.treeOutline?.isXMLMimeType),
1363
+ updateRecord: this.#updateRecord,
1364
+ onHighlightSearchResults: () => this.#highlightSearchResults(),
1365
+ onExpand: () => this.expand(),
1366
+
1367
+ containerAdornerActive: this.#containerAdornerActive,
1368
+ adProvenance: this.nodeInternal.adProvenance(),
1369
+ adTooltipId: this.#adTooltipId,
1370
+ target: this.nodeInternal.domModel().target(),
1371
+ showContainerAdorner: Boolean(this.#layout?.containerType) && !this.isClosingTag(),
1372
+ containerType: this.#layout?.containerType,
1373
+ showFlexAdorner: Boolean(this.#layout?.isFlex) && !this.isClosingTag(),
1374
+ flexAdornerActive: this.#flexAdornerActive,
1375
+ showGridAdorner: Boolean(this.#layout?.isGrid) && !this.isClosingTag(),
1376
+ showGridLanesAdorner: Boolean(this.#layout?.isGridLanes) && !this.isClosingTag(),
1377
+ showMediaAdorner: this.node().isMediaNode() && !this.isClosingTag(),
1378
+ showPopoverAdorner: Boolean(Root.Runtime.hostConfig.devToolsAllowPopoverForcing?.enabled) &&
1379
+ Boolean(this.node().attributes().find(attr => attr.name === 'popover')) && !this.isClosingTag(),
1380
+ showTopLayerAdorner: this.node().topLayerIndex() !== -1 && !this.isClosingTag(),
1381
+ gridAdornerActive: this.#gridAdornerActive,
1382
+ popoverAdornerActive: this.#popoverAdornerActive,
1383
+ isSubgrid: Boolean(this.#layout?.isSubgrid),
1384
+ showViewSourceAdorner: this.nodeInternal.isRootNode() && isOpeningTag(this.tagTypeContext),
1385
+ showScrollAdorner: ((this.node().nodeName() === 'HTML' && this.node().ownerDocument?.isScrollable()) ||
1386
+ (this.node().nodeName() !== '#document' && this.node().isScrollable())) &&
1387
+ !this.isClosingTag(),
1388
+ decorations: this.#decorations,
1389
+ descendantDecorations: this.expanded ? [] : this.#descendantDecorations,
1390
+ decorationsTooltip: this.#decorationsTooltip,
1391
+ indent: this.computeLeftIndent(),
1392
+ showScrollSnapAdorner: Boolean(this.#layout?.hasScroll) && !this.isClosingTag(),
1393
+ scrollSnapAdornerActive: this.#scrollSnapAdornerActive,
1394
+ showSlotAdorner: Boolean(this.nodeInternal.assignedSlot) && !this.isClosingTag(),
1395
+ showCustomElementAdorner: this.node().isCustomElement() && !this.isClosingTag(),
1396
+ onCustomElementAdornerClick:
1397
+ this.treeOutline?.disableEdits ? () => {} : (event: Event) => void this.#onCustomElementAdornerClick(event),
1398
+ showStartingStyleAdorner: this.nodeInternal.affectedByStartingStyles() && !this.isClosingTag(),
1399
+ startingStyleAdornerActive: this.#startingStyleAdornerActive,
1400
+ onStartingStyleAdornerClick:
1401
+ this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onStartingStyleAdornerClick(event),
1402
+ onSlotAdornerClick:
1403
+ () => {
1380
1404
  if (this.nodeInternal.assignedSlot) {
1381
1405
  const deferredNode = this.nodeInternal.assignedSlot.deferredNode;
1382
1406
  deferredNode.resolve(node => {
@@ -1384,47 +1408,45 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1384
1408
  });
1385
1409
  }
1386
1410
  },
1387
- topLayerIndex: this.node().topLayerIndex(),
1388
- onViewSourceAdornerClick: this.treeOutline?.disableEdits ? () => {} : this.revealHTMLInSources.bind(this),
1389
- onGutterClick: this.showContextMenu.bind(this),
1390
- onContainerAdornerClick:
1391
- this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onContainerAdornerClick(event),
1392
- onFlexAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1393
- (event: Event) => this.#onFlexAdornerClick(event),
1394
- onGridAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1395
- (event: Event) => this.#onGridAdornerClick(event),
1396
- onMediaAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1397
- (event: Event) => this.#onMediaAdornerClick(event),
1398
- onPopoverAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1399
- (event: Event) => this.#onPopoverAdornerClick(event),
1400
- onScrollSnapAdornerClick:
1401
- this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onScrollSnapAdornerClick(event),
1402
- onTopLayerAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1403
- () => {
1404
- if (!this.treeOutline) {
1405
- return;
1406
- }
1407
- this.treeOutline.revealInTopLayer(this.node());
1408
- },
1409
- isHovered: this.#hovered,
1410
- isSelected: this.selected,
1411
- showAiButton: Boolean(this.#hovered || this.selected) && this.node().nodeType() === Node.ELEMENT_NODE &&
1412
- this.isAiButtonEnabled() && (this.treeOutline as ElementsTreeOutline)?.showAIButton,
1413
- aiButtonTitle: this.isAiButtonEnabled() ?
1414
- UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button').title() :
1415
- undefined,
1416
- onAiButtonClick: (ev: Event) => {
1417
- ev.stopPropagation();
1418
- this.select(true, false);
1419
- const action = UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button');
1420
- if (action) {
1421
- void action.execute();
1422
- }
1423
- },
1424
- editorState: this.#editorState,
1425
- editorWidth: this.#editorWidth,
1426
- },
1427
- output, this.listItemElement);
1411
+ topLayerIndex: this.node().topLayerIndex(),
1412
+ onViewSourceAdornerClick: this.treeOutline?.disableEdits ? () => {} : this.revealHTMLInSources.bind(this),
1413
+ onGutterClick: this.showContextMenu.bind(this),
1414
+ onContainerAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1415
+ (event: Event) => this.#onContainerAdornerClick(event),
1416
+ onFlexAdornerClick: this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onFlexAdornerClick(event),
1417
+ onGridAdornerClick: this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onGridAdornerClick(event),
1418
+ onMediaAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1419
+ (event: Event) => this.#onMediaAdornerClick(event),
1420
+ onPopoverAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1421
+ (event: Event) => this.#onPopoverAdornerClick(event),
1422
+ onScrollSnapAdornerClick:
1423
+ this.treeOutline?.disableEdits ? () => {} : (event: Event) => this.#onScrollSnapAdornerClick(event),
1424
+ onTopLayerAdornerClick: this.treeOutline?.disableEdits ? () => {} :
1425
+ () => {
1426
+ if (!this.treeOutline) {
1427
+ return;
1428
+ }
1429
+ this.treeOutline.revealInTopLayer(this.node());
1430
+ },
1431
+ isHovered: this.#hovered,
1432
+ isSelected: this.selected,
1433
+ showAiButton: Boolean(this.#hovered || this.selected) && this.node().nodeType() === Node.ELEMENT_NODE &&
1434
+ this.isAiButtonEnabled() && (this.treeOutline as ElementsTreeOutline)?.showAIButton,
1435
+ aiButtonTitle: this.isAiButtonEnabled() ?
1436
+ UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button').title() :
1437
+ undefined,
1438
+ onAiButtonClick: (ev: Event) => {
1439
+ ev.stopPropagation();
1440
+ this.select(true, false);
1441
+ const action = UI.ActionRegistry.ActionRegistry.instance().getAction('freestyler.elements-floating-button');
1442
+ if (action) {
1443
+ void action.execute();
1444
+ }
1445
+ },
1446
+ editorState: this.#editorState,
1447
+ editorWidth: this.#editorWidth,
1448
+ },
1449
+ output, this.listItemElement);
1428
1450
 
1429
1451
  this.#contentElement = output.contentElement;
1430
1452
  this.#editorRef = output.editorRef;
@@ -1527,6 +1549,10 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1527
1549
  return !isOpeningTag(this.tagTypeContext);
1528
1550
  }
1529
1551
 
1552
+ isDisplayContents(): boolean {
1553
+ return Boolean(this.#layout?.isContents);
1554
+ }
1555
+
1530
1556
  node(): SDK.DOMModel.DOMNode {
1531
1557
  return this.nodeInternal;
1532
1558
  }
@@ -1732,63 +1758,64 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
1732
1758
  // ElementsPanel.
1733
1759
  // We do not change the ElementsTreeElement state in case the
1734
1760
  // element is bound again.
1735
- DEFAULT_VIEW(
1736
- {
1737
- node: null,
1738
- isClosingTag: false,
1739
- expanded: false,
1740
- isExpandable: false,
1741
- isXMLMimeType: false,
1742
- updateRecord: null,
1743
- onHighlightSearchResults: () => {},
1744
- onExpand: () => {},
1745
- containerAdornerActive: false,
1746
- adProvenance: undefined,
1747
- target: undefined,
1748
- adTooltipId: '',
1749
- showContainerAdorner: false,
1750
- containerType: this.#layout?.containerType,
1751
- showFlexAdorner: false,
1752
- flexAdornerActive: false,
1753
- showGridAdorner: false,
1754
- showGridLanesAdorner: false,
1755
- showMediaAdorner: false,
1756
- showPopoverAdorner: false,
1757
- showTopLayerAdorner: false,
1758
- gridAdornerActive: false,
1759
- popoverAdornerActive: false,
1760
- isSubgrid: false,
1761
- showViewSourceAdorner: false,
1762
- showScrollAdorner: false,
1763
- showScrollSnapAdorner: false,
1764
- scrollSnapAdornerActive: false,
1765
- showSlotAdorner: false,
1766
- showStartingStyleAdorner: false,
1767
- startingStyleAdornerActive: false,
1768
- onStartingStyleAdornerClick: () => {},
1769
- onSlotAdornerClick: () => {},
1770
- topLayerIndex: -1,
1771
- onViewSourceAdornerClick: () => {},
1772
- onGutterClick: () => {},
1773
- onContainerAdornerClick: () => {},
1774
- onFlexAdornerClick: () => {},
1775
- onGridAdornerClick: () => {},
1776
- onMediaAdornerClick: () => {},
1777
- onPopoverAdornerClick: () => {},
1778
- onScrollSnapAdornerClick: () => {},
1779
- onTopLayerAdornerClick: () => {},
1780
- isHovered: false,
1781
- isSelected: false,
1782
- showAiButton: false,
1783
- onAiButtonClick: () => {},
1784
- decorations: [],
1785
- descendantDecorations: [],
1786
- decorationsTooltip: '',
1787
- indent: 0,
1788
- editorState: null,
1789
- editorWidth: null,
1790
- },
1791
- {}, this.listItemElement);
1761
+ DEFAULT_VIEW({
1762
+ node: null,
1763
+ isClosingTag: false,
1764
+ expanded: false,
1765
+ isExpandable: false,
1766
+ isXMLMimeType: false,
1767
+ updateRecord: null,
1768
+ onHighlightSearchResults: () => {},
1769
+ onExpand: () => {},
1770
+ containerAdornerActive: false,
1771
+ adProvenance: undefined,
1772
+ target: undefined,
1773
+ adTooltipId: '',
1774
+ showContainerAdorner: false,
1775
+ containerType: this.#layout?.containerType,
1776
+ showFlexAdorner: false,
1777
+ flexAdornerActive: false,
1778
+ showGridAdorner: false,
1779
+ showGridLanesAdorner: false,
1780
+ showMediaAdorner: false,
1781
+ showPopoverAdorner: false,
1782
+ showTopLayerAdorner: false,
1783
+ gridAdornerActive: false,
1784
+ popoverAdornerActive: false,
1785
+ isSubgrid: false,
1786
+ showViewSourceAdorner: false,
1787
+ showScrollAdorner: false,
1788
+ showScrollSnapAdorner: false,
1789
+ scrollSnapAdornerActive: false,
1790
+ showSlotAdorner: false,
1791
+ showCustomElementAdorner: false,
1792
+ showStartingStyleAdorner: false,
1793
+ startingStyleAdornerActive: false,
1794
+ onStartingStyleAdornerClick: () => {},
1795
+ onSlotAdornerClick: () => {},
1796
+ onCustomElementAdornerClick: () => {},
1797
+ topLayerIndex: -1,
1798
+ onViewSourceAdornerClick: () => {},
1799
+ onGutterClick: () => {},
1800
+ onContainerAdornerClick: () => {},
1801
+ onFlexAdornerClick: () => {},
1802
+ onGridAdornerClick: () => {},
1803
+ onMediaAdornerClick: () => {},
1804
+ onPopoverAdornerClick: () => {},
1805
+ onScrollSnapAdornerClick: () => {},
1806
+ onTopLayerAdornerClick: () => {},
1807
+ isHovered: false,
1808
+ isSelected: false,
1809
+ showAiButton: false,
1810
+ onAiButtonClick: () => {},
1811
+ decorations: [],
1812
+ descendantDecorations: [],
1813
+ decorationsTooltip: '',
1814
+ indent: 0,
1815
+ editorState: null,
1816
+ editorWidth: null,
1817
+ },
1818
+ {}, this.listItemElement);
1792
1819
  }
1793
1820
 
1794
1821
  override onunbind(): void {
@@ -3211,6 +3238,44 @@ export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
3211
3238
  this.#startingStyleAdornerActive = !this.#startingStyleAdornerActive;
3212
3239
  this.performUpdate();
3213
3240
  }
3241
+
3242
+ async #onCustomElementAdornerClick(event: Event): Promise<void> {
3243
+ event.stopPropagation();
3244
+ const node = this.node();
3245
+ const object = await node.resolveToObject('');
3246
+ if (!object) {
3247
+ return;
3248
+ }
3249
+ let constructorObject: SDK.RemoteObject.RemoteObject|null = null;
3250
+ try {
3251
+ const result = await object.callFunction(function(this: Element): unknown {
3252
+ const selector = this.getAttribute('is') || this.tagName.toLowerCase();
3253
+ return (typeof customElements !== 'undefined' && customElements.get(selector)) || this.constructor;
3254
+ });
3255
+ constructorObject = result.object;
3256
+ } finally {
3257
+ object.release();
3258
+ }
3259
+ if (!constructorObject) {
3260
+ return;
3261
+ }
3262
+ try {
3263
+ if (constructorObject.type === 'function') {
3264
+ const functionDetails =
3265
+ await SDK.RemoteObject.RemoteFunction.objectAsFunction(constructorObject).targetFunctionDetails();
3266
+ if (functionDetails?.location) {
3267
+ const uiLocation =
3268
+ await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().rawLocationToUILocation(
3269
+ functionDetails.location);
3270
+ if (uiLocation) {
3271
+ void Common.Revealer.reveal(uiLocation);
3272
+ }
3273
+ }
3274
+ }
3275
+ } finally {
3276
+ constructorObject.release();
3277
+ }
3278
+ }
3214
3279
  }
3215
3280
 
3216
3281
  export const InitialChildrenLimit = 500;
@@ -1387,8 +1387,9 @@ export class ElementsTreeOutline extends
1387
1387
 
1388
1388
  private highlightTreeElement(element: UI.TreeOutline.TreeElement, showInfo: boolean): void {
1389
1389
  if (element instanceof ElementsTreeElement) {
1390
- element.node().domModel().overlayModel().highlightInOverlay(
1391
- {node: element.node(), selectorList: undefined}, 'all', showInfo);
1390
+ const selectorList = element.isDisplayContents() ? '*' : undefined;
1391
+ element.node().domModel().overlayModel().highlightInOverlay({node: element.node(), selectorList}, 'all',
1392
+ showInfo);
1392
1393
  return;
1393
1394
  }
1394
1395
 
@@ -12,6 +12,7 @@ type AdornerSettingsMap = Map<string, boolean>;
12
12
  export enum RegisteredAdorners {
13
13
  AD = 'ad',
14
14
  CONTAINER = 'container',
15
+ CUSTOM_ELEMENT = 'custom-element',
15
16
  FLEX = 'flex',
16
17
  GRID = 'grid',
17
18
  GRID_LANES = 'grid-lanes',
@@ -186,9 +186,10 @@ UI.ViewManager.registerViewExtension({
186
186
  order: 10,
187
187
  persistence: UI.ViewManager.ViewPersistence.PERMANENT,
188
188
  hasToolbar: false,
189
- async loadView() {
189
+ async loadView(universe) {
190
190
  const Elements = await loadElementsModule();
191
- return Elements.ElementsPanel.ElementsPanel.instance();
191
+ const {targetManager, settings} = universe;
192
+ return Elements.ElementsPanel.ElementsPanel.instance({forceNew: null, targetManager, settings});
192
193
  },
193
194
  });
194
195