chrome-devtools-frontend 1.0.1697595 → 1.0.1697998

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.stylelintignore +2 -0
  2. package/front_end/core/common/VersionController.ts +5 -1
  3. package/front_end/core/sdk/AnimationModel.ts +9 -1
  4. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  5. package/front_end/generated/protocol.ts +8 -2
  6. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +26 -0
  7. package/front_end/models/ai_assistance/ai_assistance.ts +4 -4
  8. package/front_end/models/ai_assistance/skills/performance.md +4 -3
  9. package/front_end/models/ai_assistance/tools/{GetFunctionCode.ts → GetTraceFunctionCode.ts} +26 -13
  10. package/front_end/models/ai_assistance/tools/{GetResourceContent.ts → GetTraceResourceContent.ts} +31 -11
  11. package/front_end/models/ai_assistance/tools/Tool.ts +2 -2
  12. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +6 -6
  13. package/front_end/models/elements/DOMChanges.ts +238 -0
  14. package/front_end/models/elements/elements.ts +2 -0
  15. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -1
  16. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +25 -5
  17. package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +2 -3
  18. package/front_end/panels/elements/ElementsTreeElement.ts +98 -20
  19. package/front_end/panels/elements/ElementsTreeOutline.ts +271 -43
  20. package/front_end/panels/elements/EventListenersWidget.ts +0 -1
  21. package/front_end/panels/event_listeners/EventListenersView.ts +241 -297
  22. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
  23. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -2
  24. package/front_end/panels/network/NetworkConfigView.ts +141 -116
  25. package/front_end/panels/network/NetworkPanel.ts +7 -4
  26. package/front_end/panels/network/RequestHeadersView.ts +1 -1
  27. package/front_end/panels/network/forward/BackendLinking.ts +5 -2
  28. package/front_end/panels/settings/BackendLinkingSettingsTab.ts +7 -2
  29. package/front_end/panels/timeline/TimelineTreeView.ts +11 -1
  30. package/front_end/third_party/chromium/README.chromium +1 -1
  31. package/front_end/ui/comments/CommentOverlayManager.ts +169 -40
  32. package/front_end/ui/comments/CommentThreadWidget.ts +221 -0
  33. package/front_end/ui/comments/CommentsOverlayWidget.ts +124 -12
  34. package/front_end/ui/comments/commentThreadWidget.css +173 -0
  35. package/front_end/ui/comments/comments.ts +2 -0
  36. package/front_end/ui/comments/commentsOverlay.css +6 -0
  37. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +1 -1
  38. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +4 -0
  39. package/package.json +5 -5
@@ -13,21 +13,45 @@ import {
13
13
  Events as CommentOverlayManagerEvents,
14
14
  type HighlightRectData,
15
15
  type HoverHighlightData,
16
+ type PendingHighlightRectData,
17
+ type PendingPinPositionData,
16
18
  type PinPositionData,
17
19
  } from './CommentOverlayManager.js';
18
20
  import commentsOverlayStyles from './commentsOverlay.css.js';
21
+ import {CommentThreadWidget} from './CommentThreadWidget.js';
19
22
 
20
- const {html, render, nothing, Directives: {styleMap}} = Lit;
23
+ const {
24
+ html,
25
+ render,
26
+ nothing,
27
+ Directives: {repeat, styleMap},
28
+ } = Lit;
29
+
30
+ export type ViewHighlightRectData = HighlightRectData|PendingHighlightRectData;
21
31
 
22
32
  export interface ViewInput {
23
33
  pins: PinPositionData[];
24
- highlights: HighlightRectData[];
34
+ pendingPin: PendingPinPositionData|null;
35
+ highlights: ViewHighlightRectData[];
25
36
  hoverHighlight: HoverHighlightData|null;
26
37
  commentMode: boolean;
27
38
  onPinClick: (threadId: string) => void;
39
+ activeThread: CommentManager.CommentManager.CommentThread|null;
40
+ activePin: PinPositionData|PendingPinPositionData|null;
41
+ activeTargetKey: unknown;
42
+ onAddComment: (text: string) => void;
28
43
  }
29
44
 
30
- export type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
45
+ export type View = (
46
+ input: ViewInput,
47
+ output: undefined,
48
+ target: HTMLElement,
49
+ ) => void;
50
+
51
+ const POPUP_MARGIN = 8;
52
+ const PIN_HEIGHT = 30;
53
+ const POPUP_WIDTH = 288;
54
+ const POPUP_HEIGHT = 220;
31
55
 
32
56
  const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
33
57
  // clang-format off
@@ -48,7 +72,7 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
48
72
  ${input.highlights.map(h => h.visible ? html`
49
73
  <div
50
74
  class="comment-anchor-highlight"
51
- data-comment-id=${h.id}
75
+ data-comment-id=${('id' in h && h.id) || nothing}
52
76
  style=${styleMap({
53
77
  top: `${h.top}px`,
54
78
  left: `${h.left}px`,
@@ -57,6 +81,16 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
57
81
  })}>
58
82
  </div>
59
83
  ` : nothing)}
84
+ ${input.pendingPin && input.pendingPin.visible ? html`
85
+ <div
86
+ class="comment-pin"
87
+ style=${styleMap({
88
+ top: `${input.pendingPin.top}px`,
89
+ left: `${input.pendingPin.left}px`,
90
+ })}>
91
+ <div class="comment-cursor">${input.pendingPin.index}</div>
92
+ </div>
93
+ ` : nothing}
60
94
  ${input.pins.map(p => p.visible ? html`
61
95
  <div
62
96
  class="comment-pin"
@@ -69,25 +103,54 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: undefined, target: HTMLEl
69
103
  <div class="comment-cursor">${p.index}</div>
70
104
  </div>
71
105
  ` : nothing)}
106
+ ${input.activePin ? repeat(
107
+ [{pin: input.activePin, key: input.activeTargetKey}],
108
+ item => item.key,
109
+ item => html`
110
+ <div
111
+ class="comment-popup-widget"
112
+ style=${styleMap({
113
+ top: `${Math.min(
114
+ Math.max(POPUP_MARGIN, item.pin.top + PIN_HEIGHT),
115
+ Math.max(POPUP_MARGIN, target.clientHeight - POPUP_HEIGHT),
116
+ )}px`,
117
+ left: `${Math.min(
118
+ Math.max(POPUP_MARGIN, item.pin.left),
119
+ Math.max(POPUP_MARGIN, target.clientWidth - POPUP_WIDTH - POPUP_MARGIN),
120
+ )}px`,
121
+ })}>
122
+ ${UI.Widget.widget(CommentThreadWidget, {
123
+ comments: input.activeThread ? [...input.activeThread.comments] : [],
124
+ onAddComment: input.onAddComment,
125
+ })}
126
+ </div>
127
+ `,
128
+ ) : nothing}
72
129
  </div>
73
130
  `, target);
74
131
  // clang-format on
75
132
  };
76
133
 
77
134
  export class CommentsOverlayWidget extends UI.Widget.Widget {
135
+ static override readonly INJECT: readonly[typeof CommentManager.CommentManager.CommentManager] =
136
+ [CommentManager.CommentManager.CommentManager] as const;
137
+
78
138
  readonly #view: View;
79
139
  readonly #commentManager: CommentManager.CommentManager.CommentManager;
80
140
  #commentOverlayManager: CommentOverlayManager;
141
+ #activeThreadId: string|null = null;
81
142
 
82
143
  constructor(
83
144
  element: HTMLElement|undefined,
84
- commentManager: CommentManager.CommentManager.CommentManager,
145
+ [commentManager]: UI.Widget.WidgetDependencies<typeof CommentsOverlayWidget>,
85
146
  view: View = DEFAULT_VIEW,
86
147
  ) {
87
148
  super(element, {useShadowDom: false});
88
149
  this.#view = view;
89
150
  this.#commentManager = commentManager;
90
- this.#commentOverlayManager = new CommentOverlayManager(this.#commentManager);
151
+ this.#commentOverlayManager = new CommentOverlayManager(
152
+ this.#commentManager,
153
+ );
91
154
  }
92
155
 
93
156
  setOverlayManagerForTest(overlayManager: CommentOverlayManager): void {
@@ -154,24 +217,68 @@ export class CommentsOverlayWidget extends UI.Widget.Widget {
154
217
  CommentManager.CommentManager.EventTypes[CommentManager.CommentManager.Events.COMMENT_MODE_CHANGED]>,
155
218
  ): void {
156
219
  const isModeActive = event.data;
157
- const action = UI.ActionRegistry.ActionRegistry.instance().getAction('comments.toggle-comment-mode');
220
+ const action = UI.ActionRegistry.ActionRegistry.instance().getAction(
221
+ 'comments.toggle-comment-mode',
222
+ );
158
223
  action?.setToggled(isModeActive);
159
224
  this.requestUpdate();
160
225
  }
161
226
 
162
227
  #onStateChanged(): void {
228
+ if (this.#commentOverlayManager.getPendingDraft()) {
229
+ this.#activeThreadId = null;
230
+ }
163
231
  this.requestUpdate();
164
232
  }
165
233
 
166
- #handlePinClick = (_threadId: string): void => {};
234
+ #handlePinClick = (threadId: string): void => {
235
+ this.#commentOverlayManager.clearPendingAnchor();
236
+ if (this.#activeThreadId === threadId) {
237
+ this.#activeThreadId = null;
238
+ } else {
239
+ this.#activeThreadId = threadId;
240
+ }
241
+ this.requestUpdate();
242
+ };
167
243
 
168
244
  override performUpdate(): void {
245
+ const pins = this.#commentOverlayManager.getPinPositions();
246
+ const draft = this.#commentOverlayManager.getPendingDraft();
247
+ const pendingPin = draft?.pin ?? null;
248
+ const highlights: ViewHighlightRectData[] = [
249
+ ...this.#commentOverlayManager.getHighlightRects(),
250
+ ];
251
+
252
+ if (draft?.highlight) {
253
+ highlights.push(draft.highlight);
254
+ }
255
+
256
+ let activePin: PinPositionData|PendingPinPositionData|null = null;
257
+ let activeThread: CommentManager.CommentManager.CommentThread|null = null;
258
+ if (pendingPin) {
259
+ activePin = pendingPin;
260
+ } else if (this.#activeThreadId) {
261
+ activePin = pins.find(p => p.id === this.#activeThreadId) ?? null;
262
+ activeThread = this.#commentManager.getCommentThread(this.#activeThreadId) ?? null;
263
+ }
264
+
169
265
  const viewInput: ViewInput = {
170
- pins: this.#commentOverlayManager.getPinPositions(),
171
- highlights: this.#commentOverlayManager.getHighlightRects(),
266
+ pins,
267
+ pendingPin,
268
+ highlights,
172
269
  hoverHighlight: this.#commentOverlayManager.getHoverHighlight(),
173
270
  commentMode: this.#commentManager.isCommentMode(),
174
271
  onPinClick: this.#handlePinClick,
272
+ activeThread,
273
+ activePin,
274
+ activeTargetKey: draft ?? activeThread,
275
+ onAddComment: (text: string) => {
276
+ const pendingDraft = this.#commentOverlayManager.getPendingDraft();
277
+
278
+ if (pendingDraft) {
279
+ this.#commentOverlayManager.createComment(pendingDraft.element, text, {pendingDraft});
280
+ }
281
+ },
175
282
  };
176
283
  this.#view(viewInput, undefined, this.contentElement);
177
284
  }
@@ -192,11 +299,16 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
192
299
  handleAction(_context: UI.Context.Context, actionId: string): boolean {
193
300
  if (actionId === 'comments.toggle-comment-mode') {
194
301
  if (!widgetInstance) {
195
- widgetInstance = new CommentsOverlayWidget(undefined, this.#commentManager);
302
+ widgetInstance = new CommentsOverlayWidget(
303
+ undefined,
304
+ [this.#commentManager],
305
+ );
196
306
  widgetInstance.markAsRoot();
197
307
  widgetInstance.show(document.body);
198
308
  }
199
- this.#commentManager.setCommentMode(!this.#commentManager.isCommentMode());
309
+ this.#commentManager.setCommentMode(
310
+ !this.#commentManager.isCommentMode(),
311
+ );
200
312
  return true;
201
313
  }
202
314
  return false;
@@ -0,0 +1,173 @@
1
+ /*
2
+ * Copyright 2026 The Chromium Authors
3
+ * Use of this source code is governed by a BSD-style license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ @scope to (devtools-widget > *) {
8
+ .comment-thread-widget {
9
+ display: flex;
10
+ width: var(--sys-size-30);
11
+ padding: var(--sys-size-8);
12
+ flex-direction: column;
13
+ align-items: flex-start;
14
+ gap: var(--sys-size-4);
15
+ border-radius: var(--sys-shape-corner-medium);
16
+ background: var(--sys-color-base);
17
+ box-shadow: var(--sys-elevation-level2);
18
+ cursor: default;
19
+ }
20
+
21
+ .comment-thread-widget.submitted {
22
+ background: var(--sys-color-surface2);
23
+ }
24
+
25
+ .header {
26
+ display: flex;
27
+ width: 100%;
28
+ justify-content: space-between;
29
+ align-items: center;
30
+ }
31
+
32
+ .sent-status {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: var(--sys-size-2);
36
+ font-size: var(--sys-typescale-body5-size);
37
+ color: var(--sys-color-on-surface-subtle);
38
+ }
39
+
40
+ .check-icon {
41
+ width: var(--sys-size-7);
42
+ height: var(--sys-size-7);
43
+ color: var(--sys-color-on-surface-subtle);
44
+ }
45
+
46
+ .selected-item {
47
+ display: flex;
48
+ height: calc(var(--sys-size-8) + var(--sys-size-2));
49
+ padding: var(--sys-size-2) var(--sys-size-4) var(--sys-size-2) var(--sys-size-3);
50
+ align-items: center;
51
+ border-radius: var(--sys-shape-corner-extra-small);
52
+ border: var(--sys-size-1) solid var(--sys-color-divider);
53
+ background: var(--sys-color-base);
54
+ font-family: var(--source-code-font-family);
55
+ font-size: var(--monospace-font-size);
56
+ color: var(--sys-color-token-tag);
57
+ overflow: hidden;
58
+ max-width: 100%;
59
+ min-width: 0;
60
+ }
61
+
62
+ .comment-text {
63
+ width: 100%;
64
+ font-family: var(--default-font-family);
65
+ font-size: var(--sys-typescale-body4-size);
66
+ color: var(--sys-color-on-surface-subtle);
67
+ line-height: var(--sys-size-9);
68
+ overflow-wrap: break-word;
69
+ white-space: pre-wrap;
70
+ }
71
+
72
+ .agent-response {
73
+ display: flex;
74
+ gap: var(--sys-size-2);
75
+ margin-top: var(--sys-size-4);
76
+ width: 100%;
77
+ align-items: flex-start;
78
+ }
79
+
80
+ .elbow {
81
+ width: var(--sys-size-6);
82
+ height: var(--sys-size-6);
83
+ margin-left: var(--sys-size-3);
84
+ margin-right: var(--sys-size-3);
85
+ border-left: var(--sys-size-1) solid var(--sys-color-neutral-outline);
86
+ border-bottom: var(--sys-size-1) solid var(--sys-color-neutral-outline);
87
+ border-bottom-left-radius: var(--sys-size-6);
88
+ flex-shrink: 0;
89
+ }
90
+
91
+ .response-content {
92
+ display: flex;
93
+ flex-direction: column;
94
+ flex: 1;
95
+ min-width: 0;
96
+
97
+ --code-block-background-color: var(--sys-color-base);
98
+ --code-background-color: var(--sys-color-base);
99
+ }
100
+
101
+ .response-header {
102
+ font-weight: bold;
103
+ margin-bottom: var(--sys-size-2);
104
+ font-family: var(--default-font-family);
105
+ font-size: var(--sys-typescale-body5-size);
106
+ line-height: var(--sys-size-8);
107
+ color: var(--sys-color-on-surface-subtle);
108
+ }
109
+
110
+ .response-content devtools-markdown-view {
111
+ font-family: var(--default-font-family);
112
+ font-size: var(--sys-typescale-body4-size);
113
+ color: var(--sys-color-on-surface-subtle);
114
+ line-height: var(--sys-size-9);
115
+ }
116
+
117
+ .input {
118
+ height: auto;
119
+ min-height: var(--sys-size-14);
120
+ max-height: var(--sys-size-27);
121
+ field-sizing: content;
122
+ resize: none;
123
+ scrollbar-width: none;
124
+ padding: var(--sys-size-5) var(--sys-size-8);
125
+ border-radius: var(--sys-shape-corner-small);
126
+ border: var(--sys-size-1) solid var(--sys-color-outline);
127
+ background: var(--sys-color-base);
128
+ font-family: var(--default-font-family);
129
+ font-size: var(--sys-typescale-body5-size);
130
+ line-height: var(--sys-size-9);
131
+ letter-spacing: 0;
132
+ }
133
+
134
+ .input::placeholder {
135
+ color: var(--sys-color-on-surface-subtle);
136
+ }
137
+
138
+ .footer {
139
+ display: flex;
140
+ width: 100%;
141
+ justify-content: flex-end;
142
+ align-items: center;
143
+ gap: var(--sys-size-5);
144
+ }
145
+
146
+ .info-icon {
147
+ color: var(--sys-color-on-surface-subtle);
148
+ cursor: pointer;
149
+ }
150
+
151
+ .info-tooltip-container {
152
+ max-width: var(--sys-size-28);
153
+ padding: var(--sys-size-4) var(--sys-size-5);
154
+ }
155
+
156
+ .tooltip-link {
157
+ display: block;
158
+ margin-top: var(--sys-size-4);
159
+ color: var(--sys-color-primary);
160
+ padding-left: 0;
161
+ background: none;
162
+ border: none;
163
+ font: inherit;
164
+ text-decoration: underline;
165
+ cursor: pointer;
166
+ }
167
+
168
+ .selected-item-text {
169
+ overflow: hidden;
170
+ white-space: nowrap;
171
+ text-overflow: ellipsis;
172
+ }
173
+ }
@@ -6,10 +6,12 @@ import * as CommentAnchorResolver from './CommentAnchorResolver.js';
6
6
  import * as CommentOverlayManager from './CommentOverlayManager.js';
7
7
  import * as CommentsOverlayWidget from './CommentsOverlayWidget.js';
8
8
  import * as CommentsStatusBarPill from './CommentsStatusBarPill.js';
9
+ import * as CommentThreadWidget from './CommentThreadWidget.js';
9
10
 
10
11
  export {
11
12
  CommentAnchorResolver,
12
13
  CommentOverlayManager,
13
14
  CommentsOverlayWidget,
14
15
  CommentsStatusBarPill,
16
+ CommentThreadWidget,
15
17
  };
@@ -66,4 +66,10 @@
66
66
  background-color: color-mix(in srgb, var(--sys-color-primary), transparent 85%);
67
67
  box-sizing: border-box;
68
68
  }
69
+
70
+ .comment-popup-widget {
71
+ position: absolute;
72
+ z-index: 2501;
73
+ pointer-events: auto;
74
+ }
69
75
  }
@@ -1984,7 +1984,7 @@ export class ObjectPropertyTreeElement extends UI.TreeOutline.TreeElement {
1984
1984
  if (arrayRanges && arrayRanges.length > 0) {
1985
1985
  empty = false;
1986
1986
  }
1987
- const sortPropertiesAlphabetically = properties?.[0]?.parent?.sortPropertiesAlphabetically ?? true;
1987
+ const sortPropertiesAlphabetically = properties?.[0]?.sortPropertiesAlphabetically ?? true;
1988
1988
  properties?.sort((a, b) => compareProperties(a, b, sortPropertiesAlphabetically));
1989
1989
 
1990
1990
  const entriesProperty = internalProperties?.find(({property}) => property.name === '[[Entries]]');
@@ -583,6 +583,10 @@ export class FlameChart extends FlameChartBase implements NetworkTimeCalculator.
583
583
  }
584
584
 
585
585
  #transformColor(entryIndex: number, color: string): string {
586
+ if (!color) {
587
+ return '';
588
+ }
589
+
586
590
  if (this.#shouldDimEvent(entryIndex)) {
587
591
  let dimmed = this.colorDimmingCache.get(color);
588
592
  if (dimmed) {
package/package.json CHANGED
@@ -52,8 +52,8 @@
52
52
  "@typescript-eslint/utils": "8.64.0",
53
53
  "@typescript/tsc": "npm:typescript@6.0.2",
54
54
  "chai": "6.2.2",
55
- "cssnano": "8.0.2",
56
- "cssnano-preset-lite": "5.0.1",
55
+ "cssnano": "9.0.4",
56
+ "cssnano-preset-lite": "6.0.2",
57
57
  "diff": "9.0.0",
58
58
  "esbuild": "0.28.2",
59
59
  "eslint": "9.39.5",
@@ -75,11 +75,11 @@
75
75
  "lit-analyzer": "2.0.3",
76
76
  "mocha": "12.0.0",
77
77
  "ora": "9.0.0",
78
- "postcss": "8.5.25",
78
+ "postcss": "8.5.28",
79
79
  "puppeteer-core": "25.3.0",
80
80
  "sinon": "22.0.0",
81
81
  "source-map-support": "0.5.21",
82
- "stylelint": "17.14.0",
82
+ "stylelint": "17.15.0",
83
83
  "stylelint-config-standard": "40.0.0",
84
84
  "svgo": "4.1.0",
85
85
  "ts-lit-plugin": "2.0.2",
@@ -90,5 +90,5 @@
90
90
  "yargs": "18.1.0",
91
91
  "yargs-unparser": "2.0.0"
92
92
  },
93
- "version": "1.0.1697595"
93
+ "version": "1.0.1697998"
94
94
  }