chrome-devtools-frontend 1.0.1700561 → 1.0.1702515

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 (119) hide show
  1. package/eslint.config.mjs +3 -1
  2. package/front_end/core/host/UserMetricsEnums.ts +2 -1
  3. package/front_end/core/root/ExperimentNames.ts +1 -0
  4. package/front_end/core/root/Runtime.ts +5 -0
  5. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +10 -10
  6. package/front_end/core/sdk/NetworkManager.ts +7 -0
  7. package/front_end/core/sdk/SecurityOrigin.ts +1 -0
  8. package/front_end/core/sdk/SourceMap.ts +12 -1
  9. package/front_end/core/sdk/SourceMapCache.ts +12 -0
  10. package/front_end/core/sdk/SourceMapManager.ts +17 -8
  11. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -19
  12. package/front_end/core/sdk/SourceMapScopesInfo.ts +21 -0
  13. package/front_end/devtools_compatibility.js +2 -1
  14. package/front_end/entrypoints/formatter_worker/ScopeParser.ts +7 -3
  15. package/front_end/entrypoints/formatter_worker/Substitute.ts +90 -26
  16. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -1
  17. package/front_end/entrypoints/main/ExecutionContextSelector.ts +17 -4
  18. package/front_end/entrypoints/main/MainImpl.ts +8 -0
  19. package/front_end/generated/InspectorBackendCommands.ts +4 -6
  20. package/front_end/generated/protocol-mapping.d.ts +0 -8
  21. package/front_end/generated/protocol-proxy-api.d.ts +0 -6
  22. package/front_end/generated/protocol.ts +4 -25
  23. package/front_end/models/ai_assistance/AiAgent2.ts +13 -1
  24. package/front_end/models/ai_assistance/AiConversation.ts +1 -1
  25. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +13 -19
  26. package/front_end/models/ai_assistance/debug.ts +10 -2
  27. package/front_end/models/change_tracker/ChangeTracker.ts +5 -64
  28. package/front_end/models/comment_manager/CD4ABridge.ts +2 -2
  29. package/front_end/models/comment_manager/CommentManager.ts +6 -5
  30. package/front_end/models/comment_manager/CommentThread.ts +30 -13
  31. package/front_end/models/formatter/FormatterWorkerPool.ts +2 -2
  32. package/front_end/models/issues_manager/CookieDeprecationMetadataIssue.ts +6 -7
  33. package/front_end/models/issues_manager/DeprecationIssue.ts +1 -1
  34. package/front_end/models/issues_manager/MarkdownIssueDescription.ts +14 -5
  35. package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -4
  36. package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantRead.md +0 -1
  37. package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantReadOptOut.md +5 -0
  38. package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSet.md +0 -1
  39. package/front_end/models/issues_manager/descriptions/cookieWarnMetadataGrantSetOptOut.md +5 -0
  40. package/front_end/models/issues_manager/descriptions/deprecation.md +1 -1
  41. package/front_end/models/issues_manager/descriptions/sriValidationFailedIntegrityMismatch.md +2 -0
  42. package/front_end/models/javascript_metadata/NativeFunctions.ts +7 -2
  43. package/front_end/models/persistence/NetworkPersistenceManager.ts +14 -2
  44. package/front_end/models/source_map_scopes/NamesResolver.ts +42 -39
  45. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +70 -1
  46. package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
  47. package/front_end/panels/common/CommentThreadWidget.ts +29 -10
  48. package/front_end/panels/common/CommentsOverlayWidget.ts +77 -14
  49. package/front_end/panels/common/ExtensionServer.ts +18 -8
  50. package/front_end/panels/common/commentThreadWidget.css +11 -0
  51. package/front_end/panels/console/ConsolePrompt.ts +1 -1
  52. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  53. package/front_end/panels/elements/ClassesPaneWidget.ts +2 -1
  54. package/front_end/panels/elements/DOMTreeContextMenu.ts +1 -1
  55. package/front_end/panels/elements/{ElementsTreeOutline.ts → DOMTreeWidget.ts} +34 -24
  56. package/front_end/panels/elements/ElementsPanel.ts +1 -1
  57. package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
  58. package/front_end/panels/elements/ShortcutTreeElement.ts +1 -1
  59. package/front_end/panels/elements/StylePropertiesSection.ts +10 -0
  60. package/front_end/panels/elements/StylesSidebarPane.ts +105 -55
  61. package/front_end/panels/elements/TopLayerContainer.ts +1 -1
  62. package/front_end/panels/elements/components/CSSQuery.ts +1 -1
  63. package/front_end/panels/elements/components/cssQuery.css +4 -0
  64. package/front_end/panels/elements/elements.ts +3 -3
  65. package/front_end/panels/elements/stylesSidebarPane.css +6 -0
  66. package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +1 -1
  67. package/front_end/panels/profiler/HeapProfileView.ts +8 -6
  68. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +8 -1
  69. package/front_end/panels/profiler/HeapSnapshotView.ts +6 -4
  70. package/front_end/panels/security/SecurityPanel.ts +87 -99
  71. package/front_end/panels/sensors/SensorsView.ts +87 -0
  72. package/front_end/panels/sensors/sensors-meta.ts +69 -1
  73. package/front_end/panels/settings/keybindsSettingsTab.css +1 -1
  74. package/front_end/panels/sources/ResourceOriginPlugin.ts +8 -3
  75. package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -4
  76. package/front_end/panels/sources/TabbedEditorContainer.ts +339 -126
  77. package/front_end/panels/sources/UISourceCodeFrame.ts +9 -0
  78. package/front_end/third_party/chromium/README.chromium +1 -1
  79. package/front_end/third_party/chromium/client-variations/ClientVariations.js +25 -96
  80. package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
  81. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  82. package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
  83. package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
  84. package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
  85. package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
  86. package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
  87. package/front_end/third_party/codemirror.next/chunk/legacy.js +1 -1
  88. package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
  89. package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
  90. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
  91. package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
  92. package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
  93. package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
  94. package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
  95. package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
  96. package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
  97. package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
  98. package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
  99. package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
  100. package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
  101. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
  102. package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
  103. package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
  104. package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
  105. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  106. package/front_end/third_party/codemirror.next/package.json +4 -1
  107. package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
  108. package/front_end/ui/comments/CommentOverlayManager.ts +11 -10
  109. package/front_end/ui/components/markdown_view/MarkdownPlaceholderLitRenderer.ts +117 -0
  110. package/front_end/ui/components/markdown_view/markdown_view.ts +2 -0
  111. package/front_end/ui/legacy/Treeoutline.ts +30 -20
  112. package/front_end/ui/legacy/UIUtils.ts +1 -1
  113. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +1 -1
  114. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +228 -343
  115. package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +2 -27
  116. package/front_end/ui/legacy/treeoutline.css +2 -2
  117. package/front_end/ui/visual_logging/KnownContextValues.ts +7 -0
  118. package/mcp/mcp.ts +1 -0
  119. package/package.json +1 -1
@@ -729,9 +729,6 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
729
729
  }
730
730
 
731
731
  setEditingStyle(editing: boolean): void {
732
- if (editing) {
733
- this.isSuppressingResets = false;
734
- }
735
732
  if (this.isEditingStyle === editing) {
736
733
  return;
737
734
  }
@@ -816,12 +813,13 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
816
813
  #scheduleResetUpdateIfNotEditing(): void {
817
814
  this.scheduleResetUpdateIfNotEditingCalledForTest();
818
815
 
819
- if (this.isSuppressingResets) {
816
+ // Don't schedule if editing; the edit completion will handle the update.
817
+ if (this.userOperation || this.isEditingStyle) {
820
818
  return;
821
819
  }
822
820
 
823
- // Don't schedule if editing; the edit completion will handle the update.
824
- if (this.userOperation || this.isEditingStyle) {
821
+ if (this.isSuppressingResets) {
822
+ this.isSuppressingResets = false;
825
823
  return;
826
824
  }
827
825
 
@@ -1128,27 +1126,39 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1128
1126
  }
1129
1127
  }
1130
1128
 
1131
- private getStyleId(style: SDK.CSSStyleDeclaration.CSSStyleDeclaration): string {
1129
+ private getStyleId(section: StylePropertiesSection): string {
1130
+ const style = section.styleInternal;
1131
+ const node = section.matchedStyles.isInherited(style) ? section.matchedStyles.nodeForStyle(style) :
1132
+ section.matchedStyles.node();
1133
+ const nodeId = node?.id ?? '';
1132
1134
  if (style.range) {
1133
- return `${style.styleSheetId || ''}:${style.range.toString()}`;
1135
+ return `${nodeId}:${style.styleSheetId || ''}:${style.range.toString()}`;
1134
1136
  }
1135
1137
  if (style.type === SDK.CSSStyleDeclaration.Type.Inline || style.type === SDK.CSSStyleDeclaration.Type.Attributes) {
1136
- return style.type;
1138
+ return `${nodeId}:${style.type}`;
1137
1139
  }
1138
1140
  if (style.type === SDK.CSSStyleDeclaration.Type.Animation) {
1139
- return `${style.type}:${style.animationName() || ''}:${style.cssText}`;
1141
+ return `${nodeId}:${style.type}:${style.animationName() || ''}:${style.cssText}`;
1140
1142
  }
1141
1143
  const parentRule = style.parentRule;
1142
1144
  if (parentRule instanceof SDK.CSSRule.CSSStyleRule) {
1143
- return `${style.type}:${parentRule.selectorText()}`;
1145
+ const ruleTypes = parentRule.ruleTypes.join(',');
1146
+ const nesting = parentRule.nestingSelectors?.join(',') ?? '';
1147
+ const media = parentRule.media.map(m => m.text).join(',');
1148
+ const containers = parentRule.containerQueries.map(c => c.text).join(',');
1149
+ const supports = parentRule.supports.map(s => s.text).join(',');
1150
+ const scopes = parentRule.scopes.map(s => s.text).join(',');
1151
+ const layers = parentRule.layers.map(l => l.text).join(',');
1152
+ return `${nodeId}:${style.type}:${parentRule.selectorText()}:${ruleTypes}:${nesting}:${media}:${containers}:${
1153
+ supports}:${scopes}:${layers}`;
1144
1154
  }
1145
1155
  if (parentRule instanceof SDK.CSSRule.CSSKeyframeRule) {
1146
- return `${style.type}:${parentRule.parentRuleName()}:${parentRule.key().text}`;
1156
+ return `${nodeId}:${style.type}:${parentRule.parentRuleName()}:${parentRule.key().text}`;
1147
1157
  }
1148
1158
  if (parentRule instanceof SDK.CSSRule.CSSPropertyRule) {
1149
- return `${style.type}:${parentRule.propertyName().text}`;
1159
+ return `${nodeId}:${style.type}:${parentRule.propertyName().text}`;
1150
1160
  }
1151
- return `${style.type}:${style.cssText}`;
1161
+ return `${nodeId}:${style.type}:${style.cssText}`;
1152
1162
  }
1153
1163
 
1154
1164
  rebuildSectionsForMatchedStyleRulesForTest(matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
@@ -1172,7 +1182,7 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1172
1182
 
1173
1183
  this.idleCallbackManager = new IdleCallbackManager();
1174
1184
 
1175
- const blocks = [new SectionBlock(null)];
1185
+ const blocks = [new SectionBlock(null, undefined, undefined, 'main')];
1176
1186
  let sectionIdx = 0;
1177
1187
  let lastParentNode: SDK.DOMModel.DOMNode|null = null;
1178
1188
 
@@ -1185,7 +1195,7 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1185
1195
  if (parentRule instanceof SDK.CSSRule.CSSStyleRule) {
1186
1196
  const layers = parentRule.layers;
1187
1197
  if ((layers.length || lastLayers) && lastLayers !== layers) {
1188
- const block = SectionBlock.createLayerBlock(parentRule);
1198
+ const block = SectionBlock.createLayerBlock(parentRule, lastLayerParent?.id);
1189
1199
  blocks.push(block);
1190
1200
  lastLayerParent?.childBlocks.push(block);
1191
1201
  sawLayers = true;
@@ -1411,37 +1421,36 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1411
1421
  return blocks;
1412
1422
  }
1413
1423
 
1414
- return this.mergeInactiveStyles(blocks);
1415
- }
1416
-
1417
- private computeBlockIds(blocks: SectionBlock[]): Map<SectionBlock, string> {
1418
- let nullBlockCounter = 0;
1419
- const blockIds = new Map<SectionBlock, string>();
1420
- for (const block of blocks) {
1421
- blockIds.set(block, block.titleElement()?.textContent || `MAIN_BLOCK_NULL_${nullBlockCounter++}`);
1422
- }
1423
- return blockIds;
1424
+ return this.mergeInactiveStyles(blocks, matchedStyles, computedStyles, parentsComputedStyles,
1425
+ computedStyleExtraFields);
1424
1426
  }
1425
1427
 
1426
- private mergeInactiveStyles(blocks: SectionBlock[]): SectionBlock[] {
1427
- const blockIds = this.computeBlockIds(blocks);
1428
- for (const [id, block] of this.#allKnownBlocks) {
1429
- if (!blockIds.has(block)) {
1430
- blockIds.set(block, id);
1431
- }
1432
- }
1433
- const getBlockId = (block: SectionBlock): string => blockIds.get(block) || 'UNKNOWN_BLOCK';
1428
+ private mergeInactiveStyles(
1429
+ blocks: SectionBlock[],
1430
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
1431
+ computedStyles: Map<string, string>|null,
1432
+ parentsComputedStyles: Map<string, string>|null,
1433
+ computedStyleExtraFields: Protocol.CSS.ComputedStyleExtraFields|null,
1434
+ ): SectionBlock[] {
1435
+ const getBlockId = (block: SectionBlock): string => block.id;
1434
1436
 
1435
1437
  for (const block of blocks) {
1436
1438
  const bid = getBlockId(block);
1437
1439
  const knownBlock = this.#allKnownBlocks.get(bid);
1438
1440
  if (knownBlock) {
1439
- block.sections = mergeOrderedItems(
1441
+ knownBlock.sections = mergeOrderedItems(
1440
1442
  knownBlock.sections,
1441
1443
  block.sections,
1442
- section => this.getStyleId(section.styleInternal),
1443
- section => section.setInactive(true),
1444
+ section => this.getStyleId(section),
1445
+ (section, active, newSection) => {
1446
+ if (active && newSection) {
1447
+ section.rebuildWithPayload(matchedStyles, newSection.style(), computedStyles, parentsComputedStyles,
1448
+ computedStyleExtraFields);
1449
+ }
1450
+ section.setInactive(!active);
1451
+ },
1444
1452
  );
1453
+ block.sections = knownBlock.sections;
1445
1454
  }
1446
1455
  }
1447
1456
 
@@ -1450,7 +1459,11 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1450
1459
  oldBlocks,
1451
1460
  blocks,
1452
1461
  getBlockId,
1453
- block => block.sections.forEach(section => section.setInactive(true)),
1462
+ (block, active) => {
1463
+ if (!active) {
1464
+ block.sections.forEach(section => section.setInactive(true));
1465
+ }
1466
+ },
1454
1467
  );
1455
1468
 
1456
1469
  this.#allKnownBlocks.clear();
@@ -1458,6 +1471,19 @@ export class StylesSidebarPane extends StylesSidebarPaneBase implements StylesCo
1458
1471
  this.#allKnownBlocks.set(getBlockId(block), block);
1459
1472
  }
1460
1473
 
1474
+ // Restore child relationships using the new tree structure,
1475
+ // but pointing to the final instances.
1476
+ for (const newBlock of blocks) {
1477
+ const finalBlock = this.#allKnownBlocks.get(getBlockId(newBlock));
1478
+ if (finalBlock) {
1479
+ const newChildBlocks =
1480
+ newBlock.childBlocks.map(child => this.#allKnownBlocks.get(getBlockId(child))).filter(b => b !== undefined);
1481
+ finalBlock.childBlocks = finalBlock === newBlock ?
1482
+ newChildBlocks :
1483
+ mergeOrderedItems(finalBlock.childBlocks, newChildBlocks, getBlockId, () => {});
1484
+ }
1485
+ }
1486
+
1461
1487
  return finalBlocks;
1462
1488
  }
1463
1489
 
@@ -1873,7 +1899,7 @@ export class SectionBlock {
1873
1899
  childBlocks: SectionBlock[] = [];
1874
1900
  #expanded = false;
1875
1901
  #icon: Icon|undefined;
1876
- constructor(titleElement: Element|null, expandable?: boolean, expandedByDefault?: boolean) {
1902
+ constructor(titleElement: Element|null, expandable?: boolean, expandedByDefault?: boolean, readonly id = 'main') {
1877
1903
  this.#titleElement = titleElement;
1878
1904
  this.sections = [];
1879
1905
  this.#expanded = expandedByDefault ?? false;
@@ -1907,7 +1933,7 @@ export class SectionBlock {
1907
1933
  const pseudoArgumentString = pseudoArgument ? `(${pseudoArgument})` : '';
1908
1934
  const pseudoTypeString = `${pseudoType}${pseudoArgumentString}`;
1909
1935
  separatorElement.textContent = i18nString(UIStrings.pseudoSElement, {PH1: pseudoTypeString});
1910
- return new SectionBlock(separatorElement);
1936
+ return new SectionBlock(separatorElement, false, false, `pseudo:${pseudoType}:${pseudoArgument ?? ''}`);
1911
1937
  }
1912
1938
 
1913
1939
  static async createInheritedPseudoTypeBlock(pseudoType: Protocol.DOM.PseudoType, pseudoArgument: string|null,
@@ -1920,12 +1946,13 @@ export class SectionBlock {
1920
1946
  UI.UIUtils.createTextChild(separatorElement, i18nString(UIStrings.inheritedFromSPseudoOf, {PH1: pseudoTypeString}));
1921
1947
  const link = PanelsCommon.DOMLinkifier.Linkifier.instance().linkify(node, {preventKeyboardFocus: true});
1922
1948
  render(link, separatorElement);
1923
- return new SectionBlock(separatorElement);
1949
+ return new SectionBlock(separatorElement, false, false,
1950
+ `inherited-pseudo:${pseudoType}:${pseudoArgument ?? ''}:${node.id}`);
1924
1951
  }
1925
1952
 
1926
1953
  static createRegisteredPropertiesBlock(expandedByDefault: boolean): SectionBlock {
1927
1954
  const separatorElement = document.createElement('div');
1928
- const block = new SectionBlock(separatorElement, true, expandedByDefault);
1955
+ const block = new SectionBlock(separatorElement, true, expandedByDefault, 'registered-properties');
1929
1956
  separatorElement.className = 'sidebar-separator';
1930
1957
  separatorElement.appendChild(document.createTextNode(REGISTERED_PROPERTY_SECTION_NAME));
1931
1958
  return block;
@@ -1933,7 +1960,7 @@ export class SectionBlock {
1933
1960
 
1934
1961
  static createFunctionBlock(expandedByDefault: boolean): SectionBlock {
1935
1962
  const separatorElement = document.createElement('div');
1936
- const block = new SectionBlock(separatorElement, true, expandedByDefault);
1963
+ const block = new SectionBlock(separatorElement, true, expandedByDefault, 'functions');
1937
1964
  separatorElement.className = 'sidebar-separator';
1938
1965
  separatorElement.appendChild(document.createTextNode(FUNCTION_SECTION_NAME));
1939
1966
  return block;
@@ -1944,12 +1971,12 @@ export class SectionBlock {
1944
1971
  separatorElement.className = 'sidebar-separator';
1945
1972
  separatorElement.setAttribute('jslog', `${VisualLogging.sectionHeader('keyframes')}`);
1946
1973
  separatorElement.textContent = `@keyframes ${keyframesName}`;
1947
- return new SectionBlock(separatorElement);
1974
+ return new SectionBlock(separatorElement, false, false, `keyframes:${keyframesName}`);
1948
1975
  }
1949
1976
 
1950
1977
  static createAtRuleBlock(expandedByDefault: boolean): SectionBlock {
1951
1978
  const separatorElement = document.createElement('div');
1952
- const block = new SectionBlock(separatorElement, true, expandedByDefault);
1979
+ const block = new SectionBlock(separatorElement, true, expandedByDefault, 'at-rules');
1953
1980
  separatorElement.className = 'sidebar-separator';
1954
1981
  separatorElement.appendChild(document.createTextNode(i18nString(UIStrings.atRuleSection)));
1955
1982
  return block;
@@ -1960,7 +1987,7 @@ export class SectionBlock {
1960
1987
  separatorElement.className = 'sidebar-separator';
1961
1988
  separatorElement.setAttribute('jslog', `${VisualLogging.sectionHeader('position-try')}`);
1962
1989
  separatorElement.textContent = `@position-try ${positionTryName}`;
1963
- return new SectionBlock(separatorElement);
1990
+ return new SectionBlock(separatorElement, false, false, `position-try:${positionTryName}`);
1964
1991
  }
1965
1992
 
1966
1993
  static async createInheritedNodeBlock(node: SDK.DOMModel.DOMNode): Promise<SectionBlock> {
@@ -1972,10 +1999,10 @@ export class SectionBlock {
1972
1999
  preventKeyboardFocus: true,
1973
2000
  });
1974
2001
  render(link, separatorElement);
1975
- return new SectionBlock(separatorElement);
2002
+ return new SectionBlock(separatorElement, false, false, `inherited-node:${node.id}`);
1976
2003
  }
1977
2004
 
1978
- static createLayerBlock(rule: SDK.CSSRule.CSSStyleRule): SectionBlock {
2005
+ static createLayerBlock(rule: SDK.CSSRule.CSSStyleRule, parentBlockId = 'main'): SectionBlock {
1979
2006
  const separatorElement = document.createElement('div');
1980
2007
  separatorElement.className = 'sidebar-separator layer-separator';
1981
2008
  separatorElement.setAttribute('jslog', `${VisualLogging.sectionHeader('layer')}`);
@@ -1985,7 +2012,7 @@ export class SectionBlock {
1985
2012
  const name = rule.origin === Protocol.CSS.StyleSheetOrigin.UserAgent ? '\xa0user\xa0agent\xa0stylesheet' :
1986
2013
  '\xa0implicit\xa0outer\xa0layer';
1987
2014
  UI.UIUtils.createTextChild(separatorElement.createChild('div'), name);
1988
- return new SectionBlock(separatorElement);
2015
+ return new SectionBlock(separatorElement, false, false, `layer:${parentBlockId}:${name}`);
1989
2016
  }
1990
2017
  const layerLink = separatorElement.createChild('button');
1991
2018
  layerLink.className = 'link';
@@ -1993,7 +2020,7 @@ export class SectionBlock {
1993
2020
  const name = layers.map(layer => SDK.CSSModel.CSSModel.readableLayerName(layer.text)).join('.');
1994
2021
  layerLink.textContent = name;
1995
2022
  layerLink.onclick = () => LayersWidget.LayersWidget.instance().revealLayer(name);
1996
- return new SectionBlock(separatorElement);
2023
+ return new SectionBlock(separatorElement, false, false, `layer:${parentBlockId}:${name}`);
1997
2024
  }
1998
2025
 
1999
2026
  updateFilter(): number {
@@ -2703,30 +2730,53 @@ export function mergeOrderedItems<T>(
2703
2730
  oldItems: T[],
2704
2731
  newItems: T[],
2705
2732
  getId: (item: T) => string,
2706
- markInactive: (item: T) => void,
2733
+ toggleActive: (item: T, active: boolean, newItem?: T) => void,
2707
2734
  ): T[] {
2708
2735
  const newIds = new Set(newItems.map(getId));
2736
+ const oldItemById = new Map(oldItems.map(item => [getId(item), item]));
2737
+ const handledIds = new Set<string>();
2709
2738
  const merged: T[] = [];
2710
2739
  let newIdx = 0;
2711
2740
 
2712
2741
  for (const oldItem of oldItems) {
2713
2742
  const oldId = getId(oldItem);
2743
+ if (handledIds.has(oldId)) {
2744
+ continue;
2745
+ }
2714
2746
  if (newIds.has(oldId)) {
2715
2747
  while (newIdx < newItems.length) {
2716
2748
  const newItem = newItems[newIdx++];
2717
- merged.push(newItem);
2718
- if (getId(newItem) === oldId) {
2749
+ const newId = getId(newItem);
2750
+ const existingItem = oldItemById.get(newId);
2751
+ if (existingItem) {
2752
+ toggleActive(existingItem, true, newItem);
2753
+ merged.push(existingItem);
2754
+ handledIds.add(newId);
2755
+ } else {
2756
+ merged.push(newItem);
2757
+ }
2758
+ if (newId === oldId) {
2719
2759
  break;
2720
2760
  }
2721
2761
  }
2722
2762
  } else {
2723
- markInactive(oldItem);
2763
+ toggleActive(oldItem, false);
2724
2764
  merged.push(oldItem);
2765
+ handledIds.add(oldId);
2725
2766
  }
2726
2767
  }
2727
2768
 
2728
2769
  while (newIdx < newItems.length) {
2729
- merged.push(newItems[newIdx++]);
2770
+ const newItem = newItems[newIdx++];
2771
+ const newId = getId(newItem);
2772
+ const existingItem = oldItemById.get(newId);
2773
+ if (existingItem && !handledIds.has(newId)) {
2774
+ toggleActive(existingItem, true, newItem);
2775
+ merged.push(existingItem);
2776
+ handledIds.add(newId);
2777
+ } else if (!handledIds.has(newId)) {
2778
+ merged.push(newItem);
2779
+ }
2730
2780
  }
2731
2781
 
2732
2782
  return merged;
@@ -6,7 +6,7 @@ import type * as Common from '../../core/common/common.js';
6
6
  import * as SDK from '../../core/sdk/sdk.js';
7
7
  import * as UI from '../../ui/legacy/legacy.js';
8
8
 
9
- import type {ElementsTreeOutline} from './ElementsTreeOutline.js';
9
+ import type {ElementsTreeOutline} from './DOMTreeWidget.js';
10
10
  import {ShortcutTreeElement} from './ShortcutTreeElement.js';
11
11
 
12
12
  export class TopLayerContainer extends UI.TreeOutline.TreeElement {
@@ -171,7 +171,7 @@ export class CSSQuery extends HTMLElement {
171
171
  <slot name="indent"></slot>
172
172
  ${this.#queryPrefix ? html`<span>${this.#queryPrefix + ' '}</span>` : Lit.nothing}
173
173
  ${this.#queryName ? html`<span>${this.#queryName + ' '}</span>` : Lit.nothing}
174
- ${queryText} {
174
+ ${queryText}<slot></slot> <span class="sidebar-pane-open-brace">{</span>
175
175
  </div>`,
176
176
  this.#shadow, {host: this});
177
177
  // clang-format on
@@ -16,3 +16,7 @@
16
16
  text-decoration: var(--override-styles-section-text-hover-text-decoration);
17
17
  cursor: var(--override-styles-section-text-hover-cursor);
18
18
  }
19
+
20
+ :host-context(.collapsed):host(:has(devtools-icon)) .sidebar-pane-open-brace::after {
21
+ content: "}";
22
+ }
@@ -10,7 +10,7 @@ import './ElementsSidebarPane.js';
10
10
  import './ElementsTreeElement.js';
11
11
  import './AdoptedStyleSheetTreeElement.js';
12
12
  import './TopLayerContainer.js';
13
- import './ElementsTreeOutline.js';
13
+ import './DOMTreeWidget.js';
14
14
  import './ImagePreviewPopover.js';
15
15
  import './EventListenersWidget.js';
16
16
  import './MarkerDecorator.js';
@@ -42,11 +42,11 @@ import * as CSSSpecificityBreakdown from './CSSSpecificityBreakdown.js';
42
42
  import * as CSSValueTraceView from './CSSValueTraceView.js';
43
43
  import * as DOMPath from './DOMPath.js';
44
44
  import * as DOMTreeContextMenu from './DOMTreeContextMenu.js';
45
+ import * as DOMTreeWidget from './DOMTreeWidget.js';
45
46
  import * as ElementsPanel from './ElementsPanel.js';
46
47
  import * as ElementsSidebarPane from './ElementsSidebarPane.js';
47
48
  import * as ElementStatePaneWidget from './ElementStatePaneWidget.js';
48
49
  import * as ElementsTreeElement from './ElementsTreeElement.js';
49
- import * as ElementsTreeOutline from './ElementsTreeOutline.js';
50
50
  import * as EventListenersWidget from './EventListenersWidget.js';
51
51
  import * as ImagePreviewPopover from './ImagePreviewPopover.js';
52
52
  import * as InspectElementModeController from './InspectElementModeController.js';
@@ -80,11 +80,11 @@ export {
80
80
  CSSValueTraceView,
81
81
  DOMPath,
82
82
  DOMTreeContextMenu,
83
+ DOMTreeWidget,
83
84
  ElementsPanel,
84
85
  ElementsSidebarPane,
85
86
  ElementStatePaneWidget,
86
87
  ElementsTreeElement,
87
- ElementsTreeOutline,
88
88
  EventListenersWidget,
89
89
  ImagePreviewPopover,
90
90
  InspectElementModeController,
@@ -115,6 +115,7 @@
115
115
  & .section-collapse-icon {
116
116
  width: var(--sys-size-6);
117
117
  height: var(--sys-size-6);
118
+ margin-block: calc(-1 * var(--sys-size-3));
118
119
  margin-right: var(--sys-size-2);
119
120
  margin-left: calc(-1 * var(--sys-size-2));
120
121
  vertical-align: middle;
@@ -122,6 +123,11 @@
122
123
  display: none;
123
124
  }
124
125
 
126
+ & .styles-section-status {
127
+ margin-block: calc(-1 * var(--sys-size-4));
128
+ vertical-align: middle;
129
+ }
130
+
125
131
  &.collapsible .section-collapse-icon {
126
132
  display: inline-block;
127
133
  }
@@ -64,7 +64,7 @@ const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLElement|
64
64
  <tr jslog=${VisualLogging.tableRow('detached-element')}>
65
65
  <td>
66
66
  <devtools-widget
67
- ${widget(Elements.ElementsTreeOutline.DOMTreeWidget, {
67
+ ${widget(Elements.DOMTreeWidget.DOMTreeWidget, {
68
68
  omitRootDOMNode: false,
69
69
  selectEnabled: true,
70
70
  hideGutter: true,
@@ -1067,12 +1067,14 @@ export class SamplingHeapProfileType extends SamplingHeapProfileTypeBase {
1067
1067
  }
1068
1068
 
1069
1069
  override customContent(): Element|null {
1070
- const checkboxSetting = SettingsUI.SettingsUI.createSettingCheckbox(
1071
- i18nString(UIStrings.samplingHeapProfilerTimeline), this.#recordTimelineSetting);
1072
- this.customContentInternal = checkboxSetting;
1073
- checkboxSetting.setAttribute(
1074
- 'jslog', `${VisualLogging.toggle('record-sampling-heap-profiler-timeline').track({click: true})}`);
1075
- return checkboxSetting;
1070
+ if (!this.customContentInternal) {
1071
+ const checkboxSetting = SettingsUI.SettingsUI.createSettingCheckbox(
1072
+ i18nString(UIStrings.samplingHeapProfilerTimeline), this.#recordTimelineSetting);
1073
+ this.customContentInternal = checkboxSetting;
1074
+ checkboxSetting.setAttribute(
1075
+ 'jslog', `${VisualLogging.toggle('record-sampling-heap-profiler-timeline').track({click: true})}`);
1076
+ }
1077
+ return this.customContentInternal;
1076
1078
  }
1077
1079
 
1078
1080
  override setCustomContentEnabled(enable: boolean): void {
@@ -532,19 +532,26 @@ export class HeapSnapshotViewportDataGrid extends HeapSnapshotSortableDataGrid {
532
532
  const scrollTop = this.scrollContainer.scrollTop;
533
533
  const scrollBottom = scrollTop + this.scrollContainer.offsetHeight;
534
534
  if (height >= scrollTop && height < scrollBottom) {
535
+ if (!node.dataGrid) {
536
+ this.updateVisibleNodes(false);
537
+ }
535
538
  return Promise.resolve(node);
536
539
  }
537
540
 
538
541
  const scrollGap = 40;
539
542
  this.scrollContainer.scrollTop = Math.max(0, height - scrollGap);
543
+ this.updateVisibleNodes(false);
540
544
  return new Promise(resolve => {
541
- console.assert(!this.scrollToResolveCallback);
545
+ if (this.scrollToResolveCallback) {
546
+ this.scrollToResolveCallback();
547
+ }
542
548
  this.scrollToResolveCallback = resolve.bind(null, node);
543
549
  // Still resolve the promise if it does not scroll for some reason.
544
550
  this.scrollContainer.window().requestAnimationFrame(() => {
545
551
  if (!this.scrollToResolveCallback) {
546
552
  return;
547
553
  }
554
+ this.updateVisibleNodes(false);
548
555
  this.scrollToResolveCallback();
549
556
  this.scrollToResolveCallback = null;
550
557
  });
@@ -1640,10 +1640,12 @@ export class TrackingHeapSnapshotProfileType extends TrackingHeapSnapshotProfile
1640
1640
  }
1641
1641
 
1642
1642
  override customContent(): Element|null {
1643
- const checkboxSetting = SettingsUI.SettingsUI.createSettingCheckbox(
1644
- i18nString(UIStrings.recordAllocationStacksExtra), this.recordAllocationStacksSettingInternal);
1645
- this.customContentInternal = (checkboxSetting);
1646
- return checkboxSetting;
1643
+ if (!this.customContentInternal) {
1644
+ const checkboxSetting = SettingsUI.SettingsUI.createSettingCheckbox(
1645
+ i18nString(UIStrings.recordAllocationStacksExtra), this.recordAllocationStacksSettingInternal);
1646
+ this.customContentInternal = checkboxSetting;
1647
+ }
1648
+ return this.customContentInternal;
1647
1649
  }
1648
1650
 
1649
1651
  override setCustomContentEnabled(enable: boolean): void {