chrome-devtools-frontend 1.0.1518653 → 1.0.1520139
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/config/owner/COMMON_OWNERS +1 -2
- package/config/typescript/tsconfig.eslint.json +12 -1
- package/docs/ui_engineering.md +1011 -0
- package/eslint.config.mjs +1 -0
- package/front_end/core/host/GdpClient.ts +12 -3
- package/front_end/core/sdk/EnhancedTracesParser.ts +5 -5
- package/front_end/core/sdk/NetworkManager.ts +1 -0
- package/front_end/core/sdk/NetworkRequest.ts +10 -0
- package/front_end/core/sdk/RehydratingConnection.snapshot.txt +211 -0
- package/front_end/core/sdk/TargetManager.ts +4 -0
- package/front_end/entrypoints/main/MainImpl.ts +6 -1
- package/front_end/entrypoints/main/main-meta.ts +3 -3
- package/front_end/generated/SupportedCSSProperties.js +19 -4
- package/front_end/models/ai_assistance/agents/AiAgent.ts +57 -10
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +64 -87
- package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -31
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +127 -29
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +106 -55
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +23 -19
- package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
- package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
- package/front_end/models/ai_assistance/performance/AIContext.ts +63 -8
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -0
- package/front_end/models/badges/AiExplorerBadge.ts +19 -3
- package/front_end/models/badges/Badge.ts +8 -1
- package/front_end/models/badges/CodeWhispererBadge.ts +1 -0
- package/front_end/models/badges/DOMDetectiveBadge.ts +1 -0
- package/front_end/models/badges/SpeedsterBadge.ts +1 -0
- package/front_end/models/badges/StarterBadge.ts +6 -0
- package/front_end/models/badges/badges.ts +1 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
- package/front_end/models/trace/EventsSerializer.ts +4 -3
- package/front_end/models/trace/handlers/UserInteractionsHandler.ts +101 -73
- package/front_end/models/trace/helpers/Timing.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +18 -8
- package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
- package/front_end/panels/ai_assistance/components/ChatView.ts +44 -68
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +63 -15
- package/front_end/panels/ai_assistance/components/chatView.css +12 -0
- package/front_end/panels/animation/AnimationTimeline.ts +1 -1
- package/front_end/panels/animation/animationTimeline.css +4 -0
- package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
- package/front_end/panels/common/BadgeNotification.ts +3 -3
- package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
- package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
- package/front_end/panels/console/ConsolePrompt.ts +6 -0
- package/front_end/panels/console/ConsoleView.ts +4 -2
- package/front_end/panels/coverage/CoverageListView.ts +133 -158
- package/front_end/panels/coverage/CoverageView.ts +39 -16
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
- package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
- package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
- package/front_end/panels/recorder/components/RecordingView.ts +2 -2
- package/front_end/panels/search/SearchResultsPane.ts +186 -134
- package/front_end/panels/search/SearchView.ts +42 -36
- package/front_end/panels/search/searchResultsPane.css +9 -0
- package/front_end/panels/search/searchView.css +0 -2
- package/front_end/panels/security/CookieControlsView.ts +2 -1
- package/front_end/panels/settings/AISettingsTab.ts +6 -3
- package/front_end/panels/settings/components/SyncSection.ts +26 -12
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +1 -1
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -4
- package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/sourcesView.css +6 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
- package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
- package/front_end/panels/timeline/TimelinePanel.ts +2 -0
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +1 -1
- package/front_end/panels/timeline/components/NetworkRequestDetails.ts +1 -1
- package/front_end/panels/timeline/components/RelatedInsightChips.ts +1 -1
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +16 -25
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +19 -28
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +16 -25
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
- package/front_end/third_party/puppeteer/package/package.json +12 -4
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/Function.ts +22 -30
- package/front_end/tsconfig.json +12 -1
- package/front_end/ui/components/dialogs/Dialog.ts +1 -1
- package/front_end/ui/components/markdown_view/MarkdownImage.ts +4 -5
- package/front_end/ui/components/switch/SwitchImpl.ts +12 -1
- package/front_end/ui/components/text_editor/config.ts +16 -2
- package/front_end/ui/legacy/InspectorView.ts +86 -13
- package/front_end/ui/legacy/TabbedPane.ts +2 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -1
- package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -11
- package/front_end/ui/lit/i18n-template.ts +5 -2
- package/front_end/ui/visual_logging/KnownContextValues.ts +15 -5
- package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
- package/package.json +1 -1
@@ -43,10 +43,20 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
43
43
|
#insight: Trace.Insights.Types.InsightModel;
|
44
44
|
#parsedTrace: Trace.TraceModel.ParsedTrace;
|
45
45
|
|
46
|
+
/**
|
47
|
+
* A utility method because we dependency inject this formatter into
|
48
|
+
* PerformanceTraceFormatter; this allows you to pass
|
49
|
+
* PerformanceInsightFormatter.create rather than an anonymous
|
50
|
+
* function that wraps the constructor.
|
51
|
+
*/
|
52
|
+
static create(focus: AgentFocus, insight: Trace.Insights.Types.InsightModel): PerformanceInsightFormatter {
|
53
|
+
return new PerformanceInsightFormatter(focus, insight);
|
54
|
+
}
|
55
|
+
|
46
56
|
constructor(focus: AgentFocus, insight: Trace.Insights.Types.InsightModel) {
|
47
|
-
super(focus);
|
57
|
+
super(focus, null);
|
48
58
|
this.#insight = insight;
|
49
|
-
this.#parsedTrace = focus.
|
59
|
+
this.#parsedTrace = focus.parsedTrace;
|
50
60
|
}
|
51
61
|
|
52
62
|
#formatMilli(x?: number): string {
|
@@ -63,6 +73,28 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
63
73
|
return this.#formatMilli(Trace.Helpers.Timing.microToMilli(x as Trace.Types.Timing.Micro));
|
64
74
|
}
|
65
75
|
|
76
|
+
#formatRequestUrl(request: Trace.Types.Events.SyntheticNetworkRequest): string {
|
77
|
+
const eventKey = this.eventsSerializer.keyForEvent(request);
|
78
|
+
return `${request.args.data.url} (eventKey: ${eventKey})`;
|
79
|
+
}
|
80
|
+
|
81
|
+
#formatScriptUrl(script: Trace.Handlers.ModelHandlers.Scripts.Script): string {
|
82
|
+
if (script.request) {
|
83
|
+
return this.#formatRequestUrl(script.request);
|
84
|
+
}
|
85
|
+
|
86
|
+
return script.url ?? script.sourceUrl ?? script.scriptId;
|
87
|
+
}
|
88
|
+
|
89
|
+
#formatUrl(url: string): string {
|
90
|
+
const request = this.#parsedTrace.data.NetworkRequests.byTime.find(request => request.args.data.url === url);
|
91
|
+
if (request) {
|
92
|
+
return this.#formatRequestUrl(request);
|
93
|
+
}
|
94
|
+
|
95
|
+
return url;
|
96
|
+
}
|
97
|
+
|
66
98
|
/**
|
67
99
|
* Information about LCP which we pass to the LLM for all insights that relate to LCP.
|
68
100
|
*/
|
@@ -81,14 +113,15 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
81
113
|
}
|
82
114
|
|
83
115
|
const {metricScore, lcpRequest, lcpEvent} = data;
|
84
|
-
const theLcpElement =
|
85
|
-
|
116
|
+
const theLcpElement = lcpEvent.args.data?.nodeName ?
|
117
|
+
`The LCP element (${lcpEvent.args.data.nodeName}, nodeId: ${lcpEvent.args.data.nodeId})` :
|
118
|
+
'The LCP element';
|
86
119
|
const parts: string[] = [
|
87
120
|
`The Largest Contentful Paint (LCP) time for this navigation was ${this.#formatMicro(metricScore.timing)}.`,
|
88
121
|
];
|
89
122
|
|
90
123
|
if (lcpRequest) {
|
91
|
-
parts.push(`${theLcpElement} is an image fetched from
|
124
|
+
parts.push(`${theLcpElement} is an image fetched from ${this.#formatRequestUrl(lcpRequest)}.`);
|
92
125
|
const request =
|
93
126
|
this.formatNetworkRequests([lcpRequest], {verbose: true, customTitle: 'LCP resource network request'});
|
94
127
|
parts.push(request);
|
@@ -100,6 +133,12 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
100
133
|
}
|
101
134
|
|
102
135
|
insightIsSupported(): boolean {
|
136
|
+
// Although our types don't show it, Insights can end up as Errors if there
|
137
|
+
// is an issue in the processing stage. In this case we should gracefully
|
138
|
+
// ignore this error.
|
139
|
+
if (this.#insight instanceof Error) {
|
140
|
+
return false;
|
141
|
+
}
|
103
142
|
return this.#description().length > 0;
|
104
143
|
}
|
105
144
|
|
@@ -197,7 +236,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
197
236
|
let output = 'The following resources were associated with ineffficient cache policies:\n';
|
198
237
|
|
199
238
|
for (const entry of insight.requests) {
|
200
|
-
output += `\n- ${entry.request
|
239
|
+
output += `\n- ${this.#formatRequestUrl(entry.request)}`;
|
201
240
|
output += `\n - Cache Time to Live (TTL): ${entry.ttl} seconds`;
|
202
241
|
output += `\n - Wasted bytes: ${bytes(entry.wastedBytes)}`;
|
203
242
|
}
|
@@ -206,6 +245,57 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
206
245
|
return output;
|
207
246
|
}
|
208
247
|
|
248
|
+
#formatLayoutShift(
|
249
|
+
shift: Trace.Types.Events.SyntheticLayoutShift, index: number,
|
250
|
+
rootCauses?: Trace.Insights.Models.CLSCulprits.LayoutShiftRootCausesData): string {
|
251
|
+
const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
|
252
|
+
|
253
|
+
const potentialRootCauses: string[] = [];
|
254
|
+
if (rootCauses) {
|
255
|
+
rootCauses.iframes.forEach(
|
256
|
+
iframe => potentialRootCauses.push(
|
257
|
+
`- An iframe (id: ${iframe.frame}, url: ${iframe.url ?? 'unknown'} was injected into the page)`));
|
258
|
+
rootCauses.webFonts.forEach(req => {
|
259
|
+
potentialRootCauses.push(`- A font that was loaded over the network: ${this.#formatRequestUrl(req)}.`);
|
260
|
+
});
|
261
|
+
rootCauses.nonCompositedAnimations.forEach(nonCompositedFailure => {
|
262
|
+
potentialRootCauses.push('- A non-composited animation:');
|
263
|
+
|
264
|
+
const animationInfoOutput = [];
|
265
|
+
potentialRootCauses.push(`- non-composited animation: \`${nonCompositedFailure.name || '(unnamed)'}\``);
|
266
|
+
if (nonCompositedFailure.name) {
|
267
|
+
animationInfoOutput.push(`Animation name: ${nonCompositedFailure.name}`);
|
268
|
+
}
|
269
|
+
if (nonCompositedFailure.unsupportedProperties) {
|
270
|
+
animationInfoOutput.push('Unsupported CSS properties:');
|
271
|
+
animationInfoOutput.push('- ' + nonCompositedFailure.unsupportedProperties.join(', '));
|
272
|
+
}
|
273
|
+
animationInfoOutput.push('Failure reasons:');
|
274
|
+
animationInfoOutput.push(' - ' + nonCompositedFailure.failureReasons.join(', '));
|
275
|
+
|
276
|
+
// Extra padding to the detail to not mess up the indentation.
|
277
|
+
potentialRootCauses.push(animationInfoOutput.map(l => ' '.repeat(4) + l).join('\n'));
|
278
|
+
});
|
279
|
+
|
280
|
+
rootCauses.unsizedImages.forEach(img => {
|
281
|
+
// TODO(b/413284569): if we store a nice human readable name for this
|
282
|
+
// image in the trace metadata, we can do something much nicer here.
|
283
|
+
const url = img.paintImageEvent.args.data.url;
|
284
|
+
const nodeName = img.paintImageEvent.args.data.nodeName;
|
285
|
+
const extraText = url ? `url: ${this.#formatUrl(url)}` : `id: ${img.backendNodeId}`;
|
286
|
+
potentialRootCauses.push(`- An unsized image (${nodeName}) (${extraText}).`);
|
287
|
+
});
|
288
|
+
}
|
289
|
+
const rootCauseText = potentialRootCauses.length ? `- Potential root causes:\n ${potentialRootCauses.join('\n')}` :
|
290
|
+
'- No potential root causes identified';
|
291
|
+
|
292
|
+
const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
|
293
|
+
return `### Layout shift ${index + 1}:
|
294
|
+
- Start time: ${millis(startTime)}
|
295
|
+
- Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
|
296
|
+
${rootCauseText}`;
|
297
|
+
}
|
298
|
+
|
209
299
|
/**
|
210
300
|
* Create an AI prompt string out of the CLS Culprits Insight model to use with Ask AI.
|
211
301
|
* @param insight The CLS Culprits Model to query.
|
@@ -214,7 +304,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
214
304
|
formatClsCulpritsInsight(insight: Trace.Insights.Models.CLSCulprits.CLSCulpritsInsightModel): string {
|
215
305
|
const {worstCluster, shifts} = insight;
|
216
306
|
if (!worstCluster) {
|
217
|
-
return '';
|
307
|
+
return 'No layout shifts were found.';
|
218
308
|
}
|
219
309
|
|
220
310
|
const baseTime = this.#parsedTrace.data.Meta.traceBounds.min;
|
@@ -225,7 +315,7 @@ export class PerformanceInsightFormatter extends PerformanceTraceFormatter {
|
|
225
315
|
} as const;
|
226
316
|
|
227
317
|
const shiftsFormatted = worstCluster.events.map((layoutShift, index) => {
|
228
|
-
return
|
318
|
+
return this.#formatLayoutShift(layoutShift, index, shifts.get(layoutShift));
|
229
319
|
});
|
230
320
|
|
231
321
|
return `The worst layout shift cluster was the cluster that started at ${
|
@@ -378,8 +468,9 @@ Duplication grouped by Node modules: ${filesFormatted}`;
|
|
378
468
|
const url = new Common.ParsedURL.ParsedURL(font.request.args.data.url);
|
379
469
|
fontName = url.isValid ? url.lastPathComponent : '(not available)';
|
380
470
|
}
|
381
|
-
output += `\n - Font name: ${fontName}, URL: ${
|
382
|
-
font.display}', Wasted time: ${
|
471
|
+
output += `\n - Font name: ${fontName}, URL: ${
|
472
|
+
this.#formatRequestUrl(font.request)}, Property 'font-display' set to: '${font.display}', Wasted time: ${
|
473
|
+
this.#formatMilli(font.wastedTime)}.`;
|
383
474
|
}
|
384
475
|
|
385
476
|
output += '\n\n' + Trace.Insights.Models.FontDisplay.UIStrings.description;
|
@@ -463,7 +554,7 @@ Duplication grouped by Node modules: ${filesFormatted}`;
|
|
463
554
|
})
|
464
555
|
.join('\n');
|
465
556
|
|
466
|
-
return `### ${image.request
|
557
|
+
return `### ${this.#formatRequestUrl(image.request)}
|
467
558
|
- Potential savings: ${bytes(image.byteSavings)}
|
468
559
|
- Optimizations:\n${optimizations}`;
|
469
560
|
})
|
@@ -574,7 +665,9 @@ ${checklistBulletPoints.map(point => `- ${point.name}: ${point.passed ? 'PASSED'
|
|
574
665
|
|
575
666
|
const filesFormatted =
|
576
667
|
Array.from(legacyJavaScriptResults)
|
577
|
-
.map(
|
668
|
+
.map(
|
669
|
+
([script, result]) =>
|
670
|
+
`\n- Script: ${this.#formatScriptUrl(script)} - Wasted bytes: ${result.estimatedByteSavings} bytes
|
578
671
|
Matches:
|
579
672
|
${result.matches.map(match => `Line: ${match.line}, Column: ${match.column}, Name: ${match.name}`).join('\n')}`)
|
580
673
|
.join('\n');
|
@@ -625,7 +718,7 @@ ${requestSummary}`;
|
|
625
718
|
function formatNode(
|
626
719
|
this: PerformanceInsightFormatter, node: Trace.Insights.Models.NetworkDependencyTree.CriticalRequestNode,
|
627
720
|
indent: string): string {
|
628
|
-
const url = node.request
|
721
|
+
const url = this.#formatRequestUrl(node.request);
|
629
722
|
const time = this.#formatMicro(node.timeFromInitialRequest);
|
630
723
|
const isLongest = node.isLongest ? ' (longest chain)' : '';
|
631
724
|
let nodeString = `${indent}- ${url} (${time})${isLongest}\n`;
|
@@ -1059,45 +1152,3 @@ Polyfills and transforms enable older browsers to use new JavaScript features. H
|
|
1059
1152
|
}
|
1060
1153
|
}
|
1061
1154
|
}
|
1062
|
-
|
1063
|
-
export class TraceEventFormatter {
|
1064
|
-
static layoutShift(
|
1065
|
-
shift: Trace.Types.Events.SyntheticLayoutShift, index: number, parsedTrace: Trace.TraceModel.ParsedTrace,
|
1066
|
-
rootCauses?: Trace.Insights.Models.CLSCulprits.LayoutShiftRootCausesData): string {
|
1067
|
-
const baseTime = parsedTrace.data.Meta.traceBounds.min;
|
1068
|
-
|
1069
|
-
const potentialRootCauses: string[] = [];
|
1070
|
-
if (rootCauses) {
|
1071
|
-
rootCauses.iframes.forEach(
|
1072
|
-
iframe => potentialRootCauses.push(
|
1073
|
-
`An iframe (id: ${iframe.frame}, url: ${iframe.url ?? 'unknown'} was injected into the page)`));
|
1074
|
-
rootCauses.webFonts.forEach(req => {
|
1075
|
-
potentialRootCauses.push(`A font that was loaded over the network (${req.args.data.url}).`);
|
1076
|
-
});
|
1077
|
-
// TODO(b/413285103): use the nice strings for non-composited animations.
|
1078
|
-
// The code for this lives in TimelineUIUtils but that cannot be used
|
1079
|
-
// within models. We should move it and then expose the animations info
|
1080
|
-
// more nicely.
|
1081
|
-
rootCauses.nonCompositedAnimations.forEach(_ => {
|
1082
|
-
potentialRootCauses.push('A non composited animation.');
|
1083
|
-
});
|
1084
|
-
rootCauses.unsizedImages.forEach(img => {
|
1085
|
-
// TODO(b/413284569): if we store a nice human readable name for this
|
1086
|
-
// image in the trace metadata, we can do something much nicer here.
|
1087
|
-
const url = img.paintImageEvent.args.data.url;
|
1088
|
-
const nodeName = img.paintImageEvent.args.data.nodeName;
|
1089
|
-
const extraText = url ? `url: ${url}` : `id: ${img.backendNodeId}`;
|
1090
|
-
potentialRootCauses.push(`An unsized image (${nodeName}) (${extraText}).`);
|
1091
|
-
});
|
1092
|
-
}
|
1093
|
-
const rootCauseText = potentialRootCauses.length ?
|
1094
|
-
`- Potential root causes:\n - ${potentialRootCauses.join('\n - ')}` :
|
1095
|
-
'- No potential root causes identified';
|
1096
|
-
|
1097
|
-
const startTime = Trace.Helpers.Timing.microToMilli(Trace.Types.Timing.Micro(shift.ts - baseTime));
|
1098
|
-
return `### Layout shift ${index + 1}:
|
1099
|
-
- Start time: ${millis(startTime)}
|
1100
|
-
- Score: ${shift.args.data?.weighted_score_delta.toFixed(4)}
|
1101
|
-
${rootCauseText}`;
|
1102
|
-
}
|
1103
|
-
}
|