chrome-devtools-frontend 1.0.1643855 → 1.0.1646286
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/.agents/skills/devtools-source-maps/SKILL.md +124 -0
- package/docs/README.md +1 -0
- package/docs/using_source_maps.md +159 -0
- package/front_end/core/host/AidaClientTypes.ts +2 -0
- package/front_end/core/host/UserMetrics.ts +5 -3
- package/front_end/core/root/Runtime.ts +10 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -3
- package/front_end/core/sdk/DebuggerModel.ts +7 -9
- package/front_end/core/sdk/NetworkRequest.ts +0 -25
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +37 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/SupportedCSSProperties.js +79 -2
- package/front_end/generated/protocol.ts +0 -5
- package/front_end/models/ai_assistance/AiAgent2.ts +52 -15
- package/front_end/models/ai_assistance/AiConversation.ts +4 -2
- package/front_end/models/ai_assistance/AiOrigins.ts +63 -2
- package/front_end/models/ai_assistance/README.md +20 -8
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +2 -2
- package/front_end/models/ai_assistance/agents/FileAgent.ts +9 -42
- package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +9 -133
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +25 -2
- package/front_end/models/ai_assistance/agents/README.md +64 -0
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +26 -3
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
- package/front_end/models/ai_assistance/contexts/FileContext.ts +45 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +48 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.ts +116 -0
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -1
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +9 -12
- package/front_end/models/ai_assistance/tools/GetStyles.ts +19 -12
- package/front_end/models/ai_assistance/tools/README.md +45 -0
- package/front_end/models/ai_assistance/tools/Tool.ts +74 -11
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +21 -5
- package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +18 -2
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +4 -0
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +17 -4
- package/front_end/models/stack_trace/StackTraceModel.ts +34 -1
- package/front_end/models/trace/Styles.ts +29 -7
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +15 -11
- package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -4
- package/front_end/models/trace/helpers/Timing.ts +10 -0
- package/front_end/models/trace/types/TraceEvents.ts +22 -2
- package/front_end/models/web_mcp/WebMCPModel.ts +8 -48
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -15
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +4 -4
- package/front_end/panels/application/ApplicationPanelSidebar.ts +69 -0
- package/front_end/panels/application/ServiceWorkersView.ts +2 -2
- package/front_end/panels/application/WebMCPView.ts +40 -71
- package/front_end/panels/application/components/AdsView.ts +31 -28
- package/front_end/panels/application/components/BackForwardCacheView.ts +1 -2
- package/front_end/panels/application/components/adsView.css +6 -0
- package/front_end/panels/common/ExtensionServer.ts +5 -0
- package/front_end/panels/console/ConsoleView.ts +6 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +46 -213
- package/front_end/panels/console/SymbolizedErrorWidget.ts +4 -1
- package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +0 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +0 -2
- package/front_end/panels/elements/PropertyRenderer.ts +0 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +9 -2
- package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
- package/front_end/panels/issues/AffectedSourcesView.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +0 -1
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -0
- package/front_end/panels/network/NetworkDataGridNode.ts +1 -2
- package/front_end/panels/network/NetworkLogView.ts +34 -7
- package/front_end/panels/profiler/HeapProfileView.ts +0 -1
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +0 -1
- package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
- package/front_end/panels/profiler/IsolateSelector.ts +4 -2
- package/front_end/panels/profiler/ProfileLauncherView.ts +194 -126
- package/front_end/panels/profiler/ProfilesPanel.ts +1 -3
- package/front_end/panels/settings/components/SyncSection.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -4
- package/front_end/panels/timeline/TimelinePanel.ts +7 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +13 -14
- package/front_end/panels/timeline/TimingsTrackAppender.ts +7 -5
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +0 -1
- package/front_end/panels/timeline/components/NetworkRequestDetails.ts +0 -2
- package/front_end/panels/timeline/components/insights/ForcedReflow.ts +0 -1
- package/front_end/panels/timeline/components/insights/NodeLink.ts +0 -1
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +2 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/helpers/OpenInNewTab.ts +3 -3
- package/front_end/ui/kit/link/Link.ts +16 -2
- package/front_end/ui/legacy/InspectorDrawerView.ts +14 -5
- package/front_end/ui/legacy/InspectorView.ts +4 -1
- package/front_end/ui/legacy/PlusButton.ts +6 -1
- package/front_end/ui/legacy/Widget.ts +19 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +95 -31
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +0 -1
- package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -16
- package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// Copyright 2011 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 @devtools/no-imperative-dom-api */
|
|
5
4
|
|
|
6
5
|
import * as Common from '../../core/common/common.js';
|
|
7
6
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
8
7
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
9
8
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
9
|
+
import {html, nothing, render} from '../../ui/lit/lit.js';
|
|
10
|
+
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
10
11
|
|
|
11
12
|
import {IsolateSelector} from './IsolateSelector.js';
|
|
12
13
|
import type {ProfileType} from './ProfileHeader.js';
|
|
@@ -41,166 +42,233 @@ const UIStrings = {
|
|
|
41
42
|
} as const;
|
|
42
43
|
const str_ = i18n.i18n.registerUIStrings('panels/profiler/ProfileLauncherView.ts', UIStrings);
|
|
43
44
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
45
|
+
const {widget, widgetRef} = UI.Widget;
|
|
46
|
+
|
|
47
|
+
interface ProfileTypeEntry {
|
|
48
|
+
profileType: ProfileType;
|
|
49
|
+
selected: boolean;
|
|
50
|
+
customContent: Element|null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ViewInput {
|
|
54
|
+
headerText: string;
|
|
55
|
+
profileTypes: ProfileTypeEntry[];
|
|
56
|
+
controlButtonText: string;
|
|
57
|
+
controlButtonDisabled: boolean;
|
|
58
|
+
controlButtonTooltip: string;
|
|
59
|
+
isProfiling: boolean;
|
|
60
|
+
isolateSelector: IsolateSelector|null;
|
|
61
|
+
onControlClick: () => void;
|
|
62
|
+
onLoadClick: () => void;
|
|
63
|
+
onProfileTypeChange: (profileType: ProfileType) => void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ViewOutput {
|
|
67
|
+
isolateSelector: IsolateSelector;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
|
|
71
|
+
|
|
72
|
+
// clang-format off
|
|
73
|
+
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
74
|
+
render(html`
|
|
75
|
+
<style>${profileLauncherViewStyles}</style>
|
|
76
|
+
<div class="profile-launcher-view-content vbox">
|
|
77
|
+
<div class="vbox">
|
|
78
|
+
<h1>${input.headerText}</h1>
|
|
79
|
+
<form role="radiogroup" aria-label=${input.headerText}>
|
|
80
|
+
${input.profileTypes.map(entry => {
|
|
81
|
+
const radioId = `profile-type-${entry.profileType.id}`;
|
|
82
|
+
const customContent = entry.customContent;
|
|
83
|
+
return html`
|
|
84
|
+
<input id=${radioId} type="radio" name="profile-type"
|
|
85
|
+
.checked=${entry.selected}
|
|
86
|
+
?disabled=${input.isProfiling}
|
|
87
|
+
@change=${() => input.onProfileTypeChange(entry.profileType)}
|
|
88
|
+
jslog=${VisualLogging.toggle().track({change: true}).context('profiler.profile-type')}
|
|
89
|
+
/>
|
|
90
|
+
<label for=${radioId}>${entry.profileType.name}</label>
|
|
91
|
+
<p>${entry.profileType.description}</p>
|
|
92
|
+
${customContent ? html`
|
|
93
|
+
<p>
|
|
94
|
+
<span role="group" aria-labelledby=${radioId}>
|
|
95
|
+
${customContent}
|
|
96
|
+
</span>
|
|
97
|
+
</p>
|
|
98
|
+
` : nothing}
|
|
99
|
+
`;
|
|
100
|
+
})}
|
|
101
|
+
</form>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="vbox profile-isolate-selector-block">
|
|
104
|
+
<h1>${i18nString(UIStrings.selectJavascriptVmInstance)}</h1>
|
|
105
|
+
<div class="vbox profile-launcher-target-list profile-launcher-target-list-container">
|
|
106
|
+
<devtools-widget
|
|
107
|
+
${widget(IsolateSelector)}
|
|
108
|
+
${widgetRef(IsolateSelector, e => {output.isolateSelector = e;})}
|
|
109
|
+
></devtools-widget>
|
|
110
|
+
</div>
|
|
111
|
+
${input.isolateSelector?.totalMemoryElement() ?? nothing}
|
|
112
|
+
</div>
|
|
113
|
+
<div class="hbox profile-launcher-buttons">
|
|
114
|
+
<devtools-button
|
|
115
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
116
|
+
.iconName=${'import'}
|
|
117
|
+
@click=${input.onLoadClick}
|
|
118
|
+
.jslogContext=${'profiler.load-from-file'}
|
|
119
|
+
>${i18nString(UIStrings.load)}</devtools-button>
|
|
120
|
+
<devtools-button
|
|
121
|
+
.variant=${Buttons.Button.Variant.PRIMARY}
|
|
122
|
+
?disabled=${input.controlButtonDisabled}
|
|
123
|
+
title=${input.controlButtonTooltip}
|
|
124
|
+
@click=${input.onControlClick}
|
|
125
|
+
.jslogContext=${'profiler.heap-toggle-recording'}
|
|
126
|
+
>${input.controlButtonText}</devtools-button>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
`, target);
|
|
130
|
+
};
|
|
131
|
+
// clang-format on
|
|
132
|
+
|
|
44
133
|
export class ProfileLauncherView extends Common.ObjectWrapper.eventMixin<EventTypes, typeof UI.Widget.VBox>(
|
|
45
134
|
UI.Widget.VBox) {
|
|
46
135
|
readonly panel: ProfilesPanel;
|
|
47
|
-
#contentElement: HTMLElement;
|
|
48
136
|
readonly selectedProfileTypeSetting: Common.Settings.Setting<string>;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}>;
|
|
58
|
-
isProfiling?: boolean;
|
|
59
|
-
isInstantProfile?: boolean;
|
|
60
|
-
isEnabled?: boolean;
|
|
61
|
-
|
|
62
|
-
constructor(profilesPanel: ProfilesPanel) {
|
|
63
|
-
super();
|
|
64
|
-
this.registerRequiredCSS(profileLauncherViewStyles);
|
|
137
|
+
readonly #view: View;
|
|
138
|
+
#isolateSelector: IsolateSelector|null = null;
|
|
139
|
+
#profileTypes = new Map<string, ProfileType>();
|
|
140
|
+
#isProfiling = false;
|
|
141
|
+
#isInstantProfile = false;
|
|
142
|
+
#isEnabled = false;
|
|
143
|
+
#recordButtonEnabled = true;
|
|
144
|
+
#selectedTypeId = '';
|
|
65
145
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.#contentElement = this.element.createChild('div', 'profile-launcher-view-content vbox');
|
|
146
|
+
constructor(profilesPanel: ProfilesPanel, view: View = DEFAULT_VIEW) {
|
|
147
|
+
super({classes: ['profile-launcher-view']});
|
|
69
148
|
|
|
70
|
-
|
|
149
|
+
this.#view = view;
|
|
150
|
+
this.panel = profilesPanel;
|
|
71
151
|
this.selectedProfileTypeSetting = Common.Settings.Settings.instance().createSetting('selected-profile-type', 'CPU');
|
|
72
|
-
this.profileTypeHeaderElement = profileTypeSelectorElement.createChild('h1');
|
|
73
|
-
this.profileTypeSelectorForm = profileTypeSelectorElement.createChild('form');
|
|
74
|
-
UI.ARIAUtils.markAsRadioGroup(this.profileTypeSelectorForm);
|
|
75
|
-
|
|
76
|
-
const isolateSelectorElement = this.#contentElement.createChild('div', 'vbox profile-isolate-selector-block');
|
|
77
|
-
isolateSelectorElement.createChild('h1').textContent = i18nString(UIStrings.selectJavascriptVmInstance);
|
|
78
|
-
const isolateSelector = new IsolateSelector();
|
|
79
|
-
const isolateSelectorElementChild = isolateSelectorElement.createChild('div', 'vbox profile-launcher-target-list');
|
|
80
|
-
isolateSelectorElementChild.classList.add('profile-launcher-target-list-container');
|
|
81
|
-
isolateSelector.show(isolateSelectorElementChild);
|
|
82
|
-
isolateSelectorElement.appendChild(isolateSelector.totalMemoryElement());
|
|
83
|
-
|
|
84
|
-
const buttonsDiv = this.#contentElement.createChild('div', 'hbox profile-launcher-buttons');
|
|
85
|
-
this.controlButton = UI.UIUtils.createTextButton('', this.controlButtonClicked.bind(this), {
|
|
86
|
-
jslogContext: 'profiler.heap-toggle-recording',
|
|
87
|
-
variant: Buttons.Button.Variant.PRIMARY,
|
|
88
|
-
});
|
|
89
|
-
this.loadButton = new Buttons.Button.Button();
|
|
90
|
-
this.loadButton
|
|
91
|
-
.data = {iconName: 'import', variant: Buttons.Button.Variant.OUTLINED, jslogContext: 'profiler.load-from-file'};
|
|
92
|
-
this.loadButton.textContent = i18nString(UIStrings.load);
|
|
93
|
-
this.loadButton.addEventListener('click', this.loadButtonClicked.bind(this));
|
|
94
|
-
buttonsDiv.appendChild(this.loadButton);
|
|
95
|
-
buttonsDiv.appendChild(this.controlButton);
|
|
96
|
-
this.recordButtonEnabled = true;
|
|
97
|
-
|
|
98
|
-
this.typeIdToOptionElementAndProfileType = new Map();
|
|
99
152
|
}
|
|
100
153
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
154
|
+
override wasShown(): void {
|
|
155
|
+
super.wasShown();
|
|
156
|
+
this.requestUpdate();
|
|
104
157
|
}
|
|
105
158
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
} else {
|
|
110
|
-
this.controlButton.setAttribute('disabled', '');
|
|
111
|
-
}
|
|
112
|
-
UI.Tooltip.Tooltip.install(
|
|
113
|
-
this.controlButton, this.recordButtonEnabled ? '' : UI.UIUtils.anotherProfilerActiveLabel());
|
|
114
|
-
if (this.isInstantProfile) {
|
|
115
|
-
this.controlButton.classList.remove('running');
|
|
116
|
-
this.controlButton.textContent = i18nString(UIStrings.takeSnapshot);
|
|
117
|
-
} else if (this.isProfiling) {
|
|
118
|
-
this.controlButton.classList.add('running');
|
|
119
|
-
this.controlButton.textContent = i18nString(UIStrings.stop);
|
|
120
|
-
} else {
|
|
121
|
-
this.controlButton.classList.remove('running');
|
|
122
|
-
this.controlButton.textContent = i18nString(UIStrings.start);
|
|
123
|
-
}
|
|
124
|
-
for (const {optionElement} of this.typeIdToOptionElementAndProfileType.values()) {
|
|
125
|
-
optionElement.disabled = Boolean(this.isProfiling);
|
|
126
|
-
}
|
|
159
|
+
#getHeaderText(): string {
|
|
160
|
+
return this.#profileTypes.size > 1 ? i18nString(UIStrings.selectProfilingType) :
|
|
161
|
+
(this.#profileTypes.values().next().value?.name ?? '');
|
|
127
162
|
}
|
|
128
163
|
|
|
129
164
|
profileStarted(): void {
|
|
130
|
-
this
|
|
131
|
-
this.
|
|
165
|
+
this.#isProfiling = true;
|
|
166
|
+
this.requestUpdate();
|
|
132
167
|
}
|
|
133
168
|
|
|
134
169
|
profileFinished(): void {
|
|
135
|
-
this
|
|
136
|
-
this.
|
|
170
|
+
this.#isProfiling = false;
|
|
171
|
+
this.requestUpdate();
|
|
137
172
|
}
|
|
138
173
|
|
|
139
174
|
updateProfileType(profileType: ProfileType, recordButtonEnabled: boolean): void {
|
|
140
|
-
this
|
|
141
|
-
this
|
|
142
|
-
this
|
|
143
|
-
this.
|
|
175
|
+
this.#isInstantProfile = profileType.isInstantProfile();
|
|
176
|
+
this.#recordButtonEnabled = recordButtonEnabled;
|
|
177
|
+
this.#isEnabled = profileType.isEnabled();
|
|
178
|
+
this.requestUpdate();
|
|
144
179
|
}
|
|
145
180
|
|
|
146
181
|
addProfileType(profileType: ProfileType): void {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.
|
|
150
|
-
radio.addEventListener('change', this.profileTypeChanged.bind(this, profileType), false);
|
|
151
|
-
const descriptionElement = this.profileTypeSelectorForm.createChild('p');
|
|
152
|
-
descriptionElement.textContent = profileType.description;
|
|
153
|
-
UI.ARIAUtils.setDescription(radio, profileType.description);
|
|
154
|
-
const customContent = profileType.customContent();
|
|
155
|
-
if (customContent) {
|
|
156
|
-
customContent.setAttribute('role', 'group');
|
|
157
|
-
customContent.setAttribute('aria-labelledby', `${radio.id}`);
|
|
158
|
-
this.profileTypeSelectorForm.createChild('p').appendChild(customContent);
|
|
159
|
-
profileType.setCustomContentEnabled(false);
|
|
160
|
-
}
|
|
161
|
-
const headerText = this.typeIdToOptionElementAndProfileType.size > 1 ? i18nString(UIStrings.selectProfilingType) :
|
|
162
|
-
profileType.name;
|
|
163
|
-
this.profileTypeHeaderElement.textContent = headerText;
|
|
164
|
-
UI.ARIAUtils.setLabel(this.profileTypeSelectorForm, headerText);
|
|
182
|
+
this.#profileTypes.set(profileType.id, profileType);
|
|
183
|
+
profileType.setCustomContentEnabled(false);
|
|
184
|
+
this.requestUpdate();
|
|
165
185
|
}
|
|
166
186
|
|
|
167
187
|
restoreSelectedProfileType(): void {
|
|
168
188
|
let typeId = this.selectedProfileTypeSetting.get();
|
|
169
|
-
if (!this.
|
|
170
|
-
typeId = this.
|
|
189
|
+
if (!this.#profileTypes.has(typeId)) {
|
|
190
|
+
typeId = this.#profileTypes.keys().next().value as string;
|
|
171
191
|
this.selectedProfileTypeSetting.set(typeId);
|
|
172
192
|
}
|
|
173
193
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
optionElementAndProfileType.optionElement.checked = true;
|
|
179
|
-
const type = optionElementAndProfileType.profileType;
|
|
180
|
-
for (const [id, {profileType}] of this.typeIdToOptionElementAndProfileType) {
|
|
181
|
-
const enabled = (id === typeId);
|
|
182
|
-
profileType.setCustomContentEnabled(enabled);
|
|
194
|
+
this.#selectedTypeId = typeId;
|
|
195
|
+
const selectedType = this.#profileTypes.get(typeId);
|
|
196
|
+
if (!selectedType) {
|
|
197
|
+
return;
|
|
183
198
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
this.
|
|
199
|
+
for (const [id, profileType] of this.#profileTypes) {
|
|
200
|
+
profileType.setCustomContentEnabled(id === typeId);
|
|
201
|
+
}
|
|
202
|
+
this.dispatchEventToListeners(Events.PROFILE_TYPE_SELECTED, selectedType);
|
|
203
|
+
this.requestUpdate();
|
|
189
204
|
}
|
|
190
205
|
|
|
191
|
-
profileTypeChanged(profileType: ProfileType): void {
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
type.setCustomContentEnabled(false);
|
|
206
|
+
#profileTypeChanged(profileType: ProfileType): void {
|
|
207
|
+
const previousTypeId = this.#selectedTypeId;
|
|
208
|
+
const previousType = this.#profileTypes.get(previousTypeId);
|
|
209
|
+
if (previousType) {
|
|
210
|
+
previousType.setCustomContentEnabled(false);
|
|
211
|
+
}
|
|
198
212
|
profileType.setCustomContentEnabled(true);
|
|
199
|
-
this
|
|
200
|
-
this.isInstantProfile = profileType.isInstantProfile();
|
|
201
|
-
this.isEnabled = profileType.isEnabled();
|
|
202
|
-
this.updateControls();
|
|
213
|
+
this.#selectedTypeId = profileType.id;
|
|
203
214
|
this.selectedProfileTypeSetting.set(profileType.id);
|
|
215
|
+
this.#isInstantProfile = profileType.isInstantProfile();
|
|
216
|
+
this.#isEnabled = profileType.isEnabled();
|
|
217
|
+
this.dispatchEventToListeners(Events.PROFILE_TYPE_SELECTED, profileType);
|
|
218
|
+
this.requestUpdate();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
override performUpdate(): void {
|
|
222
|
+
const profileTypeEntries: ProfileTypeEntry[] = [];
|
|
223
|
+
for (const [id, profileType] of this.#profileTypes) {
|
|
224
|
+
const selected = id === this.#selectedTypeId;
|
|
225
|
+
const customContent = profileType.customContent();
|
|
226
|
+
profileType.setCustomContentEnabled(selected);
|
|
227
|
+
profileTypeEntries.push({
|
|
228
|
+
profileType,
|
|
229
|
+
selected,
|
|
230
|
+
customContent,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const controlButtonText = this.#isInstantProfile ?
|
|
235
|
+
i18nString(UIStrings.takeSnapshot) :
|
|
236
|
+
(this.#isProfiling ? i18nString(UIStrings.stop) : i18nString(UIStrings.start));
|
|
237
|
+
const controlButtonDisabled = !(this.#isEnabled && this.#recordButtonEnabled);
|
|
238
|
+
const controlButtonTooltip = this.#recordButtonEnabled ? '' : UI.UIUtils.anotherProfilerActiveLabel();
|
|
239
|
+
const that = this;
|
|
240
|
+
|
|
241
|
+
this.#view(
|
|
242
|
+
{
|
|
243
|
+
headerText: this.#getHeaderText(),
|
|
244
|
+
profileTypes: profileTypeEntries,
|
|
245
|
+
controlButtonText,
|
|
246
|
+
controlButtonDisabled,
|
|
247
|
+
controlButtonTooltip,
|
|
248
|
+
isProfiling: this.#isProfiling,
|
|
249
|
+
isolateSelector: this.#isolateSelector,
|
|
250
|
+
onControlClick: () => {
|
|
251
|
+
this.panel.toggleRecord();
|
|
252
|
+
},
|
|
253
|
+
onLoadClick: () => {
|
|
254
|
+
const loadFromFileAction = UI.ActionRegistry.ActionRegistry.instance().getAction('profiler.load-from-file');
|
|
255
|
+
void loadFromFileAction.execute();
|
|
256
|
+
},
|
|
257
|
+
onProfileTypeChange: (profileType: ProfileType) => {
|
|
258
|
+
this.#profileTypeChanged(profileType);
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
set isolateSelector(isolateSelector: IsolateSelector) {
|
|
263
|
+
if (that.#isolateSelector === isolateSelector) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
that.#isolateSelector = isolateSelector;
|
|
267
|
+
that.requestUpdate();
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
this.contentElement,
|
|
271
|
+
);
|
|
204
272
|
}
|
|
205
273
|
}
|
|
206
274
|
|
|
@@ -357,7 +357,7 @@ export class ProfilesPanel extends UI.Panel.PanelWithSidebar implements DataDisp
|
|
|
357
357
|
reset(): void {
|
|
358
358
|
this.profileTypes.forEach(type => type.reset());
|
|
359
359
|
|
|
360
|
-
|
|
360
|
+
this.closeVisibleView();
|
|
361
361
|
|
|
362
362
|
this.profileGroups = {};
|
|
363
363
|
this.updateToggleRecordAction(false);
|
|
@@ -365,8 +365,6 @@ export class ProfilesPanel extends UI.Panel.PanelWithSidebar implements DataDisp
|
|
|
365
365
|
|
|
366
366
|
this.sidebarTree.element.classList.remove('some-expandable');
|
|
367
367
|
|
|
368
|
-
this.launcherView.detach();
|
|
369
|
-
this.profileViews.removeChildren();
|
|
370
368
|
this.profileViewToolbar.removeToolbarItems();
|
|
371
369
|
|
|
372
370
|
this.profilesItemTreeElement.select();
|
|
@@ -346,7 +346,7 @@ export class SyncSection extends UI.Widget.Widget {
|
|
|
346
346
|
// TODO: investigate if /advance link is alive
|
|
347
347
|
const warningLink =
|
|
348
348
|
this.#syncInfo.isSyncActive ? 'chrome://settings/syncSetup/advanced' : 'chrome://settings/syncSetup';
|
|
349
|
-
UIHelpers.openInNewTab(warningLink);
|
|
349
|
+
UIHelpers.openInNewTab(warningLink, /* allowPrivileged=*/ true);
|
|
350
350
|
event.consume();
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -69,9 +69,10 @@ export const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly<Record<string, number>> = {
|
|
|
69
69
|
[Trace.Types.Events.Name.SOFT_NAVIGATION_START]: 1,
|
|
70
70
|
[Trace.Types.Events.Name.MARK_LOAD]: 2,
|
|
71
71
|
[Trace.Types.Events.Name.MARK_FCP]: 3,
|
|
72
|
-
[Trace.Types.Events.Name.
|
|
73
|
-
[Trace.Types.Events.Name.
|
|
74
|
-
[Trace.Types.Events.Name.
|
|
72
|
+
[Trace.Types.Events.Name.MARK_SOFT_FCP]: 4,
|
|
73
|
+
[Trace.Types.Events.Name.MARK_DOM_CONTENT]: 5,
|
|
74
|
+
[Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 6,
|
|
75
|
+
[Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 7,
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
// Threshold to match up overlay markers that are off by a tiny amount so they aren't rendered
|
|
@@ -676,7 +677,7 @@ export class TimelineFlameChartView extends Common.ObjectWrapper.eventMixin<Even
|
|
|
676
677
|
event.name === Trace.Types.Events.Name.SOFT_NAVIGATION_START ||
|
|
677
678
|
event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE ||
|
|
678
679
|
event.name === Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION ||
|
|
679
|
-
event.name === Trace.Types.Events.Name.MARK_FCP ||
|
|
680
|
+
event.name === Trace.Types.Events.Name.MARK_FCP || event.name === Trace.Types.Events.Name.MARK_SOFT_FCP ||
|
|
680
681
|
event.name === Trace.Types.Events.Name.MARK_DOM_CONTENT ||
|
|
681
682
|
event.name === Trace.Types.Events.Name.MARK_LOAD);
|
|
682
683
|
|
|
@@ -2435,6 +2435,13 @@ export class TimelinePanel extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
2435
2435
|
async loadingStarted(): Promise<void> {
|
|
2436
2436
|
this.#changeView({mode: 'STATUS_PANE_OVERLAY'});
|
|
2437
2437
|
|
|
2438
|
+
// If recording was stopped automatically (e.g. page reload or AI-triggered trace),
|
|
2439
|
+
// we must transition to STOP_PENDING so that loadingComplete() knows the resulting
|
|
2440
|
+
// trace is a fresh recording.
|
|
2441
|
+
if (this.state === State.RECORDING) {
|
|
2442
|
+
this.setState(State.STOP_PENDING);
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2438
2445
|
if (this.statusDialog) {
|
|
2439
2446
|
this.statusDialog.remove();
|
|
2440
2447
|
}
|
|
@@ -668,7 +668,6 @@ export class TimelineUIUtils {
|
|
|
668
668
|
const options = {
|
|
669
669
|
tabStop: true,
|
|
670
670
|
showColumnNumber: false,
|
|
671
|
-
inlineFrameIndex: 0,
|
|
672
671
|
};
|
|
673
672
|
details = LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options);
|
|
674
673
|
}
|
|
@@ -763,7 +762,6 @@ export class TimelineUIUtils {
|
|
|
763
762
|
lineNumber,
|
|
764
763
|
columnNumber,
|
|
765
764
|
showColumnNumber: true,
|
|
766
|
-
inlineFrameIndex: 0,
|
|
767
765
|
className: 'timeline-details',
|
|
768
766
|
tabStop: true,
|
|
769
767
|
omitOrigin,
|
|
@@ -788,14 +786,13 @@ export class TimelineUIUtils {
|
|
|
788
786
|
const options = {
|
|
789
787
|
className: 'timeline-details',
|
|
790
788
|
tabStop: true,
|
|
791
|
-
inlineFrameIndex: 0,
|
|
792
789
|
showColumnNumber: true,
|
|
793
790
|
columnNumber: frame.columnNumber,
|
|
794
791
|
lineNumber: frame.lineNumber,
|
|
795
792
|
maxLength,
|
|
796
793
|
};
|
|
797
794
|
if (isFreshOrEnhanced) {
|
|
798
|
-
return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true
|
|
795
|
+
return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true});
|
|
799
796
|
}
|
|
800
797
|
return LegacyComponents.Linkifier.Linkifier.linkifyURL(frame.url as Platform.DevToolsPath.UrlString, options);
|
|
801
798
|
}
|
|
@@ -809,17 +806,21 @@ export class TimelineUIUtils {
|
|
|
809
806
|
name = 'Largest Contentful Paint';
|
|
810
807
|
break;
|
|
811
808
|
case Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION:
|
|
812
|
-
link = 'https://developer.chrome.com/docs/web-platform/soft-navigations
|
|
809
|
+
link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
|
|
813
810
|
name = 'Soft Largest Contentful Paint';
|
|
814
811
|
break;
|
|
815
812
|
case Trace.Types.Events.Name.SOFT_NAVIGATION_START:
|
|
816
|
-
link = 'https://developer.chrome.com/docs/web-platform/soft-navigations
|
|
813
|
+
link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
|
|
817
814
|
name = 'Soft Navigations';
|
|
818
815
|
break;
|
|
819
816
|
case Trace.Types.Events.Name.MARK_FCP:
|
|
820
817
|
link = 'https://web.dev/first-contentful-paint/';
|
|
821
818
|
name = 'First Contentful Paint';
|
|
822
819
|
break;
|
|
820
|
+
case Trace.Types.Events.Name.MARK_SOFT_FCP:
|
|
821
|
+
link = 'https://developer.chrome.com/docs/web-platform/soft-navigations';
|
|
822
|
+
name = 'Soft First Contentful Paint';
|
|
823
|
+
break;
|
|
823
824
|
default:
|
|
824
825
|
break;
|
|
825
826
|
}
|
|
@@ -963,7 +964,7 @@ export class TimelineUIUtils {
|
|
|
963
964
|
|
|
964
965
|
// Add timestamp to user timings, including custom extensibility markers
|
|
965
966
|
if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming) ||
|
|
966
|
-
Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {
|
|
967
|
+
Trace.Types.Extensions.isSyntheticExtensionEntry(event) || Trace.Types.Events.isSoftNavigationStart(event)) {
|
|
967
968
|
const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(
|
|
968
969
|
event,
|
|
969
970
|
parsedTrace,
|
|
@@ -1228,7 +1229,6 @@ export class TimelineUIUtils {
|
|
|
1228
1229
|
const options = {
|
|
1229
1230
|
tabStop: true,
|
|
1230
1231
|
showColumnNumber: false,
|
|
1231
|
-
inlineFrameIndex: 0,
|
|
1232
1232
|
};
|
|
1233
1233
|
contentHelper.appendElementRow(
|
|
1234
1234
|
i18nString(UIStrings.imageUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));
|
|
@@ -1242,7 +1242,6 @@ export class TimelineUIUtils {
|
|
|
1242
1242
|
const options = {
|
|
1243
1243
|
tabStop: true,
|
|
1244
1244
|
showColumnNumber: false,
|
|
1245
|
-
inlineFrameIndex: 0,
|
|
1246
1245
|
};
|
|
1247
1246
|
contentHelper.appendElementRow(
|
|
1248
1247
|
i18nString(UIStrings.stylesheetUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));
|
|
@@ -1444,6 +1443,7 @@ export class TimelineUIUtils {
|
|
|
1444
1443
|
|
|
1445
1444
|
case Trace.Types.Events.Name.MARK_FIRST_PAINT:
|
|
1446
1445
|
case Trace.Types.Events.Name.MARK_FCP:
|
|
1446
|
+
case Trace.Types.Events.Name.MARK_SOFT_FCP:
|
|
1447
1447
|
case Trace.Types.Events.Name.MARK_LOAD:
|
|
1448
1448
|
case Trace.Types.Events.Name.MARK_DOM_CONTENT: {
|
|
1449
1449
|
const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(
|
|
@@ -2074,7 +2074,7 @@ export class TimelineUIUtils {
|
|
|
2074
2074
|
tall = true;
|
|
2075
2075
|
break;
|
|
2076
2076
|
case Trace.Types.Events.Name.SOFT_NAVIGATION_START:
|
|
2077
|
-
color = 'var(--
|
|
2077
|
+
color = 'var(--color-text-primary)';
|
|
2078
2078
|
tall = true;
|
|
2079
2079
|
break;
|
|
2080
2080
|
case Trace.Types.Events.Name.FRAME_STARTED_LOADING:
|
|
@@ -2094,6 +2094,7 @@ export class TimelineUIUtils {
|
|
|
2094
2094
|
tall = true;
|
|
2095
2095
|
break;
|
|
2096
2096
|
case Trace.Types.Events.Name.MARK_FCP:
|
|
2097
|
+
case Trace.Types.Events.Name.MARK_SOFT_FCP:
|
|
2097
2098
|
color = 'var(--sys-color-green-bright)';
|
|
2098
2099
|
tall = true;
|
|
2099
2100
|
break;
|
|
@@ -2299,7 +2300,6 @@ export class TimelineDetailsContentHelper {
|
|
|
2299
2300
|
tabStop: true,
|
|
2300
2301
|
columnNumber: startColumn,
|
|
2301
2302
|
showColumnNumber: true,
|
|
2302
|
-
inlineFrameIndex: 0,
|
|
2303
2303
|
text,
|
|
2304
2304
|
omitOrigin,
|
|
2305
2305
|
};
|
|
@@ -2316,8 +2316,7 @@ export class TimelineDetailsContentHelper {
|
|
|
2316
2316
|
return;
|
|
2317
2317
|
}
|
|
2318
2318
|
const locationContent = document.createElement('span');
|
|
2319
|
-
const link = this.#linkifier.maybeLinkifyScriptLocation(
|
|
2320
|
-
this.target, null, url, startLine, {tabStop: true, inlineFrameIndex: 0});
|
|
2319
|
+
const link = this.#linkifier.maybeLinkifyScriptLocation(this.target, null, url, startLine, {tabStop: true});
|
|
2321
2320
|
if (!link) {
|
|
2322
2321
|
return;
|
|
2323
2322
|
}
|
|
@@ -2407,7 +2406,7 @@ export function isMarkerEvent(parsedTrace: Trace.TraceModel.ParsedTrace, event:
|
|
|
2407
2406
|
return true;
|
|
2408
2407
|
}
|
|
2409
2408
|
|
|
2410
|
-
if (Trace.Types.Events.
|
|
2409
|
+
if (Trace.Types.Events.isAnyFirstContentfulPaint(event) || Trace.Types.Events.isFirstPaint(event)) {
|
|
2411
2410
|
return event.args.frame === parsedTrace.data.Meta.mainFrameId;
|
|
2412
2411
|
}
|
|
2413
2412
|
|
|
@@ -37,12 +37,14 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
|
37
37
|
*/
|
|
38
38
|
export const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly<Record<string, number>> = {
|
|
39
39
|
[Trace.Types.Events.Name.NAVIGATION_START]: 0,
|
|
40
|
-
[Trace.Types.Events.Name.
|
|
41
|
-
[Trace.Types.Events.Name.MARK_FCP]: 2,
|
|
40
|
+
[Trace.Types.Events.Name.SOFT_NAVIGATION_START]: 1,
|
|
42
41
|
[Trace.Types.Events.Name.MARK_FIRST_PAINT]: 2,
|
|
43
|
-
[Trace.Types.Events.Name.
|
|
44
|
-
[Trace.Types.Events.Name.
|
|
45
|
-
[Trace.Types.Events.Name.
|
|
42
|
+
[Trace.Types.Events.Name.MARK_FCP]: 3,
|
|
43
|
+
[Trace.Types.Events.Name.MARK_SOFT_FCP]: 4,
|
|
44
|
+
[Trace.Types.Events.Name.MARK_DOM_CONTENT]: 5,
|
|
45
|
+
[Trace.Types.Events.Name.MARK_LOAD]: 6,
|
|
46
|
+
[Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 7,
|
|
47
|
+
[Trace.Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: 8,
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
export class TimingsTrackAppender implements TrackAppender {
|
|
@@ -436,7 +436,6 @@ function linkifyURL(url: Platform.DevToolsPath.UrlString): HTMLElement {
|
|
|
436
436
|
return LegacyComponents.Linkifier.Linkifier.linkifyURL(url, {
|
|
437
437
|
tabStop: true,
|
|
438
438
|
showColumnNumber: false,
|
|
439
|
-
inlineFrameIndex: 0,
|
|
440
439
|
maxLength: MAX_URL_LENGTH,
|
|
441
440
|
});
|
|
442
441
|
}
|
|
@@ -267,7 +267,6 @@ function renderURL(request: Trace.Types.Events.SyntheticNetworkRequest): Lit.Tem
|
|
|
267
267
|
const options: LegacyComponents.Linkifier.LinkifyURLOptions = {
|
|
268
268
|
tabStop: true,
|
|
269
269
|
showColumnNumber: false,
|
|
270
|
-
inlineFrameIndex: 0,
|
|
271
270
|
maxLength: MAX_URL_LENGTH,
|
|
272
271
|
};
|
|
273
272
|
const linkifiedURL = LegacyComponents.Linkifier.Linkifier.linkifyURL(
|
|
@@ -439,7 +438,6 @@ function renderInitiatedBy(
|
|
|
439
438
|
const options: LegacyComponents.Linkifier.LinkifyOptions = {
|
|
440
439
|
tabStop: true,
|
|
441
440
|
showColumnNumber: true,
|
|
442
|
-
inlineFrameIndex: 0,
|
|
443
441
|
};
|
|
444
442
|
// If we have a stack trace, that is the most reliable way to get the initiator data and display a link to the source.
|
|
445
443
|
if (hasStackTrace) {
|
|
@@ -39,7 +39,6 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
39
39
|
const options = {
|
|
40
40
|
tabStop: true,
|
|
41
41
|
showColumnNumber: false,
|
|
42
|
-
inlineFrameIndex: 0,
|
|
43
42
|
maxLength: MAX_URL_LENGTH,
|
|
44
43
|
};
|
|
45
44
|
const linkEl = LegacyComponents.Linkifier.Linkifier.linkifyURL(fallbackUrl, options);
|
|
@@ -1627,6 +1627,8 @@ export class Overlays extends EventTarget {
|
|
|
1627
1627
|
markers: HTMLElement, marker: HTMLElement): void {
|
|
1628
1628
|
if (Trace.Types.Events.isSoftNavigationStart(event)) {
|
|
1629
1629
|
name = 'Soft Nav';
|
|
1630
|
+
} else if (Trace.Types.Events.isSoftFirstContentfulPaint(event)) {
|
|
1631
|
+
name = 'Soft FCP';
|
|
1630
1632
|
} else if (Trace.Types.Events.isSoftLargestContentfulPaintCandidate(event)) {
|
|
1631
1633
|
name = 'Soft LCP';
|
|
1632
1634
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Name: Dependencies sourced from the upstream `chromium` repository
|
|
2
2
|
URL: Internal
|
|
3
3
|
Version: N/A
|
|
4
|
-
Revision:
|
|
4
|
+
Revision: e32418f5632b194cc1b5a5a0c0b1510d33edcc15
|
|
5
5
|
Update Mechanism: Manual (https://crbug.com/428069060)
|
|
6
6
|
License: BSD-3-Clause
|
|
7
7
|
License File: LICENSE
|