chrome-devtools-frontend 1.0.1018569 → 1.0.1019968

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 (40) hide show
  1. package/config/gni/devtools_grd_files.gni +3 -0
  2. package/front_end/core/i18n/locales/en-US.json +7 -1
  3. package/front_end/core/i18n/locales/en-XL.json +7 -1
  4. package/front_end/core/sdk/CSSMatchedStyles.ts +1 -1
  5. package/front_end/core/sdk/CSSModel.ts +22 -0
  6. package/front_end/core/sdk/CSSQuery.ts +2 -1
  7. package/front_end/core/sdk/CSSRule.ts +4 -0
  8. package/front_end/core/sdk/CSSScope.ts +30 -0
  9. package/front_end/core/sdk/sdk.ts +2 -0
  10. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +7 -6
  11. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
  12. package/front_end/generated/InspectorBackendCommands.js +13 -3
  13. package/front_end/generated/SupportedCSSProperties.js +2 -2
  14. package/front_end/generated/protocol-mapping.d.ts +5 -0
  15. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  16. package/front_end/generated/protocol.ts +43 -0
  17. package/front_end/models/bindings/BreakpointManager.ts +22 -14
  18. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -19
  19. package/front_end/panels/elements/CSSRuleValidator.ts +100 -0
  20. package/front_end/panels/elements/ElementsTreeOutline.ts +44 -8
  21. package/front_end/panels/elements/StylePropertiesSection.ts +35 -3
  22. package/front_end/panels/elements/StylePropertyTreeElement.ts +59 -0
  23. package/front_end/panels/elements/StylesSidebarPane.ts +28 -8
  24. package/front_end/panels/elements/TopLayerContainer.ts +9 -1
  25. package/front_end/panels/elements/components/AdornerManager.ts +7 -0
  26. package/front_end/panels/elements/elements.ts +3 -0
  27. package/front_end/panels/elements/elementsTreeOutline.css +4 -0
  28. package/front_end/panels/elements/stylesSectionTree.css +10 -0
  29. package/front_end/panels/emulation/DeviceModeToolbar.ts +1 -0
  30. package/front_end/panels/network/components/RequestHeadersView.ts +16 -16
  31. package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspector.ts +23 -1
  32. package/front_end/ui/components/linear_memory_inspector/LinearMemoryViewer.ts +18 -1
  33. package/front_end/ui/components/linear_memory_inspector/LinearMemoryViewerUtils.ts +8 -0
  34. package/front_end/ui/components/linear_memory_inspector/linearMemoryViewer.css +4 -0
  35. package/front_end/ui/components/linear_memory_inspector/linear_memory_inspector.ts +2 -0
  36. package/front_end/ui/components/node_text/nodeText.css +5 -5
  37. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -8
  38. package/front_end/ui/components/panel_feedback/previewToggle.css +1 -7
  39. package/front_end/ui/components/tree_outline/treeOutline.css +1 -0
  40. package/package.json +1 -1
@@ -35,10 +35,12 @@
35
35
  import * as Common from '../../core/common/common.js';
36
36
  import * as i18n from '../../core/i18n/i18n.js';
37
37
  import * as SDK from '../../core/sdk/sdk.js';
38
+ import * as Adorners from '../../ui/components/adorners/adorners.js';
38
39
  import * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';
40
+ import * as IconButton from '../../ui/components/icon_button/icon_button.js';
39
41
  import * as UI from '../../ui/legacy/legacy.js';
40
42
 
41
- import {linkifyDeferredNodeReference} from './DOMLinkifier.js';
43
+ import * as ElementsComponents from './components/components.js';
42
44
  import {ElementsPanel} from './ElementsPanel.js';
43
45
  import {ElementsTreeElement, InitialChildrenLimit} from './ElementsTreeElement.js';
44
46
  import elementsTreeOutlineStyles from './elementsTreeOutline.css.js';
@@ -555,7 +557,9 @@ export class ElementsTreeOutline extends
555
557
  // items extend at least to the right edge of the outer <ol> container.
556
558
  // In the no-word-wrap mode the outer <ol> may be wider than the tree container
557
559
  // (and partially hidden), in which case we are left to use only its right boundary.
558
- const x = scrollContainer.totalOffsetLeft() + scrollContainer.offsetWidth - 18;
560
+ // We use .clientWidth to account for possible scrollbar, and subtract 6px
561
+ // for the width of the split widget (see splitWidget.css).
562
+ const x = scrollContainer.totalOffsetLeft() + scrollContainer.clientWidth - 6;
559
563
 
560
564
  const y = event.pageY;
561
565
 
@@ -1627,13 +1631,45 @@ export class ShortcutTreeElement extends UI.TreeOutline.TreeElement {
1627
1631
  text = '<' + text + '>';
1628
1632
  }
1629
1633
  title.textContent = '\u21AA ' + text;
1630
-
1631
- const link = (linkifyDeferredNodeReference(nodeShortcut.deferredNode) as Element);
1632
- UI.UIUtils.createTextChild(this.listItemElement, ' ');
1633
- link.classList.add('elements-tree-shortcut-link');
1634
- link.textContent = i18nString(UIStrings.reveal);
1635
- this.listItemElement.appendChild(link);
1636
1634
  this.nodeShortcut = nodeShortcut;
1635
+ this.addRevealAdorner();
1636
+ }
1637
+
1638
+ addRevealAdorner(): void {
1639
+ const adorner = new Adorners.Adorner.Adorner();
1640
+ adorner.classList.add('adorner-reveal');
1641
+ const config = ElementsComponents.AdornerManager.getRegisteredAdorner(
1642
+ ElementsComponents.AdornerManager.RegisteredAdorners.REVEAL);
1643
+ const name = config.name;
1644
+ const adornerContent = document.createElement('span');
1645
+ const linkIcon = new IconButton.Icon.Icon();
1646
+ linkIcon
1647
+ .data = {iconName: 'ic_show_node_16x16', color: 'var(--color-text-disabled)', width: '12px', height: '12px'};
1648
+ const slotText = document.createElement('span');
1649
+ slotText.textContent = name;
1650
+ adornerContent.append(linkIcon);
1651
+ adornerContent.append(slotText);
1652
+ adornerContent.classList.add('adorner-with-icon');
1653
+ adorner.data = {
1654
+ name,
1655
+ content: adornerContent,
1656
+ };
1657
+ this.listItemElement.appendChild(adorner);
1658
+ const onClick = (((): void => {
1659
+ this.nodeShortcut.deferredNode.resolve(
1660
+ node => {
1661
+ void Common.Revealer.reveal(node);
1662
+ },
1663
+ );
1664
+ }) as EventListener);
1665
+ adorner.addInteraction(onClick, {
1666
+ isToggle: false,
1667
+ shouldPropagateOnKeydown: false,
1668
+ ariaLabelDefault: i18nString(UIStrings.reveal),
1669
+ ariaLabelActive: i18nString(UIStrings.reveal),
1670
+ });
1671
+ adorner.addEventListener('mousedown', e => e.consume(), false);
1672
+ ElementsPanel.instance().registerAdorner(adorner);
1637
1673
  }
1638
1674
 
1639
1675
  get hovered(): boolean {
@@ -121,6 +121,8 @@ export class StylePropertiesSection {
121
121
  protected parentPane: StylesSidebarPane;
122
122
  styleInternal: SDK.CSSStyleDeclaration.CSSStyleDeclaration;
123
123
  readonly matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles;
124
+ private computedStyles: Map<string, string>|null;
125
+ private parentsComputedStyles: Map<string, string>|null;
124
126
  editable: boolean;
125
127
  private hoverTimer: number|null;
126
128
  private willCauseCancelEditing: boolean;
@@ -152,11 +154,14 @@ export class StylePropertiesSection {
152
154
 
153
155
  constructor(
154
156
  parentPane: StylesSidebarPane, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
155
- style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
157
+ style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number, computedStyles: Map<string, string>|null,
158
+ parentsComputedStyles: Map<string, string>|null) {
156
159
  this.parentPane = parentPane;
157
160
  this.sectionIdx = sectionIdx;
158
161
  this.styleInternal = style;
159
162
  this.matchedStyles = matchedStyles;
163
+ this.computedStyles = computedStyles;
164
+ this.parentsComputedStyles = parentsComputedStyles;
160
165
  this.editable = Boolean(style.styleSheetId && style.range);
161
166
  this.hoverTimer = null;
162
167
  this.willCauseCancelEditing = false;
@@ -703,6 +708,7 @@ export class StylePropertiesSection {
703
708
  protected createAtRuleLists(rule: SDK.CSSRule.CSSStyleRule): void {
704
709
  this.createMediaList(rule.media);
705
710
  this.createContainerQueryList(rule.containerQueries);
711
+ this.createScopesList(rule.scopes);
706
712
  this.createSupportsList(rule.supports);
707
713
  }
708
714
 
@@ -773,6 +779,28 @@ export class StylePropertiesSection {
773
779
  }
774
780
  }
775
781
 
782
+ protected createScopesList(scopesList: SDK.CSSScope.CSSScope[]): void {
783
+ for (let i = scopesList.length - 1; i >= 0; --i) {
784
+ const scope = scopesList[i];
785
+ if (!scope.text) {
786
+ continue;
787
+ }
788
+
789
+ let onQueryTextClick;
790
+ if (scope.styleSheetId) {
791
+ onQueryTextClick = this.handleQueryRuleClick.bind(this, scope);
792
+ }
793
+
794
+ const scopeElement = new ElementsComponents.CSSQuery.CSSQuery();
795
+ scopeElement.data = {
796
+ queryPrefix: '@scope',
797
+ queryText: scope.text,
798
+ onQueryTextClick,
799
+ };
800
+ this.queryListElement.append(scopeElement);
801
+ }
802
+ }
803
+
776
804
  protected createSupportsList(supportsList: SDK.CSSSupports.CSSSupports[]): void {
777
805
  for (let i = supportsList.length - 1; i >= 0; --i) {
778
806
  const supports = supportsList[i];
@@ -932,6 +960,8 @@ export class StylePropertiesSection {
932
960
  }
933
961
  const item = new StylePropertyTreeElement(
934
962
  this.parentPane, this.matchedStyles, property, isShorthand, inherited, overloaded, false);
963
+ item.setComputedStyles(this.computedStyles);
964
+ item.setParentsComputedStyles(this.parentsComputedStyles);
935
965
  this.propertiesTreeOutline.appendChild(item);
936
966
  }
937
967
 
@@ -1178,6 +1208,8 @@ export class StylePropertiesSection {
1178
1208
  success = await cssModel.setContainerQueryText(query.styleSheetId, range, newContent);
1179
1209
  } else if (query instanceof SDK.CSSSupports.CSSSupports) {
1180
1210
  success = await cssModel.setSupportsText(query.styleSheetId, range, newContent);
1211
+ } else if (query instanceof SDK.CSSScope.CSSScope) {
1212
+ success = await cssModel.setScopeText(query.styleSheetId, range, newContent);
1181
1213
  } else {
1182
1214
  success = await cssModel.setMediaText(query.styleSheetId, range, newContent);
1183
1215
  }
@@ -1449,7 +1481,7 @@ export class BlankStylePropertiesSection extends StylePropertiesSection {
1449
1481
  insertAfterStyle: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
1450
1482
  const cssModel = (stylesPane.cssModel() as SDK.CSSModel.CSSModel);
1451
1483
  const rule = SDK.CSSRule.CSSStyleRule.createDummyRule(cssModel, defaultSelectorText);
1452
- super(stylesPane, matchedStyles, rule.style, sectionIdx);
1484
+ super(stylesPane, matchedStyles, rule.style, sectionIdx, null, null);
1453
1485
  this.normal = false;
1454
1486
  this.ruleLocation = ruleLocation;
1455
1487
  this.styleSheetId = styleSheetId;
@@ -1553,7 +1585,7 @@ export class KeyframePropertiesSection extends StylePropertiesSection {
1553
1585
  constructor(
1554
1586
  stylesPane: StylesSidebarPane, matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
1555
1587
  style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, sectionIdx: number) {
1556
- super(stylesPane, matchedStyles, style, sectionIdx);
1588
+ super(stylesPane, matchedStyles, style, sectionIdx, null, null);
1557
1589
  this.selectorElement.className = 'keyframe-key';
1558
1590
  }
1559
1591
 
@@ -21,6 +21,7 @@ import {StyleEditorWidget} from './StyleEditorWidget.js';
21
21
  import type {StylePropertiesSection} from './StylePropertiesSection.js';
22
22
  import {CSSPropertyPrompt, StylesSidebarPane, StylesSidebarPropertyRenderer} from './StylesSidebarPane.js';
23
23
  import {getCssDeclarationAsJavascriptProperty} from './StylePropertyUtils.js';
24
+ import {cssRuleValidatorsMap} from './CSSRuleValidator.js';
24
25
 
25
26
  const FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;
26
27
  const GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;
@@ -120,6 +121,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
120
121
  private hasBeenEditedIncrementally: boolean;
121
122
  private prompt: CSSPropertyPrompt|null;
122
123
  private lastComputedValue: string|null;
124
+ private computedStyles: Map<string, string>|null = null;
125
+ private parentsComputedStyles: Map<string, string>|null = null;
123
126
  private contextForTest!: Context|undefined;
124
127
  #propertyTextFromSource: string;
125
128
 
@@ -179,6 +182,14 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
179
182
  this.updateState();
180
183
  }
181
184
 
185
+ setComputedStyles(computedStyles: Map<string, string>|null): void {
186
+ this.computedStyles = computedStyles;
187
+ }
188
+
189
+ setParentsComputedStyles(parentsComputedStyles: Map<string, string>|null): void {
190
+ this.parentsComputedStyles = parentsComputedStyles;
191
+ }
192
+
182
193
  get name(): string {
183
194
  return this.property.name;
184
195
  }
@@ -568,6 +579,8 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
568
579
  const item = new StylePropertyTreeElement(
569
580
  this.parentPaneInternal, this.matchedStylesInternal, longhandProperties[i], false, inherited, overloaded,
570
581
  false);
582
+ item.setComputedStyles(this.computedStyles);
583
+ item.setParentsComputedStyles(this.parentsComputedStyles);
571
584
  this.appendChild(item);
572
585
  }
573
586
  }
@@ -702,6 +715,17 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
702
715
  }
703
716
  }
704
717
 
718
+ const hintMessage = this.getHintMessage(this.computedStyles, this.parentsComputedStyles);
719
+ if (hintMessage !== null) {
720
+ const hintIcon = UI.Icon.Icon.create('mediumicon-info', 'hint');
721
+ const hintPopover =
722
+ new UI.PopoverHelper.PopoverHelper(hintIcon, event => this.handleHintPopoverRequest(hintMessage, event));
723
+ hintPopover.setHasPadding(true);
724
+ hintPopover.setTimeout(0, 100);
725
+
726
+ this.listItemElement.append(hintIcon);
727
+ }
728
+
705
729
  if (!this.property.parsedOk) {
706
730
  // Avoid having longhands under an invalid shorthand.
707
731
  this.listItemElement.classList.add('not-parsed-ok');
@@ -793,6 +817,41 @@ export class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {
793
817
  StylesSidebarPane.createExclamationMark(this.property, warnings.join(' ')), this.listItemElement.firstChild);
794
818
  }
795
819
 
820
+ private getHintMessage(computedStyles: Map<string, string>|null, parentComputedStyles: Map<string, string>|null):
821
+ string|null {
822
+ const propertyName = this.property.name;
823
+
824
+ if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.CSS_AUTHORING_HINTS) ||
825
+ !cssRuleValidatorsMap.has(propertyName)) {
826
+ return null;
827
+ }
828
+
829
+ for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {
830
+ if (!validator.isRuleValid(computedStyles, parentComputedStyles)) {
831
+ return validator.getHintMessage(propertyName);
832
+ }
833
+ }
834
+
835
+ return null;
836
+ }
837
+
838
+ private handleHintPopoverRequest(hintMessageContent: string, event: Event): UI.PopoverHelper.PopoverRequest|null {
839
+ const link = event.composedPath()[0];
840
+ Platform.DCHECK(() => link instanceof Element, 'Link is not an instance of Element');
841
+
842
+ return {
843
+ box: (link as Element).boxInWindow(),
844
+ show: async(popover: UI.GlassPane.GlassPane): Promise<boolean> => {
845
+ const node = this.node();
846
+ if (!node) {
847
+ return false;
848
+ }
849
+ popover.contentElement.insertAdjacentHTML('beforeend', hintMessageContent);
850
+ return true;
851
+ },
852
+ };
853
+ }
854
+
796
855
  private mouseUp(event: MouseEvent): void {
797
856
  const activeTreeElement = parentMap.get(this.parentPaneInternal);
798
857
  parentMap.delete(this.parentPaneInternal);
@@ -583,8 +583,16 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
583
583
  }, 200 /* only spin for loading time > 200ms to avoid unpleasant render flashes */);
584
584
  }
585
585
 
586
+ const node = this.node();
587
+ // TODO: Fetch the parent node id using CDP command
588
+ const parentNode = node ? node.parentNode : null;
589
+
590
+ const [computedStyles, parentsComputedStyles] =
591
+ await Promise.all([this.fetchComputedStylesFor(node), this.fetchComputedStylesFor(parentNode)]);
592
+
586
593
  const matchedStyles = await this.fetchMatchedCascade();
587
- await this.innerRebuildUpdate(matchedStyles);
594
+
595
+ await this.innerRebuildUpdate(matchedStyles, computedStyles, parentsComputedStyles);
588
596
  if (!this.initialUpdateCompleted) {
589
597
  this.initialUpdateCompleted = true;
590
598
  this.appendToolbarItem(this.createRenderingShortcuts());
@@ -599,6 +607,13 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
599
607
  this.dispatchEventToListeners(Events.StylesUpdateCompleted, {hasMatchedStyles: this.hasMatchedStyles});
600
608
  }
601
609
 
610
+ private async fetchComputedStylesFor(node: SDK.DOMModel.DOMNode|null): Promise<Map<string, string>|null> {
611
+ if (!node) {
612
+ return null;
613
+ }
614
+ return await node.domModel().cssModel().getComputedStyle(node.id);
615
+ }
616
+
602
617
  onResize(): void {
603
618
  void this.resizeThrottler.schedule(this.innerResize.bind(this));
604
619
  }
@@ -718,7 +733,9 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
718
733
  }
719
734
  }
720
735
 
721
- private async innerRebuildUpdate(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null): Promise<void> {
736
+ private async innerRebuildUpdate(
737
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles|null, computedStyles: Map<string, string>|null,
738
+ parentsComputedStyles: Map<string, string>|null): Promise<void> {
722
739
  // ElementsSidebarPane's throttler schedules this method. Usually,
723
740
  // rebuild is suppressed while editing (see onCSSModelChanged()), but we need a
724
741
  // 'force' flag since the currently running throttler process cannot be canceled.
@@ -742,8 +759,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
742
759
  return;
743
760
  }
744
761
 
745
- this.sectionBlocks =
746
- await this.rebuildSectionsForMatchedStyleRules((matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles));
762
+ this.sectionBlocks = await this.rebuildSectionsForMatchedStyleRules(
763
+ (matchedStyles as SDK.CSSMatchedStyles.CSSMatchedStyles), computedStyles, parentsComputedStyles);
747
764
 
748
765
  // Style sections maybe re-created when flexbox editor is activated.
749
766
  // With the following code we re-bind the flexbox editor to the new
@@ -814,8 +831,9 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
814
831
  // For sniffing in tests.
815
832
  }
816
833
 
817
- private async rebuildSectionsForMatchedStyleRules(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles):
818
- Promise<SectionBlock[]> {
834
+ private async rebuildSectionsForMatchedStyleRules(
835
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles, computedStyles: Map<string, string>|null,
836
+ parentsComputedStyles: Map<string, string>|null): Promise<SectionBlock[]> {
819
837
  if (this.idleCallbackManager) {
820
838
  this.idleCallbackManager.discard();
821
839
  }
@@ -872,7 +890,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
872
890
  const lastBlock = blocks[blocks.length - 1];
873
891
  if (lastBlock) {
874
892
  this.idleCallbackManager.schedule(() => {
875
- const section = new StylePropertiesSection(this, matchedStyles, style, sectionIdx);
893
+ const section =
894
+ new StylePropertiesSection(this, matchedStyles, style, sectionIdx, computedStyles, parentsComputedStyles);
876
895
  sectionIdx++;
877
896
  lastBlock.sections.push(section);
878
897
  });
@@ -941,7 +960,8 @@ export class StylesSidebarPane extends Common.ObjectWrapper.eventMixin<EventType
941
960
  addLayerSeparator(style);
942
961
  const lastBlock = blocks[blocks.length - 1];
943
962
  this.idleCallbackManager.schedule(() => {
944
- const section = new HighlightPseudoStylePropertiesSection(this, matchedStyles, style, sectionIdx);
963
+ const section = new HighlightPseudoStylePropertiesSection(
964
+ this, matchedStyles, style, sectionIdx, computedStyles, parentsComputedStyles);
945
965
  sectionIdx++;
946
966
  lastBlock.sections.push(section);
947
967
  });
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  import * as i18n from '../../core/i18n/i18n.js';
5
5
  import * as SDK from '../../core/sdk/sdk.js';
6
+ import * as IconButton from '../../ui/components/icon_button/icon_button.js';
6
7
  import * as UI from '../../ui/legacy/legacy.js';
7
8
 
8
9
  import * as ElementsComponents from './components/components.js';
@@ -79,7 +80,14 @@ export class TopLayerContainer extends UI.TreeOutline.TreeElement {
79
80
  const config = ElementsComponents.AdornerManager.getRegisteredAdorner(
80
81
  ElementsComponents.AdornerManager.RegisteredAdorners.TOP_LAYER);
81
82
  const adornerContent = document.createElement('span');
82
- adornerContent.textContent = ` top-layer (${topLayerElementIndex}) `;
83
+ adornerContent.classList.add('adorner-with-icon');
84
+ const linkIcon = new IconButton.Icon.Icon();
85
+ linkIcon
86
+ .data = {iconName: 'ic_show_node_16x16', color: 'var(--color-text-disabled)', width: '12px', height: '12px'};
87
+ const adornerText = document.createElement('span');
88
+ adornerText.textContent = ` top-layer (${topLayerElementIndex}) `;
89
+ adornerContent.append(linkIcon);
90
+ adornerContent.append(adornerText);
83
91
  const adorner = element?.adorn(config, adornerContent);
84
92
  if (adorner) {
85
93
  const onClick = (((): void => {
@@ -31,6 +31,7 @@ export enum RegisteredAdorners {
31
31
  CONTAINER = 'container',
32
32
  SLOT = 'slot',
33
33
  TOP_LAYER = 'top-layer',
34
+ REVEAL = 'reveal',
34
35
  }
35
36
 
36
37
  // This enum-like const object serves as the authoritative registry for all the
@@ -79,6 +80,12 @@ export function getRegisteredAdorner(which: RegisteredAdorners): RegisteredAdorn
79
80
  category: AdornerCategories.LAYOUT,
80
81
  enabledByDefault: true,
81
82
  };
83
+ case RegisteredAdorners.REVEAL:
84
+ return {
85
+ name: 'reveal',
86
+ category: AdornerCategories.DEFAULT,
87
+ enabledByDefault: true,
88
+ };
82
89
  }
83
90
  }
84
91
 
@@ -22,6 +22,7 @@ import './StylePropertyHighlighter.js';
22
22
  import './StylesSidebarPane.js';
23
23
  import './StylePropertyTreeElement.js';
24
24
  import './ComputedStyleWidget.js';
25
+ import './CSSRuleValidator.js';
25
26
  import './ElementsPanel.js';
26
27
  import './ClassesPaneWidget.js';
27
28
  import './ElementStatePaneWidget.js';
@@ -32,6 +33,7 @@ import * as ClassesPaneWidget from './ClassesPaneWidget.js';
32
33
  import * as ColorSwatchPopoverIcon from './ColorSwatchPopoverIcon.js';
33
34
  import * as ComputedStyleModel from './ComputedStyleModel.js';
34
35
  import * as ComputedStyleWidget from './ComputedStyleWidget.js';
36
+ import * as CSSRuleValidator from './CSSRuleValidator.js';
35
37
  import * as DOMLinkifier from './DOMLinkifier.js';
36
38
  import * as DOMPath from './DOMPath.js';
37
39
  import * as ElementsPanel from './ElementsPanel.js';
@@ -62,6 +64,7 @@ export {
62
64
  ColorSwatchPopoverIcon,
63
65
  ComputedStyleModel,
64
66
  ComputedStyleWidget,
67
+ CSSRuleValidator,
65
68
  DOMLinkifier,
66
69
  DOMPath,
67
70
  ElementsPanel,
@@ -27,6 +27,10 @@
27
27
  display: none;
28
28
  }
29
29
 
30
+ .adorner-reveal {
31
+ margin: 3px;
32
+ }
33
+
30
34
  .adorner-with-icon {
31
35
  display: flex;
32
36
  justify-content: center;
@@ -155,6 +155,16 @@ ol.expanded {
155
155
  transform: scale(0.9);
156
156
  }
157
157
 
158
+ .hint {
159
+ position: absolute;
160
+ top: 0;
161
+ bottom: 0;
162
+ margin: auto;
163
+ display: inline-block;
164
+ cursor: pointer;
165
+ transform: scale(0.9);
166
+ }
167
+
158
168
  .has-ignorable-error {
159
169
  color: var(--color-text-disabled);
160
170
  }
@@ -415,6 +415,7 @@ export class DeviceModeToolbar {
415
415
  boundAppendScaleItem('100%', 1);
416
416
  boundAppendScaleItem('125%', 1.25);
417
417
  boundAppendScaleItem('150%', 1.5);
418
+ boundAppendScaleItem('200%', 2);
418
419
 
419
420
  function appendScaleItem(this: DeviceModeToolbar, title: string, value: number): void {
420
421
  contextMenu.defaultSection().appendCheckboxItem(
@@ -20,23 +20,23 @@ const UIStrings = {
20
20
  /**
21
21
  *@description Text in Request Headers View of the Network panel
22
22
  */
23
- fromMemoryCache: '(from memory cache)',
23
+ fromDiskCache: '(from disk cache)',
24
24
  /**
25
25
  *@description Text in Request Headers View of the Network panel
26
26
  */
27
- fromServiceWorker: '(from `service worker`)',
27
+ fromMemoryCache: '(from memory cache)',
28
28
  /**
29
29
  *@description Text in Request Headers View of the Network panel
30
30
  */
31
- fromSignedexchange: '(from signed-exchange)',
31
+ fromPrefetchCache: '(from prefetch cache)',
32
32
  /**
33
33
  *@description Text in Request Headers View of the Network panel
34
34
  */
35
- fromPrefetchCache: '(from prefetch cache)',
35
+ fromServiceWorker: '(from `service worker`)',
36
36
  /**
37
37
  *@description Text in Request Headers View of the Network panel
38
38
  */
39
- fromDiskCache: '(from disk cache)',
39
+ fromSignedexchange: '(from signed-exchange)',
40
40
  /**
41
41
  *@description Text in Request Headers View of the Network panel
42
42
  */
@@ -52,16 +52,24 @@ const UIStrings = {
52
52
  /**
53
53
  *@description Text in Request Headers View of the Network panel
54
54
  */
55
- requestHeaders: 'Request Headers',
55
+ referrerPolicy: 'Referrer Policy',
56
56
  /**
57
- *@description The URL of a request
57
+ *@description Text in Network Log View Columns of the Network panel
58
58
  */
59
- requestUrl: 'Request URL',
59
+ remoteAddress: 'Remote Address',
60
+ /**
61
+ *@description Text in Request Headers View of the Network panel
62
+ */
63
+ requestHeaders: 'Request Headers',
60
64
  /**
61
65
  *@description The HTTP method of a request
62
66
  */
63
67
  requestMethod: 'Request Method',
64
68
  /**
69
+ *@description The URL of a request
70
+ */
71
+ requestUrl: 'Request URL',
72
+ /**
65
73
  *@description A context menu item in the Network Log View Columns of the Network panel
66
74
  */
67
75
  responseHeaders: 'Response Headers',
@@ -73,14 +81,6 @@ const UIStrings = {
73
81
  *@description HTTP response code
74
82
  */
75
83
  statusCode: 'Status Code',
76
- /**
77
- *@description Text in Network Log View Columns of the Network panel
78
- */
79
- remoteAddress: 'Remote Address',
80
- /**
81
- *@description Text in Request Headers View of the Network panel
82
- */
83
- referrerPolicy: 'Referrer Policy',
84
84
  };
85
85
  const str_ = i18n.i18n.registerUIStrings('panels/network/components/RequestHeadersView.ts', UIStrings);
86
86
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -27,6 +27,7 @@ import {
27
27
  import {formatAddress, parseAddress} from './LinearMemoryInspectorUtils.js';
28
28
  import type {JumpToPointerAddressEvent, ValueTypeModeChangedEvent} from './ValueInterpreterDisplay.js';
29
29
  import {LinearMemoryViewer} from './LinearMemoryViewer.js';
30
+ import type {HighlightInfo} from './LinearMemoryViewerUtils.js';
30
31
 
31
32
  import * as i18n from '../../../core/i18n/i18n.js';
32
33
  const UIStrings = {
@@ -51,6 +52,7 @@ export interface LinearMemoryInspectorData {
51
52
  valueTypes?: Set<ValueType>;
52
53
  valueTypeModes?: Map<ValueType, ValueTypeMode>;
53
54
  endianness?: Endianness;
55
+ highlightInfo?: HighlightInfo;
54
56
  }
55
57
 
56
58
  export type Settings = {
@@ -120,6 +122,10 @@ export class LinearMemoryInspector extends HTMLElement {
120
122
  #outerMemoryLength = 0;
121
123
 
122
124
  #address = -1;
125
+ #highlightInfo: HighlightInfo = {
126
+ size: 0,
127
+ startAddress: 0,
128
+ };
123
129
 
124
130
  #currentNavigatorMode = Mode.Submitted;
125
131
  #currentNavigatorAddressLine = `${this.#address}`;
@@ -143,12 +149,23 @@ export class LinearMemoryInspector extends HTMLElement {
143
149
  throw new Error('Memory offset has to be greater or equal to zero.');
144
150
  }
145
151
 
152
+ if (data.highlightInfo !== undefined) {
153
+ if (data.highlightInfo.size < 0) {
154
+ throw new Error('Object size has to be greater than or equal to zero');
155
+ }
156
+ if (data.highlightInfo.startAddress > data.memoryOffset + data.memory.length ||
157
+ data.highlightInfo.startAddress < 0) {
158
+ throw new Error('Object start address is out of bounds.');
159
+ }
160
+ }
161
+
146
162
  this.#memory = data.memory;
147
163
  this.#memoryOffset = data.memoryOffset;
148
164
  this.#outerMemoryLength = data.outerMemoryLength;
149
165
  this.#valueTypeModes = data.valueTypeModes || this.#valueTypeModes;
150
166
  this.#valueTypes = data.valueTypes || this.#valueTypes;
151
167
  this.#endianness = data.endianness || this.#endianness;
168
+ this.#highlightInfo = data.highlightInfo || this.#highlightInfo;
152
169
  this.#setAddress(data.address);
153
170
  this.#render();
154
171
  }
@@ -179,7 +196,12 @@ export class LinearMemoryInspector extends HTMLElement {
179
196
  @pagenavigation=${this.#navigatePage}
180
197
  @historynavigation=${this.#navigateHistory}></${LinearMemoryNavigator.litTagName}>
181
198
  <${LinearMemoryViewer.litTagName}
182
- .data=${{memory: this.#memory.slice(start - this.#memoryOffset, end - this.#memoryOffset), address: this.#address, memoryOffset: start, focus: this.#currentNavigatorMode === Mode.Submitted} as LinearMemoryViewerData}
199
+ .data=${{
200
+ memory: this.#memory.slice(start - this.#memoryOffset,
201
+ end - this.#memoryOffset),
202
+ address: this.#address, memoryOffset: start,
203
+ focus: this.#currentNavigatorMode === Mode.Submitted,
204
+ highlightInfo: this.#highlightInfo } as LinearMemoryViewerData}
183
205
  @byteselected=${this.#onByteSelected}
184
206
  @resize=${this.#resize}>
185
207
  </${LinearMemoryViewer.litTagName}>