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
@@ -31,6 +31,7 @@ export interface ViewInput {
31
31
  activePin: Comments.CommentOverlayManager.PinPositionData|null;
32
32
  title: Title;
33
33
  onAddComment: (text: string) => void;
34
+ onCloseCommentThread: () => void;
34
35
  }
35
36
 
36
37
  export type View = (
@@ -43,6 +44,7 @@ const POPUP_MARGIN = 8;
43
44
  const PIN_HEIGHT = 30;
44
45
  const POPUP_WIDTH = 288;
45
46
  const POPUP_HEIGHT = 220;
47
+ const AUTO_CLOSE_DELAY_MS = 2000;
46
48
 
47
49
  const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
48
50
  // clang-format off
@@ -102,6 +104,7 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
102
104
  title: input.title,
103
105
  comments: [...item.thread.comments],
104
106
  onAddComment: input.onAddComment,
107
+ onClose: input.onCloseCommentThread,
105
108
  })}
106
109
  </div>
107
110
  `,
@@ -119,9 +122,22 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
119
122
  readonly #commentManager: CommentManager.CommentManager.CommentManager;
120
123
  #commentOverlayManager: Comments.CommentOverlayManager.CommentOverlayManager;
121
124
  #activeThreadId: string|null = null;
125
+ #closeTimeoutId: number|null = null;
122
126
  #cachedTitle: Title = {text: ''};
123
127
  #cachedTitleAnchor: CommentManager.CommentManager.CommentAnchorSignature|null = null;
124
128
 
129
+ #setActiveThreadId(threadId: string|null): void {
130
+ if (this.#activeThreadId !== threadId) {
131
+ this.#clearCloseTimeout();
132
+ this.#activeThreadId = threadId;
133
+ if (threadId && this.isShowing()) {
134
+ document.documentElement.addEventListener('keydown', this.#onKeyDown);
135
+ } else {
136
+ document.documentElement.removeEventListener('keydown', this.#onKeyDown);
137
+ }
138
+ }
139
+ }
140
+
125
141
  constructor(
126
142
  element: HTMLElement|undefined,
127
143
  [commentManager]: UI.Widget.WidgetDependencies<typeof CommentsOverlayWidget>,
@@ -168,11 +184,16 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
168
184
  this.#onAgentAttachedChanged,
169
185
  this,
170
186
  );
187
+ if (this.#activeThreadId) {
188
+ document.documentElement.addEventListener('keydown', this.#onKeyDown);
189
+ }
171
190
 
172
191
  this.requestUpdate();
173
192
  }
174
193
 
175
194
  override willHide(): void {
195
+ this.#clearCloseTimeout();
196
+ document.documentElement.removeEventListener('keydown', this.#onKeyDown);
176
197
  this.#commentOverlayManager.stop();
177
198
  this.#commentOverlayManager.removeEventListener(
178
199
  Comments.CommentOverlayManager.Events.POSITIONS_UPDATED,
@@ -204,12 +225,19 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
204
225
  super.willHide();
205
226
  }
206
227
 
228
+ #clearCloseTimeout(): void {
229
+ if (this.#closeTimeoutId !== null) {
230
+ window.clearTimeout(this.#closeTimeoutId);
231
+ this.#closeTimeoutId = null;
232
+ }
233
+ }
234
+
207
235
  #onAgentAttachedChanged(
208
236
  event: Common.EventTarget.EventTargetEvent<
209
237
  CommentManager.CommentManager.EventTypes[CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED]>,
210
238
  ): void {
211
239
  if (!event.data) {
212
- this.#activeThreadId = null;
240
+ this.#setActiveThreadId(null);
213
241
  }
214
242
  this.requestUpdate();
215
243
  }
@@ -220,7 +248,7 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
220
248
  ): void {
221
249
  const isModeActive = event.data;
222
250
  if (!isModeActive) {
223
- this.#activeThreadId = null;
251
+ this.#setActiveThreadId(null);
224
252
  }
225
253
  const action = UI.ActionRegistry.ActionRegistry.instance().getAction(
226
254
  'comments.toggle-comment-mode',
@@ -232,9 +260,9 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
232
260
  #onStateChanged(): void {
233
261
  const draftThread = this.#commentManager.getCommentThreads().find(t => t.status === 'DRAFT');
234
262
  if (draftThread) {
235
- this.#activeThreadId = draftThread.id;
263
+ this.#setActiveThreadId(draftThread.id);
236
264
  } else if (this.#activeThreadId && !this.#commentManager.getCommentThread(this.#activeThreadId)) {
237
- this.#activeThreadId = null;
265
+ this.#setActiveThreadId(null);
238
266
  }
239
267
  this.requestUpdate();
240
268
  }
@@ -262,7 +290,6 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
262
290
  return {node};
263
291
  }
264
292
  }
265
- return {text: ''};
266
293
  }
267
294
 
268
295
  if (anchor.networkRequestId) {
@@ -277,19 +304,35 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
277
304
  }
278
305
 
279
306
  #handlePinClick = (threadId: string): void => {
280
- const thread = this.#commentManager.getCommentThread(threadId);
281
307
  if (this.#activeThreadId === threadId) {
282
- if (thread?.status === 'DRAFT') {
283
- this.#commentOverlayManager.clearDraftThreads();
284
- }
285
- this.#activeThreadId = null;
286
- } else {
308
+ this.#handleCloseCommentThread();
309
+ return;
310
+ }
311
+
312
+ this.#commentOverlayManager.clearDraftThreads();
313
+ this.#setActiveThreadId(threadId);
314
+ this.requestUpdate();
315
+ };
316
+
317
+ #handleCloseCommentThread = (): void => {
318
+ if (!this.#activeThreadId) {
319
+ return;
320
+ }
321
+ const thread = this.#commentManager.getCommentThread(this.#activeThreadId);
322
+ if (thread?.status === 'DRAFT') {
287
323
  this.#commentOverlayManager.clearDraftThreads();
288
- this.#activeThreadId = threadId;
289
324
  }
325
+ this.#setActiveThreadId(null);
290
326
  this.requestUpdate();
291
327
  };
292
328
 
329
+ #onKeyDown = (event: KeyboardEvent): void => {
330
+ if (this.#activeThreadId && event.key === 'Escape' && !event.isComposing) {
331
+ event.consume(true);
332
+ this.#handleCloseCommentThread();
333
+ }
334
+ };
335
+
293
336
  override async performUpdate(signal?: AbortSignal): Promise<void> {
294
337
  if (!this.#commentManager.isAgentAttached()) {
295
338
  this.#view(
@@ -303,6 +346,7 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
303
346
  activePin: null,
304
347
  title: {text: ''},
305
348
  onAddComment: () => {},
349
+ onCloseCommentThread: this.#handleCloseCommentThread,
306
350
  },
307
351
  undefined,
308
352
  this.contentElement,
@@ -329,8 +373,21 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
329
373
  activePin,
330
374
  title,
331
375
  onAddComment: (text: string) => {
332
- activeThread?.save(text);
376
+ if (!activeThread) {
377
+ return;
378
+ }
379
+ activeThread.sendToAgent(text);
380
+ const threadId = activeThread.id;
381
+ this.#clearCloseTimeout();
382
+ this.#closeTimeoutId = window.setTimeout(() => {
383
+ this.#closeTimeoutId = null;
384
+ if (this.#activeThreadId === threadId) {
385
+ this.#setActiveThreadId(null);
386
+ this.requestUpdate();
387
+ }
388
+ }, AUTO_CLOSE_DELAY_MS);
333
389
  },
390
+ onCloseCommentThread: this.#handleCloseCommentThread,
334
391
  };
335
392
  this.#view(viewInput, undefined, this.contentElement);
336
393
  }
@@ -350,6 +407,9 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
350
407
 
351
408
  handleAction(_context: UI.Context.Context, actionId: string): boolean {
352
409
  if (actionId === 'comments.toggle-comment-mode') {
410
+ if (!this.#commentManager.isAgentAttached()) {
411
+ return false;
412
+ }
353
413
  if (!widgetInstance) {
354
414
  widgetInstance = new CommentsOverlayWidget(
355
415
  undefined,
@@ -383,11 +443,14 @@ export class ButtonProvider implements UI.Toolbar.Provider {
383
443
  Root.DevToolsContext.globalInstance().get(
384
444
  CommentManager.CommentManager.CommentManager,
385
445
  );
386
- this.#button = UI.Toolbar.Toolbar.createActionButton('comments.toggle-comment-mode');
446
+ const action = UI.ActionRegistry.ActionRegistry.instance().getAction('comments.toggle-comment-mode');
447
+ action.setEnabled(this.#commentManager.isAgentAttached());
448
+ this.#button = UI.Toolbar.Toolbar.createActionButton(action);
387
449
  this.#button.setVisible(this.#commentManager.isAgentAttached());
388
450
  this.#commentManager.addEventListener(
389
451
  CommentManager.CommentManager.Events.AGENT_ATTACHED_CHANGED,
390
452
  event => {
453
+ action.setEnabled(event.data);
391
454
  this.#button.setVisible(event.data);
392
455
  },
393
456
  );
@@ -34,6 +34,7 @@ const kForbiddenSchemes = [
34
34
  'chrome-error:',
35
35
  'chrome-search:',
36
36
  'devtools:',
37
+ 'isolated-app:',
37
38
  ];
38
39
 
39
40
  declare global {
@@ -44,6 +45,18 @@ declare global {
44
45
 
45
46
  let extensionServerInstance: ExtensionServer|null;
46
47
 
48
+ function parseCanonicalURL(url: Platform.DevToolsPath.UrlString): URL|null {
49
+ try {
50
+ let parsedURL = new URL(url);
51
+ while (parsedURL.protocol === 'blob:' || parsedURL.protocol === 'filesystem:') {
52
+ parsedURL = new URL(parsedURL.href.slice(parsedURL.protocol.length));
53
+ }
54
+ return parsedURL;
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+
47
60
  export class HostsPolicy {
48
61
  static create(policy?: Host.InspectorFrontendHostAPI.ExtensionHostsPolicy): HostsPolicy|null {
49
62
  const runtimeAllowedHosts = [];
@@ -98,12 +111,11 @@ class RegisteredExtension {
98
111
  return false;
99
112
  }
100
113
 
101
- let parsedURL;
102
- try {
103
- parsedURL = new URL(inspectedURL);
104
- } catch {
114
+ const parsedURL = parseCanonicalURL(inspectedURL);
115
+ if (!parsedURL) {
105
116
  return false;
106
117
  }
118
+ inspectedURL = parsedURL.href as Platform.DevToolsPath.UrlString;
107
119
 
108
120
  if (parsedURL.protocol === 'chrome-extension:') {
109
121
  if (parsedURL.origin !== this.origin) {
@@ -1827,12 +1839,10 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1827
1839
  }
1828
1840
 
1829
1841
  static canInspectURL(url: Platform.DevToolsPath.UrlString): boolean {
1830
- let parsedURL;
1831
1842
  // This is only to work around invalid URLs we're occasionally getting from some tests.
1832
1843
  // TODO(caseq): make sure tests supply valid URLs or we specifically handle invalid ones.
1833
- try {
1834
- parsedURL = new URL(url);
1835
- } catch {
1844
+ const parsedURL = parseCanonicalURL(url);
1845
+ if (!parsedURL) {
1836
1846
  return false;
1837
1847
  }
1838
1848
 
@@ -30,6 +30,17 @@
30
30
  gap: var(--sys-size-4);
31
31
  }
32
32
 
33
+ .header-actions {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: var(--sys-size-3);
37
+ flex-shrink: 0;
38
+ }
39
+
40
+ .close-button {
41
+ flex-shrink: 0;
42
+ }
43
+
33
44
  .sent-status {
34
45
  display: flex;
35
46
  align-items: center;
@@ -459,7 +459,7 @@ export class ConsolePrompt extends ConsolePromptBase {
459
459
  ?.evaluateCommandInConsole(executionContext, message, expression, useCommandLineAPI);
460
460
  }
461
461
 
462
- private async substituteNames(expression: string, mapping: Map<string, string|null>): Promise<string> {
462
+ private async substituteNames(expression: string, mapping: Array<Map<string, string|null>>): Promise<string> {
463
463
  try {
464
464
  return await Formatter.FormatterWorkerPool.formatterWorkerPool().javaScriptSubstitute(expression, mapping);
465
465
  } catch {
@@ -1030,7 +1030,7 @@ export class ConsoleViewMessage implements ConsoleViewportElement {
1030
1030
  result.appendChild(this.formatParameterAsObject(remoteObject, false));
1031
1031
  return;
1032
1032
  }
1033
- const treeOutline = new Elements.ElementsTreeOutline.ElementsTreeOutline(
1033
+ const treeOutline = new Elements.DOMTreeWidget.ElementsTreeOutline(
1034
1034
  /* omitRootDOMNode: */ false, /* selectEnabled: */ true, /* hideGutter: */ true);
1035
1035
  treeOutline.rootDOMNode = node;
1036
1036
  treeOutline.deindentSingleNode();
@@ -359,7 +359,8 @@ export class ClassNamePrompt extends UI.TextPrompt.TextPrompt {
359
359
 
360
360
  let completions: string[] = await this.classNamesPromise;
361
361
  const classesMap = this.nodeClasses((selectedNode));
362
- completions = completions.filter(value => !classesMap.get(value));
362
+ const existingClasses = new Set(expression.split(/[,\s]/).map(className => className.trim()).filter(Boolean));
363
+ completions = completions.filter(value => !classesMap.get(value) && !existingClasses.has(value));
363
364
 
364
365
  if (prefix[0] === '.') {
365
366
  completions = completions.map(value => '.' + value);
@@ -9,9 +9,9 @@ import * as UI from '../../ui/legacy/legacy.js';
9
9
  import * as Emulation from '../emulation/emulation.js';
10
10
 
11
11
  import {canGetJSPath} from './DOMPath.js';
12
+ import type {DOMTreeWidget} from './DOMTreeWidget.js';
12
13
  import {ElementsPanel} from './ElementsPanel.js';
13
14
  import {ElementsTreeElement} from './ElementsTreeElement.js';
14
- import type {DOMTreeWidget} from './ElementsTreeOutline.js';
15
15
 
16
16
  const UIStrings = {
17
17
  /**
@@ -75,7 +75,7 @@ import {ImagePreviewPopover} from './ImagePreviewPopover.js';
75
75
  import {ShortcutTreeElement} from './ShortcutTreeElement.js';
76
76
  import {TopLayerContainer} from './TopLayerContainer.js';
77
77
 
78
- const {html, nothing, render, Directives: {classMap, repeat, styleMap}} = Lit;
78
+ const {html, nothing, render, Directives: {classMap, ifDefined, repeat, styleMap}} = Lit;
79
79
 
80
80
  const UIStrings = {
81
81
  /**
@@ -101,7 +101,7 @@ const UIStrings = {
101
101
  */
102
102
  reveal: 'reveal',
103
103
  } as const;
104
- const str_ = i18n.i18n.registerUIStrings('panels/elements/ElementsTreeOutline.ts', UIStrings);
104
+ const str_ = i18n.i18n.registerUIStrings('panels/elements/DOMTreeWidget.ts', UIStrings);
105
105
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
106
106
  const elementsTreeOutlineByDOMModel = new WeakMap<SDK.DOMModel.DOMModel, ElementsTreeOutline>();
107
107
 
@@ -919,6 +919,8 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
919
919
  // clang-format off
920
920
  return html`
921
921
  <li role="treeitem"
922
+ data-backend-node-id=${ifDefined(node.backendNodeId())}
923
+ data-target-id=${ifDefined(node.domModel().target().id())}
922
924
  selectable=${input.selectEnabled ? 'true' : 'false'}
923
925
  ?selected=${isSelected && !input.selectedClosingTag}
924
926
  class=${classes}
@@ -997,6 +999,8 @@ export const DECLARATIVE_VIEW: View = (input: ViewInput, _output: ViewOutput, ta
997
999
  ${node instanceof SDK.DOMModel.DOMDocument ? renderTopLayerContainer(node, depth + 1) : nothing}
998
1000
  ${needsClosingTag ? html`
999
1001
  <li role="treeitem"
1002
+ data-backend-node-id=${ifDefined(node.backendNodeId())}
1003
+ data-target-id=${ifDefined(node.domModel().target().id())}
1000
1004
  selectable=${input.selectEnabled ? 'true' : 'false'}
1001
1005
  ?selected=${isSelected && Boolean(input.selectedClosingTag)}
1002
1006
  class=${classMap({
@@ -1348,7 +1352,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
1348
1352
  element?: HTMLElement,
1349
1353
  [changeTracker]:
1350
1354
  UI.Widget.WidgetDependencies<typeof DOMTreeWidget>|[ChangeTracker.ChangeTracker.ChangeTracker?] = [],
1351
- view: View = DEFAULT_VIEW,
1355
+ view: View = DECLARATIVE_VIEW,
1352
1356
  ) {
1353
1357
  super(element, {
1354
1358
  useShadowDom: false,
@@ -1358,12 +1362,12 @@ export class DOMTreeWidget extends UI.Widget.Widget {
1358
1362
  this.#changeTracker = changeTracker;
1359
1363
  this.#showHTMLCommentsSetting.addChangeListener(this.#onShowHTMLCommentsChange, this);
1360
1364
  if (Common.Settings.Settings.instance().moduleSetting('highlight-node-on-hover-in-overlay').get()) {
1361
- SDK.TargetManager.TargetManager.instance().addModelListener(
1362
- SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.HIGHLIGHT_NODE_REQUESTED, this.#highlightNode, this,
1363
- {scoped: true});
1364
- SDK.TargetManager.TargetManager.instance().addModelListener(
1365
- SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.INSPECT_MODE_WILL_BE_TOGGLED,
1366
- this.#clearHighlightedNode, this, {scoped: true});
1365
+ SDK.TargetManager.TargetManager.instance().addModelListener(SDK.OverlayModel.OverlayModel,
1366
+ SDK.OverlayModel.Events.HIGHLIGHT_NODE_REQUESTED,
1367
+ this.#highlightNode, this, {scoped: true});
1368
+ SDK.TargetManager.TargetManager.instance().addModelListener(SDK.OverlayModel.OverlayModel,
1369
+ SDK.OverlayModel.Events.INSPECT_MODE_WILL_BE_TOGGLED,
1370
+ this.#clearHighlightedNode, this, {scoped: true});
1367
1371
  }
1368
1372
  this.#setupPopovers();
1369
1373
  }
@@ -2245,7 +2249,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
2245
2249
  this.onDocumentUpdated(domModel);
2246
2250
  } else {
2247
2251
  void domModel.requestDocument().then(document => {
2248
- if (document && this.isShowing()) {
2252
+ if (document && this.isShowing() && this.#wiredDOMModels.has(domModel)) {
2249
2253
  this.rootDOMNode = document;
2250
2254
  this.onDocumentUpdated(domModel);
2251
2255
  }
@@ -2269,6 +2273,12 @@ export class DOMTreeWidget extends UI.Widget.Widget {
2269
2273
  this.#wiredDOMModels.delete(domModel);
2270
2274
  this.#unwireDOMModel(domModel);
2271
2275
  }
2276
+ if (this.#rootDOMNode?.domModel() === domModel) {
2277
+ this.#rootDOMNode = null;
2278
+ this.#selectedDOMNode = null;
2279
+ this.#expandedNodes.clear();
2280
+ this.#updateRecords.clear();
2281
+ }
2272
2282
  this.performUpdate();
2273
2283
  return;
2274
2284
  }
@@ -3141,7 +3151,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
3141
3151
  this.onDocumentUpdated(domModel);
3142
3152
  } else if (this.#view === DECLARATIVE_VIEW) {
3143
3153
  void domModel.requestDocument().then(document => {
3144
- if (document && this.isShowing()) {
3154
+ if (document && this.isShowing() && this.#wiredDOMModels.has(domModel)) {
3145
3155
  this.rootDOMNode = document;
3146
3156
  this.onDocumentUpdated(domModel);
3147
3157
  }
@@ -3472,8 +3482,8 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
3472
3482
  }
3473
3483
 
3474
3484
  selectedNodeChanged(focus: boolean): void {
3475
- this.dispatchEventToListeners(
3476
- ElementsTreeOutline.Events.SelectedNodeChanged, {node: this.selectedDOMNodeInternal, focus});
3485
+ this.dispatchEventToListeners(ElementsTreeOutline.Events.SelectedNodeChanged,
3486
+ {node: this.selectedDOMNodeInternal, focus});
3477
3487
  }
3478
3488
 
3479
3489
  private fireElementsTreeUpdated(nodes: SDK.DOMModel.DOMNode[]): void {
@@ -3787,8 +3797,8 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
3787
3797
  domModel.addEventListener(SDK.DOMModel.Events.DocumentURLChanged, this.documentURLChanged, this);
3788
3798
  domModel.addEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.childNodeCountUpdated, this);
3789
3799
  domModel.addEventListener(SDK.DOMModel.Events.DistributedNodesChanged, this.distributedNodesChanged, this);
3790
- domModel.addEventListener(
3791
- SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated, this.affectedByStartingStylesFlagUpdated, this);
3800
+ domModel.addEventListener(SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated,
3801
+ this.affectedByStartingStylesFlagUpdated, this);
3792
3802
  domModel.addEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.adoptedStyleSheetsModified, this);
3793
3803
  }
3794
3804
 
@@ -3803,8 +3813,8 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
3803
3813
  domModel.removeEventListener(SDK.DOMModel.Events.DocumentURLChanged, this.documentURLChanged, this);
3804
3814
  domModel.removeEventListener(SDK.DOMModel.Events.ChildNodeCountUpdated, this.childNodeCountUpdated, this);
3805
3815
  domModel.removeEventListener(SDK.DOMModel.Events.DistributedNodesChanged, this.distributedNodesChanged, this);
3806
- domModel.removeEventListener(
3807
- SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated, this.affectedByStartingStylesFlagUpdated, this);
3816
+ domModel.removeEventListener(SDK.DOMModel.Events.AffectedByStartingStylesFlagUpdated,
3817
+ this.affectedByStartingStylesFlagUpdated, this);
3808
3818
  domModel.removeEventListener(SDK.DOMModel.Events.AdoptedStyleSheetsModified, this.adoptedStyleSheetsModified, this);
3809
3819
  elementsTreeOutlineByDOMModel.delete(domModel);
3810
3820
  }
@@ -4026,8 +4036,8 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
4026
4036
  return false;
4027
4037
  }
4028
4038
 
4029
- private createElementTreeElement(node: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[], isClosingTag?: boolean):
4030
- UI.TreeOutline.TreeElement {
4039
+ private createElementTreeElement(node: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[],
4040
+ isClosingTag?: boolean): UI.TreeOutline.TreeElement {
4031
4041
  if (node instanceof Array) {
4032
4042
  return new AdoptedStyleSheetSetTreeElement(node);
4033
4043
  }
@@ -4202,9 +4212,9 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
4202
4212
  this.#updateChildren(treeElement);
4203
4213
  }
4204
4214
 
4205
- insertChildElement(
4206
- treeElement: ElementsTreeElement|TopLayerContainer, child: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[],
4207
- index: number, isClosingTag?: boolean): UI.TreeOutline.TreeElement {
4215
+ insertChildElement(treeElement: ElementsTreeElement|TopLayerContainer,
4216
+ child: SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[], index: number,
4217
+ isClosingTag?: boolean): UI.TreeOutline.TreeElement {
4208
4218
  const newElement = this.createElementTreeElement(child, isClosingTag);
4209
4219
  treeElement.insertChild(newElement, index);
4210
4220
  return newElement;
@@ -4237,8 +4247,8 @@ export class ElementsTreeOutline extends ElementsTreeOutlineBase {
4237
4247
 
4238
4248
  // Remove any tree elements that no longer have this node as their parent and save
4239
4249
  // all existing elements that could be reused. This also removes closing tag element.
4240
- const existingTreeElements = new Map<
4241
- SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[], UI.TreeOutline.TreeElement&ElementsTreeElement>();
4250
+ const existingTreeElements = new Map<SDK.DOMModel.DOMNode|SDK.DOMModel.AdoptedStyleSheet[],
4251
+ UI.TreeOutline.TreeElement&ElementsTreeElement>();
4242
4252
  for (let i = treeElement.childCount() - 1; i >= 0; --i) {
4243
4253
  const existingTreeElement = treeElement.childAt(i);
4244
4254
  if (!(existingTreeElement instanceof ElementsTreeElement)) {
@@ -51,8 +51,8 @@ import {AccessibilityTreeView} from './AccessibilityTreeView.js';
51
51
  import {ColorSwatchPopoverIcon} from './ColorSwatchPopoverIcon.js';
52
52
  import * as ElementsComponents from './components/components.js';
53
53
  import {ComputedStyleWidget} from './ComputedStyleWidget.js';
54
+ import {DOMTreeWidget, type ElementsTreeOutline} from './DOMTreeWidget.js';
54
55
  import elementsPanelStyles from './elementsPanel.css.js';
55
- import {DOMTreeWidget, type ElementsTreeOutline} from './ElementsTreeOutline.js';
56
56
  import {LayoutPane} from './LayoutPane.js';
57
57
  import type {MarkerDecorator} from './MarkerDecorator.js';
58
58
  import {MetricsSidebarPane} from './MetricsSidebarPane.js';
@@ -67,10 +67,10 @@ import * as Media from '../media/media.js';
67
67
 
68
68
  import * as ElementsComponents from './components/components.js';
69
69
  import {cssPath} from './DOMPath.js';
70
+ import {type ElementsTreeOutline, MappedCharToEntity} from './DOMTreeWidget.js';
70
71
  import {getElementIssueDetails} from './ElementIssueUtils.js';
71
72
  import {ElementsPanel} from './ElementsPanel.js';
72
73
  import * as ElementStatePaneWidget from './ElementStatePaneWidget.js';
73
- import {type ElementsTreeOutline, MappedCharToEntity} from './ElementsTreeOutline.js';
74
74
  import {ImagePreviewPopover} from './ImagePreviewPopover.js';
75
75
  import {getRegisteredDecorators, type MarkerDecorator, type MarkerDecoratorRegistration} from './MarkerDecorator.js';
76
76
 
@@ -40,8 +40,8 @@ import * as Lit from '../../ui/lit/lit.js';
40
40
  import * as VisualElements from '../../ui/visual_logging/visual_logging.js';
41
41
 
42
42
  import * as ElementsComponents from './components/components.js';
43
+ import {ElementsTreeOutline} from './DOMTreeWidget.js';
43
44
  import {adornerRef, ElementsTreeElement, handleAdornerKeydown} from './ElementsTreeElement.js';
44
- import {ElementsTreeOutline} from './ElementsTreeOutline.js';
45
45
 
46
46
  const {html, render} = Lit;
47
47
 
@@ -304,6 +304,7 @@ export class StylePropertiesSection {
304
304
  closeBrace.createChild('span').textContent = '}';
305
305
  } else {
306
306
  this.titleElement.classList.add('hidden');
307
+ this.updateAncestorRuleList();
307
308
  }
308
309
 
309
310
  if (rule) {
@@ -425,6 +426,7 @@ export class StylePropertiesSection {
425
426
  this.computedStyleExtraFields = computedStyleExtraFields;
426
427
  this.#lastInheritedNode = matchedStyles.isInherited(style) ? matchedStyles.nodeForStyle(style) : null;
427
428
  this.update(true);
429
+ this.updateCollapsedState();
428
430
  }
429
431
 
430
432
  inheritedNode(): SDK.DOMModel.DOMNode|null {
@@ -1250,6 +1252,14 @@ export class StylePropertiesSection {
1250
1252
  this.#ancestorClosingBracesElement.removeChildren();
1251
1253
  this.maybeCreateAncestorRules(this.styleInternal);
1252
1254
  this.#styleRuleElement.style.paddingLeft = `${this.nestingLevel}ch`;
1255
+ if (this.headerText().length === 0 && (this.styleInternal.parentRule instanceof SDK.CSSRule.CSSStyleRule)) {
1256
+ const lastAncestor = this.#ancestorRuleListElement.lastElementChild;
1257
+ if (lastAncestor && this.#collapseIcon && this.#statusElement) {
1258
+ this.#collapseIcon.slot = 'indent';
1259
+ lastAncestor.append(this.#collapseIcon, this.#statusElement);
1260
+ }
1261
+ this.#ancestorClosingBracesElement.firstElementChild?.classList.add('sidebar-pane-closing-brace');
1262
+ }
1253
1263
  }
1254
1264
 
1255
1265
  isPropertyInherited(propertyName: string): boolean {