chrome-devtools-frontend 1.0.1521880 → 1.0.1522585
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.
- package/docs/ui_engineering.md +76 -0
- package/front_end/core/host/GdpClient.ts +116 -66
- package/front_end/core/root/Runtime.ts +1 -0
- package/front_end/core/sdk/EnhancedTracesParser.ts +13 -6
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +82 -32
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +7 -1
- package/front_end/generated/Deprecation.ts +4 -4
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +10 -6
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +559 -0
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +42 -4
- package/front_end/models/badges/UserBadges.ts +14 -16
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/trace/LanternComputationData.ts +1 -0
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +10 -0
- package/front_end/models/trace/insights/DocumentLatency.ts +9 -10
- package/front_end/models/trace/types/TraceEvents.ts +6 -5
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -2
- package/front_end/panels/application/IndexedDBViews.ts +1 -0
- package/front_end/panels/application/ReportingApiTreeElement.ts +1 -2
- package/front_end/panels/application/ReportingApiView.ts +18 -20
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +3 -0
- package/front_end/panels/application/components/EndpointsGrid.ts +51 -59
- package/front_end/panels/application/components/ReportsGrid.ts +86 -107
- package/front_end/panels/application/components/StorageMetadataView.ts +30 -4
- package/front_end/panels/application/components/endpointsGrid.css +30 -0
- package/front_end/panels/application/components/reportsGrid.css +34 -0
- package/front_end/panels/application/components/storageMetadataView.css +9 -0
- package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +19 -27
- package/front_end/panels/common/BadgeNotification.ts +10 -3
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +31 -32
- package/front_end/panels/search/SearchResultsPane.ts +14 -13
- package/front_end/panels/search/SearchView.ts +3 -20
- package/front_end/panels/settings/components/SyncSection.ts +8 -6
- package/front_end/panels/sources/SearchSourcesView.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartView.ts +17 -0
- package/front_end/panels/timeline/TimelinePanel.ts +5 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +12 -3
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +21 -9
- package/front_end/panels/timeline/timelineDetailsView.css +5 -0
- package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -11
- package/front_end/panels/whats_new/resources/WNDT.md +9 -6
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/diff/README.chromium +0 -1
- package/front_end/ui/components/tooltips/Tooltip.ts +13 -4
- package/front_end/ui/legacy/Treeoutline.ts +6 -9
- package/front_end/ui/legacy/UIUtils.ts +4 -17
- package/front_end/ui/legacy/Widget.ts +0 -5
- package/front_end/ui/legacy/XElement.ts +0 -33
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
- package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +38 -21
- package/front_end/ui/legacy/components/perf_ui/filmStripView.css +29 -0
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +3 -2
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/panels/application/components/reportingApiGrid.css +0 -31
- package/front_end/ui/legacy/XWidget.ts +0 -133
@@ -52,23 +52,24 @@ export type View = (input: ViewInput, output: unknown, target: HTMLElement) => v
|
|
52
52
|
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
53
53
|
const {results, matches, expandedResults, onSelectMatch, onExpandSearchResult, onShowMoreMatches} = input;
|
54
54
|
|
55
|
-
const onExpand =
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
};
|
55
|
+
const onExpand =
|
56
|
+
(searchResult: SearchResult, {detail: {expanded}}: UI.TreeOutline.TreeViewElement.ExpandEvent): void => {
|
57
|
+
if (expanded) {
|
58
|
+
expandedResults.add(searchResult);
|
59
|
+
onExpandSearchResult(searchResult);
|
60
|
+
} else {
|
61
|
+
expandedResults.delete(searchResult);
|
62
|
+
}
|
63
|
+
};
|
65
64
|
|
66
65
|
// clang-format off
|
67
66
|
render(html`
|
68
|
-
<devtools-tree hide-overflow
|
67
|
+
<devtools-tree hide-overflow .template=${html`
|
69
68
|
<ul role="tree">
|
70
|
-
${results.map(
|
71
|
-
<li
|
69
|
+
${results.map(searchResult => html`
|
70
|
+
<li @expand=${(e: UI.TreeOutline.TreeViewElement.ExpandEvent) => onExpand(searchResult, e)}
|
71
|
+
role="treeitem"
|
72
|
+
class="search-result">
|
72
73
|
<style>${searchResultsPaneStyles}</style>
|
73
74
|
${renderSearchResult(searchResult)}
|
74
75
|
<ul role="group" ?hidden=${!expandedResults.has(searchResult)}>
|
@@ -293,12 +293,9 @@ export class SearchView extends UI.Widget.VBox {
|
|
293
293
|
}>;
|
294
294
|
#searchScope: SearchScope|null;
|
295
295
|
|
296
|
-
// We throttle adding search results, otherwise we trigger DOM layout for each
|
297
|
-
// result added.
|
298
|
-
#throttler: Common.Throttler.Throttler;
|
299
296
|
#searchResults: SearchResult[] = [];
|
300
297
|
|
301
|
-
constructor(settingKey: string,
|
298
|
+
constructor(settingKey: string, view = DEFAULT_VIEW) {
|
302
299
|
super({
|
303
300
|
jslog: `${VisualLogging.panel('search').track({resize: true})}`,
|
304
301
|
useShadowDom: true,
|
@@ -316,7 +313,6 @@ export class SearchView extends UI.Widget.VBox {
|
|
316
313
|
this.#searchConfig = null;
|
317
314
|
this.#pendingSearchConfig = null;
|
318
315
|
this.#progress = null;
|
319
|
-
this.#throttler = throttler;
|
320
316
|
|
321
317
|
this.#advancedSearchConfig = Common.Settings.Settings.instance().createLocalSetting(
|
322
318
|
settingKey + '-search-config', new Workspace.SearchConfig.SearchConfig('', true, false).toPlainObject());
|
@@ -451,17 +447,8 @@ export class SearchView extends UI.Widget.VBox {
|
|
451
447
|
return;
|
452
448
|
}
|
453
449
|
this.#searchResults.push(searchResult);
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
#setSearchResults(): void {
|
458
|
-
this.#searchMatchesCount = 0;
|
459
|
-
this.#searchResultsCount = 0;
|
460
|
-
this.#nonEmptySearchResultsCount = 0;
|
461
|
-
for (const searchResult of this.#searchResults) {
|
462
|
-
this.#addSearchResult(searchResult);
|
463
|
-
}
|
464
|
-
this.performUpdate();
|
450
|
+
this.#addSearchResult(searchResult);
|
451
|
+
this.requestUpdate();
|
465
452
|
}
|
466
453
|
|
467
454
|
#onSearchFinished(searchId: number, finished: boolean): void {
|
@@ -640,8 +627,4 @@ export class SearchView extends UI.Widget.VBox {
|
|
640
627
|
this.#resetSearch();
|
641
628
|
this.#onClearSearchInput();
|
642
629
|
}
|
643
|
-
|
644
|
-
get throttlerForTest(): Common.Throttler.Throttler {
|
645
|
-
return this.#throttler;
|
646
|
-
}
|
647
630
|
}
|
@@ -11,7 +11,6 @@ import type * as Common from '../../../core/common/common.js';
|
|
11
11
|
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
|
-
import * as Root from '../../../core/root/root.js';
|
15
14
|
import * as SDK from '../../../core/sdk/sdk.js';
|
16
15
|
import * as Badges from '../../../models/badges/badges.js';
|
17
16
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
@@ -206,8 +205,13 @@ export class SyncSection extends HTMLElement {
|
|
206
205
|
return;
|
207
206
|
}
|
208
207
|
|
209
|
-
|
210
|
-
|
208
|
+
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
209
|
+
if (!getProfileResponse) {
|
210
|
+
return;
|
211
|
+
}
|
212
|
+
|
213
|
+
this.#gdpProfile = getProfileResponse.profile ?? undefined;
|
214
|
+
this.#isEligibleToCreateGdpProfile = getProfileResponse.isEligible;
|
211
215
|
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
|
212
216
|
}
|
213
217
|
}
|
@@ -310,9 +314,7 @@ function renderGdpSectionIfNeeded({
|
|
310
314
|
if (!Host.GdpClient.isGdpProfilesAvailable() || (!gdpProfile && !isEligibleToCreateProfile)) {
|
311
315
|
return Lit.nothing;
|
312
316
|
}
|
313
|
-
const hasReceiveBadgesCheckbox =
|
314
|
-
Host.GdpClient.getGdpProfilesEnterprisePolicy() === Root.Runtime.GdpProfilesEnterprisePolicyValue.ENABLED;
|
315
|
-
|
317
|
+
const hasReceiveBadgesCheckbox = Host.GdpClient.isBadgesEnabled() && receiveBadgesSetting;
|
316
318
|
function renderBrand(): Lit.LitTemplate {
|
317
319
|
// clang-format off
|
318
320
|
return html`
|
@@ -17,7 +17,7 @@ export class SearchSources {
|
|
17
17
|
|
18
18
|
export class SearchSourcesView extends Search.SearchView.SearchView {
|
19
19
|
constructor() {
|
20
|
-
super('sources'
|
20
|
+
super('sources');
|
21
21
|
}
|
22
22
|
|
23
23
|
override createScope(): Search.SearchScope.SearchScope {
|
@@ -1430,6 +1430,23 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
|
|
1430
1430
|
}
|
1431
1431
|
}
|
1432
1432
|
|
1433
|
+
zoomEvent(event: Trace.Types.Events.Event): void {
|
1434
|
+
const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds;
|
1435
|
+
if (!traceBounds) {
|
1436
|
+
return;
|
1437
|
+
}
|
1438
|
+
|
1439
|
+
this.#expandEntryTrack(event);
|
1440
|
+
this.revealEventVertically(event);
|
1441
|
+
const entryWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(
|
1442
|
+
event.ts,
|
1443
|
+
Trace.Types.Timing.Micro(event.ts + (event.dur ?? 0)),
|
1444
|
+
);
|
1445
|
+
const expandedBounds = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(entryWindow, traceBounds, 100);
|
1446
|
+
TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(
|
1447
|
+
expandedBounds, {ignoreMiniMapBounds: true, shouldAnimate: true});
|
1448
|
+
}
|
1449
|
+
|
1433
1450
|
revealEvent(event: Trace.Types.Events.Event): void {
|
1434
1451
|
const mainIndex = this.mainDataProvider.indexForEvent(event);
|
1435
1452
|
const networkIndex = this.networkDataProvider.indexForEvent(event);
|
@@ -660,6 +660,10 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
660
660
|
);
|
661
661
|
}
|
662
662
|
|
663
|
+
zoomEvent(event: Trace.Types.Events.Event): void {
|
664
|
+
this.flameChart.zoomEvent(event);
|
665
|
+
}
|
666
|
+
|
663
667
|
/**
|
664
668
|
* Activates an insight and ensures the sidebar is open too.
|
665
669
|
* Pass `highlightInsight: true` to flash the insight with the background highlight colour.
|
@@ -3156,6 +3160,7 @@ export const rowHeight = 18;
|
|
3156
3160
|
export const headerHeight = 20;
|
3157
3161
|
export interface TimelineModeViewDelegate {
|
3158
3162
|
select(selection: TimelineSelection|null): void;
|
3163
|
+
zoomEvent(event: Trace.Types.Events.Event): void;
|
3159
3164
|
element: Element;
|
3160
3165
|
set3PCheckboxDisabled(disabled: boolean): void;
|
3161
3166
|
selectEntryAtTime(events: Trace.Types.Events.Event[]|null, time: number): void;
|
@@ -967,7 +967,7 @@ export class TimelineUIUtils {
|
|
967
967
|
const isMarker = parsedTrace && isMarkerEvent(parsedTrace, event);
|
968
968
|
const color = isMarker ? TimelineUIUtils.markerStyleForEvent(event).color : defaultColorForEvent;
|
969
969
|
|
970
|
-
contentHelper.addSection(TimelineUIUtils.eventTitle(event), color);
|
970
|
+
contentHelper.addSection(TimelineUIUtils.eventTitle(event), color, event);
|
971
971
|
|
972
972
|
// TODO: as part of the removal of the old engine, produce a typesafe way
|
973
973
|
// to look up args and data for events.
|
@@ -2374,7 +2374,7 @@ export class TimelineDetailsContentHelper {
|
|
2374
2374
|
this.fragment.appendChild(this.element);
|
2375
2375
|
}
|
2376
2376
|
|
2377
|
-
addSection(title: string, swatchColor?: string): void {
|
2377
|
+
addSection(title: string, swatchColor?: string, event?: Trace.Types.Events.Event): void {
|
2378
2378
|
if (!this.tableElement.hasChildNodes()) {
|
2379
2379
|
this.element.removeChildren();
|
2380
2380
|
} else {
|
@@ -2388,7 +2388,16 @@ export class TimelineDetailsContentHelper {
|
|
2388
2388
|
if (swatchColor) {
|
2389
2389
|
titleElement.createChild('div').style.backgroundColor = swatchColor;
|
2390
2390
|
}
|
2391
|
-
|
2391
|
+
|
2392
|
+
const textChild = titleElement.createChild('span');
|
2393
|
+
textChild.textContent = title;
|
2394
|
+
|
2395
|
+
if (event) {
|
2396
|
+
textChild.classList.add('timeline-details-chip-title-reveal-entry');
|
2397
|
+
textChild.addEventListener('click', function() {
|
2398
|
+
TimelinePanel.instance().zoomEvent(event);
|
2399
|
+
});
|
2400
|
+
}
|
2392
2401
|
}
|
2393
2402
|
|
2394
2403
|
this.tableElement = this.element.createChild('div', 'vbox timeline-details-chip-body');
|
@@ -49,10 +49,6 @@ const UIStrings = {
|
|
49
49
|
* @description Text for the save trace button
|
50
50
|
*/
|
51
51
|
saveButtonTitle: 'Save',
|
52
|
-
/**
|
53
|
-
* @description Title for the information icon showing more information about an option
|
54
|
-
*/
|
55
|
-
moreInfoTitle: 'More information',
|
56
52
|
/**
|
57
53
|
* @description Text shown in the information pop-up next to the "Include script content" option.
|
58
54
|
*/
|
@@ -60,7 +56,11 @@ const UIStrings = {
|
|
60
56
|
/**
|
61
57
|
* @description Text shown in the information pop-up next to the "Include script sourcemaps" option.
|
62
58
|
*/
|
63
|
-
sourceMapsContentPrivacyInfo: 'Includes available source maps, which may expose authored code.'
|
59
|
+
sourceMapsContentPrivacyInfo: 'Includes available source maps, which may expose authored code.',
|
60
|
+
/**
|
61
|
+
* @description Text used as the start of the accessible label for the information button which shows additional context when the user focuses / hovers.
|
62
|
+
*/
|
63
|
+
moreInfoLabel: 'Additional information:',
|
64
64
|
} as const;
|
65
65
|
|
66
66
|
const str_ = i18n.i18n.registerUIStrings('panels/timeline/components/ExportTraceOptions.ts', UIStrings);
|
@@ -204,6 +204,17 @@ export class ExportTraceOptions extends HTMLElement {
|
|
204
204
|
this.state = newState;
|
205
205
|
}
|
206
206
|
|
207
|
+
#accessibleLabelForInfoCheckbox(checkboxId: CheckboxId): string {
|
208
|
+
if (checkboxId === 'script-source-maps') {
|
209
|
+
return i18nString(UIStrings.moreInfoLabel) + ' ' + i18nString(UIStrings.sourceMapsContentPrivacyInfo);
|
210
|
+
}
|
211
|
+
|
212
|
+
if (checkboxId === 'script-content') {
|
213
|
+
return i18nString(UIStrings.moreInfoLabel) + ' ' + i18nString(UIStrings.scriptContentPrivacyInfo);
|
214
|
+
}
|
215
|
+
|
216
|
+
return '';
|
217
|
+
}
|
207
218
|
#renderCheckbox(
|
208
219
|
checkboxId: CheckboxId, checkboxWithLabel: UI.UIUtils.CheckboxLabel, title: Common.UIString.LocalizedString,
|
209
220
|
checked: boolean): Lit.TemplateResult {
|
@@ -224,8 +235,8 @@ export class ExportTraceOptions extends HTMLElement {
|
|
224
235
|
${checkboxesWithInfoDialog.has(checkboxId) ? html`
|
225
236
|
<devtools-button
|
226
237
|
aria-details=${`export-trace-tooltip-${checkboxId}`}
|
238
|
+
aria-label=${this.#accessibleLabelForInfoCheckbox(checkboxId)}
|
227
239
|
class="pen-icon"
|
228
|
-
.title=${UIStrings.moreInfoTitle}
|
229
240
|
.iconName=${'info'}
|
230
241
|
.variant=${Buttons.Button.Variant.ICON}
|
231
242
|
></devtools-button>
|
@@ -275,8 +286,10 @@ export class ExportTraceOptions extends HTMLElement {
|
|
275
286
|
closeButton: false,
|
276
287
|
dialogTitle: i18nString(UIStrings.exportTraceOptionsDialogTitle),
|
277
288
|
state: this.#state.dialogState,
|
289
|
+
closeOnESC: true,
|
278
290
|
} as Dialogs.ButtonDialog.ButtonDialogData}>
|
279
291
|
<div class='export-trace-options-content'>
|
292
|
+
|
280
293
|
${this.#state.displayAnnotationsCheckbox ? this.#renderCheckbox('annotations', this.#includeAnnotationsCheckbox,
|
281
294
|
i18nString(UIStrings.includeAnnotations),
|
282
295
|
this.#state.includeAnnotations): ''}
|
@@ -296,11 +309,10 @@ export class ExportTraceOptions extends HTMLElement {
|
|
296
309
|
} as Buttons.Button.ButtonData}
|
297
310
|
>${i18nString(UIStrings.saveButtonTitle)}</devtools-button>
|
298
311
|
</div>
|
312
|
+
${this.#state.displayScriptContentCheckbox ? this.#renderInfoTooltip('script-content') : Lit.nothing}
|
313
|
+
${this.#state.displayScriptContentCheckbox && this.#state.displaySourceMapsCheckbox ? this.#renderInfoTooltip('script-source-maps') : Lit.nothing}
|
299
314
|
</div>
|
300
315
|
</devtools-button-dialog>
|
301
|
-
|
302
|
-
${this.#state.displayScriptContentCheckbox ? this.#renderInfoTooltip('script-content') : Lit.nothing}
|
303
|
-
${this.#state.displayScriptContentCheckbox && this.#state.displaySourceMapsCheckbox ? this.#renderInfoTooltip('script-source-maps') : Lit.nothing}
|
304
316
|
`;
|
305
317
|
// clang-format on
|
306
318
|
Lit.render(output, this.#shadow, {host: this});
|
@@ -47,6 +47,11 @@
|
|
47
47
|
align-items: center;
|
48
48
|
}
|
49
49
|
|
50
|
+
.timeline-details-chip-title-reveal-entry:hover {
|
51
|
+
background: var(--sys-color-state-hover-on-subtle);
|
52
|
+
cursor: pointer;
|
53
|
+
}
|
54
|
+
|
50
55
|
.timeline-details-view-block:first-child > .timeline-details-chip-title {
|
51
56
|
font-size: 13px;
|
52
57
|
}
|
@@ -40,28 +40,32 @@ export function getReleaseNote(): ReleaseNote {
|
|
40
40
|
}
|
41
41
|
|
42
42
|
let releaseNote: ReleaseNote = {
|
43
|
-
version:
|
44
|
-
header: 'What\'s new in DevTools
|
43
|
+
version: 83,
|
44
|
+
header: 'What\'s new in DevTools 142',
|
45
45
|
markdownLinks: [
|
46
46
|
{
|
47
|
-
key: 'ai-
|
48
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
47
|
+
key: 'perf-ai-agent',
|
48
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#perf-ai-agent',
|
49
49
|
},
|
50
50
|
{
|
51
|
-
key: 'ai-
|
52
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
51
|
+
key: 'ai-code-completion',
|
52
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#ai-code-completion',
|
53
53
|
},
|
54
54
|
{
|
55
|
-
key: '
|
56
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
55
|
+
key: 'gdp',
|
56
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#gdp',
|
57
|
+
},
|
58
|
+
{
|
59
|
+
key: 'ai-main-button',
|
60
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/#ai-main-button',
|
57
61
|
},
|
58
62
|
],
|
59
63
|
videoLinks: [
|
60
64
|
{
|
61
|
-
description: 'See past highlights from Chrome
|
62
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
65
|
+
description: 'See past highlights from Chrome 141',
|
66
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-141' as Platform.DevToolsPath.UrlString,
|
63
67
|
type: VideoType.WHATS_NEW,
|
64
68
|
},
|
65
69
|
],
|
66
|
-
link: 'https://developer.chrome.com/blog/new-in-devtools-
|
70
|
+
link: 'https://developer.chrome.com/blog/new-in-devtools-142/',
|
67
71
|
};
|
@@ -1,8 +1,11 @@
|
|
1
|
-
### [
|
2
|
-
|
1
|
+
### [Full stack trace AI agent in Performance panel](perf-ai-agent)
|
2
|
+
The Performance panel now integrates a more capable AI agent that has full access to the stack trace.
|
3
3
|
|
4
|
-
### [
|
5
|
-
|
4
|
+
### [AI code completion in Sources and Console](ai-code-completion)
|
5
|
+
Code completion powered by AI is now available in the Sources panel and the Console.
|
6
6
|
|
7
|
-
### [
|
8
|
-
|
7
|
+
### [Google Developer Program support](gdp)
|
8
|
+
The Google Developer Program, a ready-made subscription and community platform, is now in DevTools, offering a more personalized experience, a badge system, and easier discovery of new features.
|
9
|
+
|
10
|
+
### [One main 'Debug with AI' button](ai-main-button)
|
11
|
+
The primary action bar at the top of DevTools now features the primary "Debug with AI" button which opens the 'AI assistance' panel in a right-hand side bar.
|
@@ -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:
|
4
|
+
Revision: c7c3037a902ef52ab055674cd106721ea54d13d1
|
5
5
|
Update Mechanism: Manual (https://crbug.com/428069060)
|
6
6
|
License: BSD-3-Clause
|
7
7
|
License File: LICENSE
|
@@ -3,7 +3,6 @@ Short Name: diff-match-patch
|
|
3
3
|
URL: https://github.com/google/diff-match-patch/tree/master/javascript
|
4
4
|
Version: 5.60.0
|
5
5
|
Revision: 0ae308daa77aeddb089cd6b7b0a443fca026266e
|
6
|
-
Update Mechanism: Manual
|
7
6
|
License: Apache-2.0
|
8
7
|
License File: LICENSE
|
9
8
|
Update Mechanism: Static.HardFork (https://crbug.com/422918273)
|
@@ -480,7 +480,13 @@ export class Tooltip extends HTMLElement {
|
|
480
480
|
};
|
481
481
|
|
482
482
|
#keyDown = (event: KeyboardEvent): void => {
|
483
|
-
|
483
|
+
// There are two scenarios when we care about keydown:
|
484
|
+
// 1. The tooltip is open, and the user presses ESC
|
485
|
+
// 2. "use-hotkey" is set, and the user presses Alt+ArrowDown.
|
486
|
+
const shouldToggleVisibility =
|
487
|
+
(event.key === 'Escape' && this.open) || (this.useHotkey && event.altKey && event.key === 'ArrowDown');
|
488
|
+
|
489
|
+
if (shouldToggleVisibility) {
|
484
490
|
this.#openedViaHotkey = !this.open;
|
485
491
|
this.toggle();
|
486
492
|
event.consume(true);
|
@@ -489,15 +495,18 @@ export class Tooltip extends HTMLElement {
|
|
489
495
|
|
490
496
|
#registerEventListeners(): void {
|
491
497
|
if (this.#anchor) {
|
498
|
+
// We bind the keydown listener regardless of if use-hotkey is enabled
|
499
|
+
// as we always want to support ESC to close.
|
500
|
+
this.#anchor.addEventListener('keydown', this.#keyDown);
|
501
|
+
|
492
502
|
if (this.useClick) {
|
493
503
|
this.#anchor.addEventListener('click', this.toggle);
|
494
504
|
} else {
|
495
505
|
this.#anchor.addEventListener('mouseenter', this.showTooltip);
|
496
|
-
if (this.useHotkey) {
|
497
|
-
this.#anchor.addEventListener('keydown', this.#keyDown);
|
498
|
-
} else {
|
506
|
+
if (!this.useHotkey) {
|
499
507
|
this.#anchor.addEventListener('focus', this.showTooltip);
|
500
508
|
}
|
509
|
+
|
501
510
|
this.#anchor.addEventListener('blur', this.hideTooltip);
|
502
511
|
this.#anchor.addEventListener('mouseleave', this.hideTooltip);
|
503
512
|
this.addEventListener('mouseleave', this.hideTooltip);
|
@@ -1637,7 +1637,7 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1637
1637
|
* <devtools-tree
|
1638
1638
|
* .template=${html`
|
1639
1639
|
* <ul role="tree">
|
1640
|
-
* <li role="treeitem">
|
1640
|
+
* <li role="treeitem" @expand=${onExpand}>
|
1641
1641
|
* Tree Node Text
|
1642
1642
|
* <ul role="group">
|
1643
1643
|
* Node with subtree
|
@@ -1659,7 +1659,7 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1659
1659
|
* tree node). If a tree node contains a <ul role="group">, that defines a subtree under that tree node. The `hidden`
|
1660
1660
|
* attribute on the <ul> defines whether that subtree should render as collapsed. Note that node expanding/collapsing do
|
1661
1661
|
* not reflect this state back to the attribute on the config element, those state changes are rather sent out as
|
1662
|
-
* `expand` events.
|
1662
|
+
* `expand` events on the config element.
|
1663
1663
|
*
|
1664
1664
|
* Under the hood this uses TreeOutline.
|
1665
1665
|
*
|
@@ -1687,7 +1687,6 @@ function getTreeNodes(nodeList: NodeList|Node[]): HTMLLIElement[] {
|
|
1687
1687
|
*
|
1688
1688
|
* @property template Define the tree contents
|
1689
1689
|
* @event selected A node was selected
|
1690
|
-
* @event expand A subtree was expanded or collapsed
|
1691
1690
|
* @attribute navigation-variant Turn this tree into the navigation variant
|
1692
1691
|
* @attribute hide-overflow
|
1693
1692
|
*/
|
@@ -1704,14 +1703,12 @@ export class TreeViewElement extends HTMLElementWithLightDOMTemplate {
|
|
1704
1703
|
});
|
1705
1704
|
this.#treeOutline.addEventListener(Events.ElementExpanded, event => {
|
1706
1705
|
if (event.data instanceof TreeViewTreeElement) {
|
1707
|
-
|
1708
|
-
{expanded: true, target: (event.data as TreeViewTreeElement).configElement}));
|
1706
|
+
event.data.listItemElement.dispatchEvent(new TreeViewElement.ExpandEvent({expanded: true}));
|
1709
1707
|
}
|
1710
1708
|
});
|
1711
1709
|
this.#treeOutline.addEventListener(Events.ElementCollapsed, event => {
|
1712
1710
|
if (event.data instanceof TreeViewTreeElement) {
|
1713
|
-
|
1714
|
-
{expanded: false, target: (event.data as TreeViewTreeElement).configElement}));
|
1711
|
+
event.data.listItemElement.dispatchEvent(new TreeViewElement.ExpandEvent({expanded: false}));
|
1715
1712
|
}
|
1716
1713
|
});
|
1717
1714
|
this.addNodes(getTreeNodes([this]));
|
@@ -1832,8 +1829,8 @@ export namespace TreeViewElement {
|
|
1832
1829
|
}
|
1833
1830
|
}
|
1834
1831
|
|
1835
|
-
export class ExpandEvent extends CustomEvent<{expanded: boolean
|
1836
|
-
constructor(detail: {expanded: boolean
|
1832
|
+
export class ExpandEvent extends CustomEvent<{expanded: boolean}> {
|
1833
|
+
constructor(detail: {expanded: boolean}) {
|
1837
1834
|
super('expand', {detail});
|
1838
1835
|
}
|
1839
1836
|
}
|
@@ -62,7 +62,6 @@ import smallBubbleStyles from './smallBubble.css.js';
|
|
62
62
|
import type {ToolbarButton} from './Toolbar.js';
|
63
63
|
import {Tooltip} from './Tooltip.js';
|
64
64
|
import {Widget} from './Widget.js';
|
65
|
-
import type {XWidget} from './XWidget.js';
|
66
65
|
|
67
66
|
declare global {
|
68
67
|
interface HTMLElementTagNameMap {
|
@@ -1935,27 +1934,11 @@ function updateWidgetfocusWidgetForNode(node: Node|null): void {
|
|
1935
1934
|
}
|
1936
1935
|
}
|
1937
1936
|
|
1938
|
-
function updateXWidgetfocusWidgetForNode(node: Node|null): void {
|
1939
|
-
node = node?.parentNodeOrShadowHost() ?? null;
|
1940
|
-
const XWidgetConstructor = customElements.get('x-widget') as Platform.Constructor.Constructor<XWidget>| undefined;
|
1941
|
-
let widget = null;
|
1942
|
-
while (node) {
|
1943
|
-
if (XWidgetConstructor && node instanceof XWidgetConstructor) {
|
1944
|
-
if (widget) {
|
1945
|
-
node.defaultFocusedElement = widget;
|
1946
|
-
}
|
1947
|
-
widget = node;
|
1948
|
-
}
|
1949
|
-
node = node.parentNodeOrShadowHost();
|
1950
|
-
}
|
1951
|
-
}
|
1952
|
-
|
1953
1937
|
function focusChanged(event: Event): void {
|
1954
1938
|
const target = event.target as HTMLElement;
|
1955
1939
|
const document = target ? target.ownerDocument : null;
|
1956
1940
|
const element = document ? Platform.DOMUtilities.deepActiveElement(document) : null;
|
1957
1941
|
updateWidgetfocusWidgetForNode(element);
|
1958
|
-
updateXWidgetfocusWidgetForNode(element);
|
1959
1942
|
}
|
1960
1943
|
|
1961
1944
|
/**
|
@@ -2282,6 +2265,10 @@ export class HTMLElementWithLightDOMTemplate extends HTMLElement {
|
|
2282
2265
|
}
|
2283
2266
|
}
|
2284
2267
|
|
2268
|
+
get templateRoot(): DocumentFragment|HTMLElement {
|
2269
|
+
return this.#contentTemplate?.content ?? this;
|
2270
|
+
}
|
2271
|
+
|
2285
2272
|
set template(template: Lit.LitTemplate) {
|
2286
2273
|
if (!this.#contentTemplate) {
|
2287
2274
|
this.removeChildren();
|
@@ -36,7 +36,6 @@ import * as Geometry from '../../models/geometry/geometry.js';
|
|
36
36
|
import * as Lit from '../../ui/lit/lit.js';
|
37
37
|
|
38
38
|
import {createShadowRootWithCoreStyles} from './UIUtils.js';
|
39
|
-
import {XWidget} from './XWidget.js';
|
40
39
|
|
41
40
|
// Remember the original DOM mutation methods here, since we
|
42
41
|
// will override them below to sanity check the Widget system.
|
@@ -757,10 +756,6 @@ export class Widget {
|
|
757
756
|
}
|
758
757
|
let child = this.contentElement.traverseNextNode(this.contentElement);
|
759
758
|
while (child) {
|
760
|
-
if (child instanceof XWidget) {
|
761
|
-
child.focus();
|
762
|
-
return;
|
763
|
-
}
|
764
759
|
child = child.traverseNextNode(this.contentElement);
|
765
760
|
}
|
766
761
|
}
|
@@ -39,36 +39,3 @@ export class XElement extends HTMLElement {
|
|
39
39
|
}
|
40
40
|
}
|
41
41
|
}
|
42
|
-
|
43
|
-
class XBox extends XElement {
|
44
|
-
constructor(direction: string) {
|
45
|
-
super();
|
46
|
-
this.style.setProperty('display', 'flex');
|
47
|
-
this.style.setProperty('flex-direction', direction);
|
48
|
-
this.style.setProperty('justify-content', 'flex-start');
|
49
|
-
}
|
50
|
-
|
51
|
-
static override get observedAttributes(): string[] {
|
52
|
-
return super.observedAttributes.concat(['x-start', 'x-center', 'x-stretch', 'x-baseline', 'justify-content']);
|
53
|
-
}
|
54
|
-
|
55
|
-
override attributeChangedCallback(attr: string, oldValue: string|null, newValue: string|null): void {
|
56
|
-
if (attr === 'x-start' || attr === 'x-center' || attr === 'x-stretch' || attr === 'x-baseline') {
|
57
|
-
if (newValue === null) {
|
58
|
-
this.style.removeProperty('align-items');
|
59
|
-
} else {
|
60
|
-
this.style.setProperty('align-items', attr === 'x-start' ? 'flex-start' : attr.substr(2));
|
61
|
-
}
|
62
|
-
return;
|
63
|
-
}
|
64
|
-
super.attributeChangedCallback(attr, oldValue, newValue);
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
|
-
class XHBox extends XBox {
|
69
|
-
constructor() {
|
70
|
-
super('row');
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
customElements.define('x-hbox', XHBox);
|
@@ -95,7 +95,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
95
95
|
|
96
96
|
this.#resizeObserver.observe(this);
|
97
97
|
this.#updateColumns();
|
98
|
-
this.addNodes(this.querySelectorAll('tr'));
|
98
|
+
this.addNodes(this.templateRoot.querySelectorAll('tr'));
|
99
99
|
}
|
100
100
|
|
101
101
|
attributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void {
|
@@ -155,7 +155,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
155
155
|
this.#hideableColumns.clear();
|
156
156
|
this.#columns = [];
|
157
157
|
let hasEditableColumn = false;
|
158
|
-
for (const column of this.querySelectorAll('th[id]') || []) {
|
158
|
+
for (const column of this.templateRoot.querySelectorAll('th[id]') || []) {
|
159
159
|
const id = column.id as Lowercase<string>;
|
160
160
|
let title = column.textContent?.trim() || '';
|
161
161
|
const titleDOMFragment = column.firstElementChild ? document.createDocumentFragment() : undefined;
|
@@ -308,7 +308,7 @@ class DataGridElement extends UI.UIUtils.HTMLElementWithLightDOMTemplate {
|
|
308
308
|
this.#usedCreationNode = null;
|
309
309
|
this.#dataGrid.creationNode = undefined;
|
310
310
|
}
|
311
|
-
const placeholder = this.querySelector('tr[placeholder]');
|
311
|
+
const placeholder = this.templateRoot.querySelector('tr[placeholder]');
|
312
312
|
if (!placeholder) {
|
313
313
|
this.#dataGrid.creationNode?.remove();
|
314
314
|
this.#dataGrid.creationNode = undefined;
|