chrome-devtools-frontend 1.0.1518653 → 1.0.1519267

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 (91) hide show
  1. package/config/owner/COMMON_OWNERS +2 -2
  2. package/eslint.config.mjs +1 -0
  3. package/front_end/core/sdk/EnhancedTracesParser.ts +5 -5
  4. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +211 -0
  5. package/front_end/core/sdk/TargetManager.ts +4 -0
  6. package/front_end/generated/SupportedCSSProperties.js +19 -4
  7. package/front_end/models/ai_assistance/agents/AiAgent.ts +57 -10
  8. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +4 -53
  9. package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -31
  10. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +6 -0
  11. package/front_end/models/ai_assistance/performance/AIContext.ts +1 -1
  12. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -0
  13. package/front_end/models/badges/AiExplorerBadge.ts +19 -3
  14. package/front_end/models/badges/Badge.ts +2 -0
  15. package/front_end/models/badges/CodeWhispererBadge.ts +1 -0
  16. package/front_end/models/badges/DOMDetectiveBadge.ts +1 -0
  17. package/front_end/models/badges/SpeedsterBadge.ts +1 -0
  18. package/front_end/models/badges/StarterBadge.ts +1 -0
  19. package/front_end/models/badges/badges.ts +1 -0
  20. package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
  21. package/front_end/models/trace/EventsSerializer.ts +4 -3
  22. package/front_end/models/trace/handlers/UserInteractionsHandler.ts +101 -73
  23. package/front_end/models/trace/helpers/Timing.ts +1 -1
  24. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +4 -1
  25. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +16 -14
  26. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
  27. package/front_end/panels/common/BadgeNotification.ts +3 -3
  28. package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
  29. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
  30. package/front_end/panels/recorder/components/RecordingView.ts +2 -2
  31. package/front_end/panels/search/SearchResultsPane.ts +157 -138
  32. package/front_end/panels/search/SearchView.ts +12 -9
  33. package/front_end/panels/search/searchResultsPane.css +9 -0
  34. package/front_end/panels/security/CookieControlsView.ts +2 -1
  35. package/front_end/panels/settings/AISettingsTab.ts +6 -3
  36. package/front_end/panels/settings/components/SyncSection.ts +23 -9
  37. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -1
  38. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +3 -0
  39. package/front_end/panels/sources/SourcesPanel.ts +1 -1
  40. package/front_end/panels/sources/sourcesView.css +6 -1
  41. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +1 -1
  42. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +1 -1
  43. package/front_end/panels/timeline/components/RelatedInsightChips.ts +1 -1
  44. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  45. package/front_end/third_party/chromium/README.chromium +1 -1
  46. package/front_end/third_party/puppeteer/README.chromium +2 -2
  47. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  48. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
  50. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  51. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  52. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  53. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  54. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
  55. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  56. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  57. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  58. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.d.ts.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +16 -25
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  63. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +19 -28
  64. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
  65. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  67. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  68. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
  70. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.d.ts.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +16 -25
  76. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
  77. package/front_end/third_party/puppeteer/package/package.json +10 -3
  78. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  79. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  80. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
  81. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  82. package/front_end/third_party/puppeteer/package/src/util/Function.ts +22 -30
  83. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  84. package/front_end/ui/components/markdown_view/MarkdownImage.ts +4 -5
  85. package/front_end/ui/components/switch/SwitchImpl.ts +12 -1
  86. package/front_end/ui/components/text_editor/config.ts +16 -2
  87. package/front_end/ui/legacy/Treeoutline.ts +3 -1
  88. package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -11
  89. package/front_end/ui/lit/i18n-template.ts +5 -2
  90. package/front_end/ui/visual_logging/KnownContextValues.ts +9 -5
  91. package/package.json +1 -1
@@ -1,16 +1,13 @@
1
1
  // Copyright 2014 The Chromium Authors
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
- /* eslint-disable rulesdir/no-imperative-dom-api */
5
- /* eslint-disable rulesdir/no-lit-render-outside-of-view */
6
-
7
4
  import * as Common from '../../core/common/common.js';
8
5
  import * as i18n from '../../core/i18n/i18n.js';
9
6
  import * as Platform from '../../core/platform/platform.js';
10
7
  import * as TextUtils from '../../models/text_utils/text_utils.js';
11
8
  import type * as Workspace from '../../models/workspace/workspace.js';
12
9
  import * as UI from '../../ui/legacy/legacy.js';
13
- import {html, render} from '../../ui/lit/lit.js';
10
+ import {html, render, type TemplateResult} from '../../ui/lit/lit.js';
14
11
 
15
12
  import searchResultsPaneStyles from './searchResultsPane.css.js';
16
13
  import type {SearchResult} from './SearchScope.js';
@@ -41,143 +38,168 @@ interface SearchMatch {
41
38
  resultLabel: string|number;
42
39
  }
43
40
 
44
- export class SearchResultsPane extends UI.Widget.VBox {
45
- private readonly searchConfig: Workspace.SearchConfig.SearchConfig;
46
- private readonly searchResults = new Map<SearchResult, UI.TreeOutline.TreeElement>();
47
- private expandedResults = new WeakSet<SearchResult>();
48
- private readonly searchMatches = new WeakMap<SearchResult, SearchMatch[]>();
49
- private treeOutline: UI.TreeOutline.TreeOutlineInShadow;
50
- private matchesExpandedCount = 0;
51
-
52
- private addTreeElement(searchResult: SearchResult): void {
53
- const treeElement = new UI.TreeOutline.TreeElement('', true);
54
- treeElement.toggleOnClick = true;
55
- this.searchResults.set(searchResult, treeElement);
56
- this.treeOutline.appendChild(treeElement);
57
- if (!this.treeOutline.selectedTreeElement) {
58
- treeElement.select(/* omitFocus */ true, /* selectedByUser */ true);
59
- }
60
- treeElement.listItemElement.classList.add('search-result');
61
- // clang-format off
62
- render(html`
63
- <span class="search-result-file-name">${searchResult.label()}
64
- <span class="search-result-dash">${'\u2014'}</span>
65
- <span class="search-result-qualifier">${searchResult.description()}</span>
66
- </span>
67
- <span class="search-result-matches-count"
68
- aria-label=${i18nString(UIStrings.matchesCountS, {PH1: searchResult.matchesCount()})}>
69
- ${searchResult.matchesCount()}
70
- </span>`,
71
- treeElement.listItemElement);
72
- // clang-format on
73
- treeElement.tooltip = searchResult.description();
74
- }
41
+ interface ViewInput {
42
+ results: SearchResult[];
43
+ matches: WeakMap<SearchResult, SearchMatch[]>;
44
+ expandedResults: WeakSet<SearchResult>;
45
+ onSelectMatch: (searchResult: SearchResult, matchIndex: number) => void;
46
+ onExpandSearchResult: (searchResult: SearchResult) => void;
47
+ onShowMoreMatches: (searchResult: SearchResult) => void;
48
+ }
75
49
 
76
- private appendSearchMatchElement(searchResult: SearchResult, match: SearchMatch, i: number): void {
77
- const {lineContent, matchRanges, resultLabel} = match;
78
- const element = this.searchResults.get(searchResult);
79
- if (!element) {
80
- return;
50
+ export type View = (input: ViewInput, output: unknown, target: HTMLElement) => void;
51
+
52
+ export const DEFAULT_VIEW: View = (input, _output, target) => {
53
+ const {results, matches, expandedResults, onSelectMatch, onExpandSearchResult, onShowMoreMatches} = input;
54
+
55
+ const onExpand = ({detail: {expanded, target}}: UI.TreeOutline.TreeViewElement.ExpandEvent): void => {
56
+ const searchResultIndex = Number(target.dataset.searchResultIndex);
57
+ const searchResult = results[searchResultIndex];
58
+ if (expanded) {
59
+ expandedResults.add(searchResult);
60
+ onExpandSearchResult(searchResult);
61
+ } else {
62
+ expandedResults.delete(searchResult);
81
63
  }
82
- const searchMatchElement = new UI.TreeOutline.TreeElement();
83
- element.appendChild(searchMatchElement);
84
- // clang-format off
85
- render(html`
86
- <button class="devtools-link text-button link-style search-match-link"
87
- jslog="Link; context: search-match; track: click" role="link" tabindex="0"
88
- @click=${() => void Common.Revealer.reveal(searchResult.matchRevealable(i))}>
89
- <span class="search-match-line-number"
90
- aria-label=${typeof resultLabel === 'number' && !isNaN(resultLabel)
91
- ? i18nString(UIStrings.lineS, {PH1: resultLabel}) : resultLabel}>
92
- ${resultLabel}
93
- </span>
94
- <span class="search-match-content" aria-label="${lineContent} line">
95
- ${lineContent}
96
- </span>
97
- </button>`,
98
- searchMatchElement.listItemElement);
99
- // clang-format on
100
- const contentSpan = searchMatchElement.listItemElement.querySelector('.search-match-content') as HTMLElement;
101
- UI.UIUtils.highlightRangesWithStyleClass(contentSpan, matchRanges, 'highlighted-search-result');
102
- searchMatchElement.listItemElement.className = 'search-match';
103
- searchMatchElement.listItemElement.addEventListener('keydown', event => {
104
- if (event.key === 'Enter') {
105
- event.consume(true);
106
- void Common.Revealer.reveal(searchResult.matchRevealable(i));
107
- }
108
- });
109
- searchMatchElement.tooltip = lineContent;
110
- }
64
+ };
65
+
66
+ // clang-format off
67
+ render(html`
68
+ <devtools-tree hide-overflow @expand=${onExpand} .template=${html`
69
+ <ul role="tree">
70
+ ${results.map((searchResult, i) => html`
71
+ <li role="treeitem" data-search-result-index=${i} class="search-result">
72
+ <style>${searchResultsPaneStyles}</style>
73
+ ${renderSearchResult(searchResult)}
74
+ <ul role="group" ?hidden=${!expandedResults.has(searchResult)}>
75
+ ${renderSearchMatches(searchResult, matches, onSelectMatch, onShowMoreMatches)}
76
+ </ul>
77
+ </li>`)}
78
+ </ul>
79
+ `}></devtools-tree>`,
80
+ target,
81
+ );
82
+ // clang-format on
83
+ };
84
+
85
+ const renderSearchResult = (searchResult: SearchResult): TemplateResult => {
86
+ // clang-format off
87
+ return html`
88
+ <span class="search-result-file-name">${searchResult.label()}
89
+ <span class="search-result-dash">${'\u2014'}</span>
90
+ <span class="search-result-qualifier">${searchResult.description()}</span>
91
+ </span>
92
+ <span class="search-result-matches-count"
93
+ aria-label=${i18nString(UIStrings.matchesCountS, {PH1: searchResult.matchesCount()})}>
94
+ ${searchResult.matchesCount()}
95
+ </span>`;
96
+ // clang-format on
97
+ };
98
+
99
+ const renderSearchMatches =
100
+ (searchResult: SearchResult, matches: WeakMap<SearchResult, SearchMatch[]>,
101
+ onSelectMatch: (searchResult: SearchResult, matchIndex: number) => void,
102
+ onShowMoreMatches: (searchResult: SearchResult) => void): TemplateResult => {
103
+ const visibleMatches = matches.get(searchResult) ?? [];
104
+ const matchesLeftCount = searchResult.matchesCount() - visibleMatches.length;
105
+ // clang-format off
106
+ return html`
107
+ ${visibleMatches.map(({lineContent, matchRanges, resultLabel}, i) => html`
108
+ <li role="treeitem" class="search-match" @click=${() => onSelectMatch(searchResult, i)}
109
+ ${UI.TreeOutline.TreeSearch.highlight(matchRanges.map(range =>
110
+ ({offset: range.offset + `${resultLabel}`.length, length: range.length})), undefined)}
111
+ @keydown=${(event: KeyboardEvent) => {
112
+ if (event.key === 'Enter') {
113
+ onSelectMatch(searchResult, i);
114
+ }
115
+ }}
116
+ >
117
+ <button class="devtools-link text-button link-style search-match-link"
118
+ jslog="Link; context: search-match; track: click" role="link" tabindex="0"
119
+ @click=${() => void Common.Revealer.reveal(searchResult.matchRevealable(i))}>
120
+ <span class="search-match-line-number"
121
+ aria-label=${typeof resultLabel === 'number' && !isNaN(resultLabel)
122
+ ? i18nString(UIStrings.lineS, {PH1: resultLabel}) : resultLabel}>
123
+ ${resultLabel}
124
+ </span>
125
+ <span class="search-match-content" aria-label="${lineContent} line">
126
+ ${lineContent}
127
+ </span>
128
+ </button>
129
+ </li>`)}
130
+ ${
131
+ matchesLeftCount > 0 ? html`
132
+ <li role="treeitem" class="show-more-matches" @click=${() => onShowMoreMatches(searchResult)}>
133
+ ${i18nString(UIStrings.showDMore, { PH1: matchesLeftCount })}
134
+ </li>` : ''}`;
135
+ // clang-format on
136
+ };
137
+
138
+ export class SearchResultsPane extends UI.Widget.VBox {
139
+ readonly #searchConfig: Workspace.SearchConfig.SearchConfig;
140
+ #searchResults: SearchResult[] = [];
141
+ #expandedResults = new WeakSet<SearchResult>();
142
+ readonly #searchMatches = new WeakMap<SearchResult, SearchMatch[]>();
143
+ #view: View;
111
144
 
112
- constructor(searchConfig: Workspace.SearchConfig.SearchConfig) {
145
+ constructor(searchConfig: Workspace.SearchConfig.SearchConfig, view: View = DEFAULT_VIEW) {
113
146
  super({useShadowDom: true});
114
- this.searchConfig = searchConfig;
115
- this.treeOutline = new UI.TreeOutline.TreeOutlineInShadow();
116
- this.treeOutline.registerRequiredCSS(searchResultsPaneStyles);
117
- this.treeOutline.setHideOverflow(true);
118
- this.treeOutline.addEventListener(
119
- UI.TreeOutline.Events.ElementExpanded,
120
- (event: Common.EventTarget.EventTargetEvent<UI.TreeOutline.TreeElement>) => {
121
- const searchResult = this.searchResults.entries().find(entry => entry[1] === event.data)?.[0];
122
- if (!searchResult) {
123
- return;
124
- }
125
- this.expandSearchResult(searchResult);
126
- });
127
-
128
- this.contentElement.appendChild(this.treeOutline.element);
129
-
130
- this.matchesExpandedCount = 0;
147
+ this.#view = view;
148
+ this.#searchConfig = searchConfig;
149
+ }
150
+
151
+ get searchResults(): SearchResult[] {
152
+ return this.#searchResults;
131
153
  }
132
154
 
133
- addSearchResult(searchResult: SearchResult): void {
134
- this.addTreeElement(searchResult);
135
- // Expand until at least a certain number of matches is expanded.
136
- if (this.matchesExpandedCount < matchesExpandedByDefault) {
137
- this.searchResults.get(searchResult)?.expand();
155
+ set searchResults(searchResults: SearchResult[]) {
156
+ this.#searchResults = searchResults;
157
+ let matchesExpandedCount = 0;
158
+ for (const searchResult of searchResults) {
159
+ if (this.#expandedResults.has(searchResult)) {
160
+ matchesExpandedCount += this.#searchMatches.get(searchResult)?.length ?? 0;
161
+ }
138
162
  }
163
+ for (const searchResult of searchResults) {
164
+ if (matchesExpandedCount < matchesExpandedByDefault && !this.#expandedResults.has(searchResult)) {
165
+ this.#expandedResults.add(searchResult);
166
+ this.#onExpandSearchResult(searchResult);
167
+ matchesExpandedCount += this.#searchMatches.get(searchResult)?.length ?? 0;
168
+ }
169
+ }
170
+ this.requestUpdate();
139
171
  }
140
172
 
141
173
  showAllMatches(): void {
142
- for (const searchResult of this.searchResults.keys()) {
143
- const startMatchIndex = this.searchMatches.get(searchResult)?.length ?? 0;
144
- this.appendSearchMatches(searchResult, startMatchIndex, searchResult.matchesCount());
174
+ for (const searchResult of this.#searchResults) {
175
+ const startMatchIndex = this.#searchMatches.get(searchResult)?.length ?? 0;
176
+ this.#appendSearchMatches(searchResult, startMatchIndex, searchResult.matchesCount());
145
177
  }
178
+ this.requestUpdate();
146
179
  }
147
180
 
148
181
  collapseAllResults(): void {
149
- for (const treeElement of this.searchResults.values()) {
150
- treeElement.collapse();
151
- }
182
+ this.#expandedResults = new WeakSet<SearchResult>();
183
+ this.requestUpdate();
152
184
  }
153
185
 
154
- private expandSearchResult(searchResult: SearchResult): void {
186
+ #onExpandSearchResult(searchResult: SearchResult): void {
155
187
  const toIndex = Math.min(searchResult.matchesCount(), matchesShownAtOnce);
156
- if (toIndex < searchResult.matchesCount()) {
157
- this.appendSearchMatches(searchResult, 0, toIndex - 1);
158
- this.appendShowMoreMatchesElement(searchResult, toIndex - 1);
159
- } else {
160
- this.appendSearchMatches(searchResult, 0, toIndex);
161
- }
162
- this.matchesExpandedCount += toIndex;
188
+ this.#appendSearchMatches(searchResult, 0, toIndex);
163
189
  this.requestUpdate();
164
190
  }
165
191
 
166
- private collapseSearchResult(searchResult: SearchResult): void {
167
- this.searchResults.get(searchResult)?.collapse();
168
- }
169
-
170
- private appendSearchMatches(searchResult: SearchResult, fromIndex: number, toIndex: number): void {
171
- const queries = this.searchConfig.queries();
192
+ #appendSearchMatches(searchResult: SearchResult, fromIndex: number, toIndex: number): void {
193
+ const queries = this.#searchConfig.queries();
172
194
  const regexes = [];
173
195
  for (let i = 0; i < queries.length; ++i) {
174
196
  regexes.push(Platform.StringUtilities.createSearchRegex(
175
- queries[i], !this.searchConfig.ignoreCase(), this.searchConfig.isRegex()));
197
+ queries[i], !this.#searchConfig.ignoreCase(), this.#searchConfig.isRegex()));
176
198
  }
177
199
 
178
- const searchMatches = this.searchMatches.get(searchResult) ?? [];
179
- this.searchMatches.set(searchResult, searchMatches);
180
- if (searchMatches.length > toIndex) {
200
+ const searchMatches = this.#searchMatches.get(searchResult) ?? [];
201
+ this.#searchMatches.set(searchResult, searchMatches);
202
+ if (searchMatches.length >= toIndex) {
181
203
  return;
182
204
  }
183
205
 
@@ -197,32 +219,32 @@ export class SearchResultsPane extends UI.Widget.VBox {
197
219
  } else {
198
220
  lineContent = lineContent.trim();
199
221
  for (let j = 0; j < regexes.length; ++j) {
200
- matchRanges = matchRanges.concat(this.regexMatchRanges(lineContent, regexes[j]));
222
+ matchRanges = matchRanges.concat(this.#regexMatchRanges(lineContent, regexes[j]));
201
223
  }
202
224
  ({lineSegment: lineContent, matchRanges} = lineSegmentForMultipleMatches(lineContent, matchRanges));
203
225
  }
204
226
 
205
227
  const resultLabel = searchResult.matchLabel(i);
206
228
  searchMatches.push({lineContent, matchRanges, resultLabel});
207
- this.appendSearchMatchElement(searchResult, searchMatches[i], i);
208
229
  }
209
230
  }
210
231
 
211
- private appendShowMoreMatchesElement(searchResult: SearchResult, startMatchIndex: number): void {
212
- const element = this.searchResults.get(searchResult);
213
- if (!element) {
214
- return;
215
- }
216
- const matchesLeftCount = searchResult.matchesCount() - startMatchIndex;
217
- const showMoreMatchesText = i18nString(UIStrings.showDMore, {PH1: matchesLeftCount});
218
- const showMoreMatchesTreeElement = new UI.TreeOutline.TreeElement(showMoreMatchesText);
219
- element.appendChild(showMoreMatchesTreeElement);
220
- showMoreMatchesTreeElement.listItemElement.classList.add('show-more-matches');
221
- showMoreMatchesTreeElement.onselect =
222
- this.showMoreMatchesElementSelected.bind(this, searchResult, showMoreMatchesTreeElement, startMatchIndex);
232
+ override performUpdate(): void {
233
+ this.#view(
234
+ {
235
+ results: this.#searchResults,
236
+ matches: this.#searchMatches,
237
+ expandedResults: this.#expandedResults,
238
+ onSelectMatch: (searchResult, matchIndex) => {
239
+ void Common.Revealer.reveal(searchResult.matchRevealable(matchIndex));
240
+ },
241
+ onExpandSearchResult: this.#onExpandSearchResult.bind(this),
242
+ onShowMoreMatches: this.#onShowMoreMatches.bind(this),
243
+ },
244
+ {}, this.contentElement);
223
245
  }
224
246
 
225
- private regexMatchRanges(lineContent: string, regex: RegExp): TextUtils.TextRange.SourceRange[] {
247
+ #regexMatchRanges(lineContent: string, regex: RegExp): TextUtils.TextRange.SourceRange[] {
226
248
  regex.lastIndex = 0;
227
249
  let match;
228
250
  const matchRanges = [];
@@ -233,13 +255,10 @@ export class SearchResultsPane extends UI.Widget.VBox {
233
255
  return matchRanges;
234
256
  }
235
257
 
236
- private showMoreMatchesElementSelected(
237
- searchResult: SearchResult, showMoreMatchesTreeElement: UI.TreeOutline.TreeElement,
238
- startMatchIndex: number): boolean {
239
- const parentElement = showMoreMatchesTreeElement.parent;
240
- parentElement?.removeChild(showMoreMatchesTreeElement);
241
- this.appendSearchMatches(searchResult, startMatchIndex, searchResult.matchesCount());
242
- return true;
258
+ #onShowMoreMatches(searchResult: SearchResult): void {
259
+ const startMatchIndex = this.#searchMatches.get(searchResult)?.length ?? 0;
260
+ this.#appendSearchMatches(searchResult, startMatchIndex, searchResult.matchesCount());
261
+ this.requestUpdate();
243
262
  }
244
263
  }
245
264
 
@@ -288,7 +288,7 @@ export class SearchView extends UI.Widget.VBox {
288
288
  // We throttle adding search results, otherwise we trigger DOM layout for each
289
289
  // result added.
290
290
  #throttler: Common.Throttler.Throttler;
291
- #pendingSearchResults: SearchResult[] = [];
291
+ #searchResults: SearchResult[] = [];
292
292
 
293
293
  constructor(settingKey: string, throttler: Common.Throttler.Throttler, view = DEFAULT_VIEW) {
294
294
  super({
@@ -439,22 +439,24 @@ export class SearchView extends UI.Widget.VBox {
439
439
  if (!this.#searchResultsPane) {
440
440
  this.#searchResultsPane = this.createSearchResultsPane();
441
441
  }
442
- this.#pendingSearchResults.push(searchResult);
443
- void this.#throttler.schedule(async () => this.#addPendingSearchResults());
442
+ this.#searchResults.push(searchResult);
443
+ void this.#throttler.schedule(async () => this.#setSearchResults());
444
444
  }
445
445
 
446
446
  protected createSearchResultsPane(): SearchResultsPane {
447
447
  return new SearchResultsPane((this.#searchConfig as Workspace.SearchConfig.SearchConfig));
448
448
  }
449
449
 
450
- #addPendingSearchResults(): void {
451
- for (const searchResult of this.#pendingSearchResults) {
450
+ #setSearchResults(): void {
451
+ this.#searchMatchesCount = 0;
452
+ this.#searchResultsCount = 0;
453
+ this.#nonEmptySearchResultsCount = 0;
454
+ for (const searchResult of this.#searchResults) {
452
455
  this.#addSearchResult(searchResult);
453
- if (searchResult.matchesCount()) {
454
- this.#searchResultsPane?.addSearchResult(searchResult);
455
- }
456
456
  }
457
- this.#pendingSearchResults = [];
457
+ if (this.#searchResultsPane) {
458
+ this.#searchResultsPane.searchResults = this.#searchResults.filter(searchResult => searchResult.matchesCount());
459
+ }
458
460
  }
459
461
 
460
462
  #onSearchFinished(searchId: number, finished: boolean): void {
@@ -503,6 +505,7 @@ export class SearchView extends UI.Widget.VBox {
503
505
  #searchStarted(): void {
504
506
  this.#searchMatchesCount = 0;
505
507
  this.#searchResultsCount = 0;
508
+ this.#searchResults = [];
506
509
  this.#nonEmptySearchResultsCount = 0;
507
510
  if (!this.#searchingView) {
508
511
  this.#searchingView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.searching), '');
@@ -31,6 +31,11 @@ li.search-result {
31
31
  white-space: pre;
32
32
  }
33
33
 
34
+ li.search-result .tree-element-title {
35
+ display: flex;
36
+ width: 100%;
37
+ }
38
+
34
39
  li.search-result:hover {
35
40
  background-color: var(--sys-color-state-hover-on-subtle);
36
41
  }
@@ -68,6 +73,10 @@ li.search-match {
68
73
  white-space: pre;
69
74
  }
70
75
 
76
+ li.search-match .tree-element-title {
77
+ display: flex;
78
+ }
79
+
71
80
  li.search-match.selected:focus-visible {
72
81
  background: var(--sys-color-tonal-container);
73
82
  }
@@ -186,8 +186,9 @@ export class CookieControlsView extends UI.Widget.VBox {
186
186
  <devtools-switch
187
187
  .checked=${Boolean(toggleEnabledSetting.get())}
188
188
  .disabled=${Boolean(enterpriseEnabledSetting.get())}
189
+ .label=${'Temporarily limit third-party cookies, only when DevTools is open'}
190
+ data-testid="cookie-control-override"
189
191
  @switchchange=${()=>{input.inputChanged(!toggleEnabledSetting.get(), toggleEnabledSetting);}}
190
- aria-label="Temporarily limit third-party cookies, only when DevTools is open"
191
192
  jslog=${VisualLogging.toggle(toggleEnabledSetting.name).track({click: true})}
192
193
  >
193
194
  </devtools-switch>
@@ -381,8 +381,10 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen
381
381
  text: noLogging ? i18nString(UIStrings.codeSuggestionsSendDataNoLogging) :
382
382
  i18nString(UIStrings.codeSuggestionsSendData)
383
383
  }],
384
- // TODO: Add a relevant link
385
- learnMoreLink: {url: '', linkJSLogContext: 'learn-more.code-completion'},
384
+ learnMoreLink: {
385
+ url: ' https://developers.chrome.com/docs/devtools/ai-assistance/code-completion',
386
+ linkJSLogContext: 'learn-more.code-completion'
387
+ },
386
388
  settingExpandState: {
387
389
  isSettingExpanded: false,
388
390
  expandSettingJSLogContext: 'code-completion.accordion',
@@ -590,8 +592,9 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen
590
592
  .checked=${Boolean(setting.get()) && !isDisabled}
591
593
  .jslogContext=${setting.name || ''}
592
594
  .disabled=${isDisabled}
595
+ .label=${disabledReasonsJoined || settingData.enableSettingText}
596
+ data-testid=${settingData.enableSettingText}
593
597
  @switchchange=${this.#toggleSetting.bind(this, setting)}
594
- aria-label=${disabledReasonsJoined || settingData.enableSettingText}
595
598
  ></devtools-switch>
596
599
  </div>
597
600
  <div class=${classMap(detailsClasses)}>
@@ -12,6 +12,7 @@ import * as Host from '../../../core/host/host.js';
12
12
  import * as i18n from '../../../core/i18n/i18n.js';
13
13
  import type * as Platform from '../../../core/platform/platform.js';
14
14
  import * as Root from '../../../core/root/root.js';
15
+ import * as SDK from '../../../core/sdk/sdk.js';
15
16
  import * as Badges from '../../../models/badges/badges.js';
16
17
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
17
18
  import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
@@ -252,16 +253,29 @@ function renderWarningIfNeeded(syncInfo: Host.InspectorFrontendHostAPI.SyncInfor
252
253
  'chrome://settings/syncSetup/advanced' as Platform.DevToolsPath.UrlString;
253
254
  const warningText =
254
255
  !syncInfo.isSyncActive ? i18nString(UIStrings.syncDisabled) : i18nString(UIStrings.preferencesSyncDisabled);
256
+ const handleClick = (event: Event): void => {
257
+ const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();
258
+ if (rootTarget === null) {
259
+ return;
260
+ }
261
+
262
+ void rootTarget.targetAgent().invoke_createTarget({url: warningLink}).then(result => {
263
+ if (result.getError()) {
264
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(warningLink);
265
+ }
266
+ });
267
+ event.consume();
268
+ };
255
269
  // clang-format off
256
270
  return html`
257
- <devtools-chrome-link .href=${warningLink}>
258
- <devtools-button
259
- aria-describedby=settings-sync-info
260
- .iconName=${'info'}
261
- .variant=${Buttons.Button.Variant.ICON}
262
- .size=${Buttons.Button.Size.SMALL}>
263
- </devtools-button>
264
- </devtools-chrome-link>
271
+ <devtools-button
272
+ aria-describedby=settings-sync-info
273
+ aria-label=${warningText}
274
+ .iconName=${'info'}
275
+ .variant=${Buttons.Button.Variant.ICON}
276
+ .size=${Buttons.Button.Size.SMALL}
277
+ @click=${handleClick}>
278
+ </devtools-button>
265
279
  <devtools-tooltip
266
280
  id=settings-sync-info
267
281
  variant=simple>
@@ -315,7 +329,7 @@ function renderGdpSectionIfNeeded({
315
329
  // clang-format off
316
330
  return html`
317
331
  <div class="gdp-profile-header">
318
- <div class="gdp-logo" role="img" tabindex="0" aria-label="Google Developer Program"></div>
332
+ <div class="gdp-logo" role="img" aria-label="Google Developer Program"></div>
319
333
  </div>
320
334
  `;
321
335
  // clang-format on
@@ -585,7 +585,7 @@ export class UserAgentClientHintsForm extends HTMLElement {
585
585
  ${i18nString(UIStrings.mobileCheckboxLabel)}
586
586
  </label>
587
587
  ` :
588
- html``;
588
+ Lit.nothing;
589
589
  return html`
590
590
  <span class="full-row label">${i18nString(UIStrings.deviceModel)}</span>
591
591
  <div class="full-row brand-row" aria-label=${i18nString(UIStrings.deviceProperties)} role="group">
@@ -59,6 +59,9 @@ export class AiCodeCompletionPlugin extends Plugin {
59
59
  if (showTeaser) {
60
60
  this.#teaser = new PanelCommon.AiCodeCompletionTeaser({onDetach: this.#detachAiCodeCompletionTeaser.bind(this)});
61
61
  }
62
+
63
+ this.#aiCodeCompletionDisclaimerContainer.classList.add('ai-code-completion-disclaimer-container');
64
+ this.#aiCodeCompletionDisclaimerContainer.style.paddingInline = 'var(--sys-size-3)';
62
65
  }
63
66
 
64
67
  static override accepts(uiSourceCode: Workspace.UISourceCode.UISourceCode): boolean {
@@ -1197,7 +1197,7 @@ export class SourcesPanel extends UI.Panel.Panel implements
1197
1197
  } else if (position === 'bottom') {
1198
1198
  vertically = true;
1199
1199
  } else {
1200
- vertically = UI.InspectorView.InspectorView.instance().element.offsetWidth < 680;
1200
+ vertically = this.splitWidget.element.offsetWidth < 680;
1201
1201
  }
1202
1202
 
1203
1203
  if (this.sidebarPaneView && vertically === !this.splitWidget.isVertical()) {
@@ -14,11 +14,16 @@
14
14
 
15
15
  #sources-panel-sources-view .sources-toolbar {
16
16
  display: flex;
17
- flex: 0 0 27px;
17
+ flex: 0 0 auto;
18
18
  background-color: var(--sys-color-cdt-base-container);
19
19
  border-top: 1px solid var(--sys-color-divider);
20
20
  overflow: hidden;
21
21
  z-index: 0;
22
+ align-items: flex-end;
23
+
24
+ devtools-toolbar:first-of-type {
25
+ flex-wrap: wrap;
26
+ }
22
27
  }
23
28
 
24
29
  .source-frame-debugger-script {
@@ -158,7 +158,7 @@ export class LayoutShiftDetails extends UI.Widget.Widget {
158
158
  export const DEFAULT_VIEW: (input: ViewInput, output: object, target: HTMLElement) => void =
159
159
  (input, _output, target) => {
160
160
  if (!input.event || !input.parsedTrace) {
161
- render(html``, target);
161
+ render(Lit.nothing, target);
162
162
  return;
163
163
  }
164
164
 
@@ -197,7 +197,7 @@ export interface ViewInput {
197
197
  export const DEFAULT_VIEW: (
198
198
  input: ViewInput, output: object, target: HTMLElement) => void = (input, _output, target) => {
199
199
  if (!input.request) {
200
- render(html``, target);
200
+ render(Lit.nothing, target);
201
201
  return;
202
202
  }
203
203
  const {request} = input;
@@ -86,7 +86,7 @@ export const DEFAULT_VIEW: (input: ViewInput, output: object, target: HTMLElemen
86
86
  const {activeEvent, eventToInsightsMap} = input;
87
87
  const relatedInsights = activeEvent ? eventToInsightsMap.get(activeEvent) ?? [] : [];
88
88
  if (!activeEvent || eventToInsightsMap.size === 0 || relatedInsights.length === 0) {
89
- render(html``, target);
89
+ render(Lit.nothing, target);
90
90
  return;
91
91
  }
92
92
 
@@ -478,7 +478,7 @@ export class SidebarSingleInsightSet extends HTMLElement {
478
478
  insightSetKey,
479
479
  } = this.#data;
480
480
  if (!parsedTrace?.insights || !insightSetKey) {
481
- Lit.render(html``, this.#shadow, {host: this});
481
+ Lit.render(Lit.nothing, this.#shadow, {host: this});
482
482
  return;
483
483
  }
484
484
 
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://source.chromium.org/chromium/chromium/src/+/main:components/variations/proto/devtools/
3
3
  Version: N/A
4
- Revision: 8b6a2b940e6b293e99d648cdf34f8d26ae731d64
4
+ Revision: 0b46aaf7af942d8ed35500074840aba1ef6d6303
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -1,10 +1,10 @@
1
1
  Name: Puppeteer Core
2
2
  Short Name: Puppeteer Core
3
3
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
4
- Version: 24.22.0
4
+ Version: 24.22.1
5
5
  License: Apache-2.0
6
6
  License File: LICENSE
7
- Revision: 0e2affad10d4e4e19ef07504d9b8784b3da9ff91
7
+ Revision: 6480e2548977ea43c962cb8043357cfb6524e50c
8
8
  Security Critical: no
9
9
  Shipped: yes
10
10
  Update Mechanism: Autoroll