chrome-devtools-frontend 1.0.1613625 → 1.0.1615539

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 (64) hide show
  1. package/AUTHORS +1 -0
  2. package/docs/contributing/infrastructure.md +0 -1
  3. package/front_end/core/common/VersionController.ts +17 -1
  4. package/front_end/core/host/UserMetrics.ts +0 -1
  5. package/front_end/core/root/ExperimentNames.ts +0 -1
  6. package/front_end/core/sdk/OverlayModel.ts +2 -4
  7. package/front_end/core/sdk/sdk-meta.ts +13 -0
  8. package/front_end/entrypoints/device_mode_emulation_frame/device_mode_emulation_frame.ts +4 -0
  9. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -1
  10. package/front_end/entrypoints/greendev_floaty/floaty.css +3 -0
  11. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -1
  12. package/front_end/entrypoints/main/MainImpl.ts +0 -6
  13. package/front_end/entrypoints/shell/shell.ts +4 -0
  14. package/front_end/entrypoints/trace_app/trace_app.ts +4 -0
  15. package/front_end/generated/InspectorBackendCommands.ts +6 -4
  16. package/front_end/generated/protocol-mapping.d.ts +14 -0
  17. package/front_end/generated/protocol-proxy-api.d.ts +10 -0
  18. package/front_end/generated/protocol.ts +33 -3
  19. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +10 -2
  20. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +23 -7
  21. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +4 -1
  22. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +200 -46
  23. package/front_end/models/issues_manager/IssuesManager.ts +4 -0
  24. package/front_end/models/javascript_metadata/NativeFunctions.js +673 -639
  25. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +161 -0
  26. package/front_end/models/stack_trace/StackTrace.ts +18 -0
  27. package/front_end/models/stack_trace/StackTraceImpl.ts +96 -4
  28. package/front_end/models/stack_trace/StackTraceModel.ts +39 -0
  29. package/front_end/models/stack_trace/Trie.ts +21 -0
  30. package/front_end/models/stack_trace/stack_trace_impl.ts +2 -0
  31. package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +55 -14
  32. package/front_end/panels/ai_assistance/components/ChatView.ts +4 -3
  33. package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +4 -1
  34. package/front_end/panels/ai_assistance/components/optInChangeDialog.css +1 -2
  35. package/front_end/panels/application/WebMCPView.ts +270 -18
  36. package/front_end/panels/application/components/ProtocolHandlersView.ts +2 -2
  37. package/front_end/panels/application/webMCPView.css +4 -1
  38. package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +7 -0
  39. package/front_end/panels/console/ConsoleContextSelector.ts +1 -1
  40. package/front_end/panels/console/ConsoleViewMessage.ts +8 -2
  41. package/front_end/panels/console/consoleView.css +4 -0
  42. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -3
  43. package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -2
  44. package/front_end/panels/network/RequestConditionsDrawer.ts +4 -2
  45. package/front_end/panels/network/RequestPayloadView.ts +8 -3
  46. package/front_end/panels/network/RequestTimingView.ts +6 -7
  47. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +7 -5
  48. package/front_end/third_party/chromium/README.chromium +1 -1
  49. package/front_end/third_party/codemirror/codemirror-tsconfig.json +4 -4
  50. package/front_end/third_party/lighthouse/lighthouse-tsconfig.json +1 -1
  51. package/front_end/tsconfig.json +2 -1
  52. package/front_end/ui/legacy/EmptyWidget.ts +2 -2
  53. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -2
  54. package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +4 -5
  55. package/front_end/ui/legacy/components/source_frame/XMLView.ts +12 -7
  56. package/front_end/ui/lit/lit.ts +4 -1
  57. package/front_end/ui/lit/render.ts +81 -0
  58. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -1
  59. package/package.json +1 -1
  60. /package/front_end/third_party/codemirror/package/addon/runmode/{runmode-standalone.mjs.d.ts → runmode-standalone.d.mts} +0 -0
  61. /package/front_end/third_party/codemirror/package/mode/css/{css.mjs.d.ts → css.d.mts} +0 -0
  62. /package/front_end/third_party/codemirror/package/mode/javascript/{javascript.mjs.d.ts → javascript.d.mts} +0 -0
  63. /package/front_end/third_party/codemirror/package/mode/xml/{xml.mjs.d.ts → xml.d.mts} +0 -0
  64. /package/front_end/third_party/lighthouse/report-assets/{report-generator.mjs.d.ts → report-generator.d.mts} +0 -0
@@ -49,6 +49,13 @@ const UIStringsNotTranslated = {
49
49
  } as const;
50
50
  const lockedString = i18n.i18n.lockedString;
51
51
 
52
+ /**
53
+ * Labels used to identify specific periods or categories in the trace for getting main thread summary.
54
+ * Supports hardcoded phases, dynamic navigation IDs (`NAVIGATION_X`), and insight models.
55
+ */
56
+ type MainThreadSectionLabel = 'nav-to-lcp'|'lcp-ttfb'|'lcp-render-delay'|'trace-bounds'|'NO_NAVIGATION'|
57
+ `NAVIGATION_${string}`|keyof Trace.Insights.Types.InsightModels;
58
+
52
59
  /**
53
60
  * WARNING: preamble defined in code is only used when userTier is
54
61
  * TESTERS. Otherwise, a server-side preamble is used (see
@@ -102,7 +109,8 @@ You can also use this key with \`selectEventByKey\` to show the user a specific
102
109
 
103
110
  ## Step-by-step instructions for debugging performance issues
104
111
 
105
- Note: if the user asks a specific question about the trace (such as "What is my LCP?", or "How many requests were render-blocking?", directly answer their question and skip starting a performance investigation. Otherwise, your task is to collaborate with the user to discover and resolve real performance issues.
112
+ Note: if the user asks a specific question about the trace (such as "What is my LCP?", or "How many requests were render-blocking?"), directly answer their question using available data. However, if the user asks a general question like "What performance issues exist?" or requests an investigation, you MUST NOT give a generic answer. You must treat it as a full performance investigation (Step 1) and call main thread functions to find specific issues. Generic advice like "reduce long tasks" without specific details is UNACCEPTABLE.
113
+
106
114
 
107
115
  ### Step 1: Determine a performance problem to investigate
108
116
 
@@ -138,11 +146,22 @@ Note: if the user asks a specific question about the trace (such as "What is my
138
146
 
139
147
  ## Guidelines
140
148
 
149
+ - You must call \`getMainThreadTrackSummary\` (by specifying a time range) or \`getMainThreadTrackSummaryByLabel\` (with the relevant label) to investigate the main thread activity before giving the user a reply or suggesting solutions for any performance problem or insight. Call \`getMainThreadTrackSummary\` with specific bounds when you identify a specific time range of interest from the initial data. This applies even if you already have some information about that period from \`getInsightDetails\` or the initial trace summary.
150
+ - Dig Deeper: Before replying, you should really dig into the main thread activity to uncover what the performance issues actually are. Use the initially provided main thread data as a reference to identify interesting tasks or time ranges, and then use those time bounds to call functions like \`getMainThreadTrackSummary\` to get more detailed data. Do not solely rely on the information from the initial data; ensure you identify the root cause before suggesting solutions.
151
+ - No Shortcutting: Even if the initial facts contain specific line numbers or function names, you are not allowed to reply using only that information. You MUST call \`getMainThreadTrackSummary\` with the time bounds of the task to inspect its full context and children before describing it to the user.
152
+ - Look for Aggregated Cost: Performance issues are not always caused by a single "Long Task". Many small, frequent events (like unthrottled \`mousemove\` or \`scroll\` handlers) can add up to significant main thread blockage. Use the Bottom-Up summary in \`getMainThreadTrackSummary\` to identify functions with high total time, even if they are not associated with a Long Task.
141
153
  - Use the provided functions to get detailed performance data. Prioritize functions that provide context relevant to the performance issue being investigated.
142
154
  - Before finalizing your advice, look over it and validate using any relevant functions. If something seems off, refine the advice before giving it to the user.
143
155
  - Base your analysis and advice solely on the data retrieved through the provided functions. Always use the provided functions to gather sufficient data when needed.
144
156
  - Use absolute microsecond timestamps for any function that requires a \`min\` and \`max\` bounds. These timestamps can be found in the trace summary or within the details of an insight.
145
157
  - Example: If the trace bounds are {min: 1000, max: 5000} and you want to investigate a specific interaction that happened between 2000 and 3000, you should call \`getMainThreadTrackSummary({min: 2000, max: 3000})\`.
158
+ - Available labels for \`getMainThreadTrackSummaryByLabel\` include:
159
+ - \`trace-bounds\` (entire trace)
160
+ - \`nav-to-lcp\` (navigation to LCP)
161
+ - \`lcp-ttfb\` (LCP TTFB phase)
162
+ - \`lcp-render-delay\` (LCP render delay phase)
163
+ - Insight names: \`LCPBreakdown\`, \`CLSCulprits\`, \`RenderBlocking\`, \`NetworkDependencyTree\`, \`ImageDelivery\`, \`FontDisplay\`, \`ThirdParties\`, \`ForcedReflow\`, \`Cache\`, \`DOMSize\`
164
+ - Navigation IDs: \`NAVIGATION_0\`, \`NAVIGATION_1\`, etc.
146
165
  - Use \`getEventByKey\` to get data on a specific trace event. This is great for root-cause analysis or validating any assumptions.
147
166
  - Provide clear, actionable recommendations. Avoid technical jargon unless necessary, and explain any technical terms used.
148
167
  - If you see a generic task like "Task", "Evaluate script" or "(anonymous)" in the main thread activity, try to look at its children to see what actual functions are executed and refer to those. When referencing the main thread activity, be as specific as you can. Ensure you identify to the user relevant functions and which script they were defined in. Avoid referencing "Task", "Evaluate script" and "(anonymous)" nodes if possible and instead focus on their children.
@@ -413,6 +432,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
413
432
  * we only show it once.
414
433
  */
415
434
  #hasShownWidgetForInsightSet = new WeakSet<Trace.Insights.Types.InsightSet>();
435
+ #hasShownWidgetForCallTree = new WeakSet<AICallTree>();
416
436
 
417
437
  get preamble(): string {
418
438
  return buildPreamble();
@@ -453,16 +473,44 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
453
473
  contextDisclosure.push(...this.#additionalSelectionsForQuery);
454
474
 
455
475
  const widgets: AiWidget[] = [];
456
- const primaryInsightSet = context.getItem().primaryInsightSet;
457
- if (primaryInsightSet && !this.#hasShownWidgetForInsightSet.has(primaryInsightSet)) {
458
- widgets.push({
459
- name: 'CORE_VITALS',
460
- data: {
461
- parsedTrace: context.getItem().parsedTrace,
462
- insightSetKey: primaryInsightSet.id,
463
- },
464
- });
465
- this.#hasShownWidgetForInsightSet.add(primaryInsightSet);
476
+ const focus = context.getItem();
477
+
478
+ // If the user has selected a specific task (call tree) as context, show the summary and bottom-up tree for it.
479
+ // Otherwise, show the high-level Core Web Vitals widget for the trace or insight.
480
+ if (focus.callTree && !this.#hasShownWidgetForCallTree.has(focus.callTree)) {
481
+ const event = focus.callTree.selectedNode?.event;
482
+ if (event) {
483
+ const {startTime, endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(event);
484
+ const bounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime);
485
+ widgets.push({
486
+ name: 'TIMELINE_RANGE_SUMMARY',
487
+ data: {
488
+ bounds,
489
+ parsedTrace: focus.parsedTrace,
490
+ track: 'main',
491
+ },
492
+ });
493
+ widgets.push({
494
+ name: 'BOTTOM_UP_TREE',
495
+ data: {
496
+ bounds,
497
+ parsedTrace: focus.parsedTrace,
498
+ },
499
+ });
500
+ this.#hasShownWidgetForCallTree.add(focus.callTree);
501
+ }
502
+ } else {
503
+ const primaryInsightSet = focus.primaryInsightSet;
504
+ if (primaryInsightSet && !this.#hasShownWidgetForInsightSet.has(primaryInsightSet)) {
505
+ widgets.push({
506
+ name: 'CORE_VITALS',
507
+ data: {
508
+ parsedTrace: focus.parsedTrace,
509
+ insightSetKey: primaryInsightSet.id,
510
+ },
511
+ });
512
+ this.#hasShownWidgetForInsightSet.add(primaryInsightSet);
513
+ }
466
514
  }
467
515
 
468
516
  yield {
@@ -777,6 +825,52 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
777
825
  this.#functionCallCacheForFocus.set(focus, cache);
778
826
  }
779
827
 
828
+ async #handleMainThreadTrackSummary(
829
+ bounds: Trace.Types.Timing.TraceWindowMicro,
830
+ focus: AgentFocus,
831
+ functionName: string,
832
+ cacheKey: string,
833
+ ): Promise<FunctionCallHandlerResult<{summary: string}>> {
834
+ const formatter = this.#formatter;
835
+ if (!formatter) {
836
+ throw new Error('missing formatter');
837
+ }
838
+ const summary = await formatter.formatMainThreadTrackSummary(bounds);
839
+ if (this.#isFunctionResponseTooLarge(summary)) {
840
+ return {
841
+ error:
842
+ `${functionName} response is too large. Try investigating using other functions, or a more narrow bounds`,
843
+ };
844
+ }
845
+
846
+ const byteCount = Platform.StringUtilities.countWtf8Bytes(summary);
847
+ Host.userMetrics.performanceAIMainThreadActivityResponseSize(byteCount);
848
+
849
+ this.#cacheFunctionResult(focus, cacheKey, summary);
850
+ const widgets: AiWidget[] = [];
851
+ widgets.push({
852
+ name: 'TIMELINE_RANGE_SUMMARY',
853
+ data: {
854
+ parsedTrace: focus.parsedTrace,
855
+ bounds,
856
+ track: 'main',
857
+ },
858
+ });
859
+
860
+ widgets.push({
861
+ name: 'BOTTOM_UP_TREE',
862
+ data: {
863
+ bounds,
864
+ parsedTrace: focus.parsedTrace,
865
+ },
866
+ });
867
+
868
+ return {
869
+ result: {summary},
870
+ widgets,
871
+ };
872
+ }
873
+
780
874
  #declareFunctions(context: PerformanceTraceContext): void {
781
875
  const focus = context.getItem();
782
876
  const {parsedTrace} = focus;
@@ -972,53 +1066,51 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
972
1066
  handler: async args => {
973
1067
  debugLog('Function call: getMainThreadTrackSummary');
974
1068
 
975
- if (!this.#formatter) {
976
- throw new Error('missing formatter');
977
- }
978
-
979
1069
  const bounds = createBounds(args.min, args.max);
980
1070
  if (!bounds) {
981
1071
  return {error: 'invalid bounds'};
982
1072
  }
983
1073
 
984
- const formatter = this.#formatter;
985
- const summary = await formatter.formatMainThreadTrackSummary(bounds);
986
- if (this.#isFunctionResponseTooLarge(summary)) {
987
- return {
988
- error:
989
- 'getMainThreadTrackSummary response is too large. Try investigating using other functions, or a more narrow bounds',
990
- };
991
- }
992
-
993
- const byteCount = Platform.StringUtilities.countWtf8Bytes(summary);
994
- Host.userMetrics.performanceAIMainThreadActivityResponseSize(byteCount);
995
-
996
1074
  const key = `getMainThreadTrackSummary({min: ${bounds.min}, max: ${bounds.max}})`;
997
- this.#cacheFunctionResult(focus, key, summary);
998
- const widgets: AiWidget[] = [];
999
- widgets.push({
1000
- name: 'TIMELINE_RANGE_SUMMARY',
1001
- data: {
1002
- parsedTrace,
1003
- bounds,
1004
- track: 'main',
1005
- },
1006
- });
1075
+ return await this.#handleMainThreadTrackSummary(bounds, focus, 'getMainThreadTrackSummary', key);
1076
+ },
1007
1077
 
1008
- widgets.push({
1009
- name: 'BOTTOM_UP_TREE',
1010
- data: {
1011
- bounds,
1012
- parsedTrace,
1013
- },
1014
- });
1078
+ });
1015
1079
 
1080
+ this.declareFunction<{label: MainThreadSectionLabel}, {summary: string}>('getMainThreadTrackSummaryByLabel', {
1081
+ description:
1082
+ 'Returns a focused, detailed summary of the main thread for a predefined labeled period. Use this to get more relevant detail than the initial trace summary before diagnosing issues.',
1083
+ parameters: {
1084
+ type: Host.AidaClient.ParametersTypes.OBJECT,
1085
+ description: '',
1086
+ nullable: false,
1087
+ properties: {
1088
+ label: {
1089
+ type: Host.AidaClient.ParametersTypes.STRING,
1090
+ description:
1091
+ 'The label of the period to investigate (e.g., \'LCPBreakdown\', \'CLSCulprits\', \'nav-to-lcp\').',
1092
+ nullable: false,
1093
+ },
1094
+ },
1095
+ required: ['label']
1096
+ },
1097
+ displayInfoFromArgs: args => {
1016
1098
  return {
1017
- result: {summary},
1018
- widgets,
1099
+ title: lockedString(UIStringsNotTranslated.mainThreadActivity),
1100
+ action: `getMainThreadTrackSummaryByLabel('${args.label}')`
1019
1101
  };
1020
1102
  },
1103
+ handler: async args => {
1104
+ debugLog('Function call: getMainThreadTrackSummaryByLabel');
1105
+
1106
+ const bounds = this.#getBoundsForLabel(args.label, focus);
1107
+ if (!bounds) {
1108
+ return {error: `Invalid label: ${args.label}`};
1109
+ }
1021
1110
 
1111
+ const key = `getMainThreadTrackSummaryByLabel('${args.label}')`;
1112
+ return await this.#handleMainThreadTrackSummary(bounds, focus, 'getMainThreadTrackSummaryByLabel', key);
1113
+ },
1022
1114
  });
1023
1115
 
1024
1116
  this.declareFunction<
@@ -1362,6 +1454,68 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1362
1454
  }
1363
1455
  }
1364
1456
 
1457
+ #getBoundsForLabel(label: MainThreadSectionLabel, focus: AgentFocus): Trace.Types.Timing.TraceWindowMicro|null {
1458
+ const {parsedTrace} = focus;
1459
+ const insightSet = focus.primaryInsightSet;
1460
+
1461
+ if (label === 'nav-to-lcp') {
1462
+ if (insightSet) {
1463
+ const lcp = Trace.Insights.Common.getLCP(insightSet);
1464
+ if (lcp) {
1465
+ return Trace.Helpers.Timing.traceWindowFromMicroSeconds(
1466
+ insightSet.bounds.min, lcp.event.ts as Trace.Types.Timing.Micro);
1467
+ }
1468
+ }
1469
+ return null;
1470
+ }
1471
+
1472
+ if (label === 'lcp-ttfb') {
1473
+ if (insightSet) {
1474
+ const subparts = insightSet.model.LCPBreakdown?.subparts;
1475
+ if (subparts?.ttfb) {
1476
+ return subparts.ttfb;
1477
+ }
1478
+ }
1479
+ return null;
1480
+ }
1481
+
1482
+ if (label === 'lcp-render-delay') {
1483
+ if (insightSet) {
1484
+ const subparts = insightSet.model.LCPBreakdown?.subparts;
1485
+ if (subparts?.renderDelay) {
1486
+ return subparts.renderDelay;
1487
+ }
1488
+ }
1489
+ return null;
1490
+ }
1491
+
1492
+ if (label === 'trace-bounds') {
1493
+ return parsedTrace.data.Meta.traceBounds;
1494
+ }
1495
+
1496
+ for (const is of parsedTrace.insights?.values() ?? []) {
1497
+ if (is.id === label) {
1498
+ return is.bounds;
1499
+ }
1500
+ }
1501
+
1502
+ if (insightSet) {
1503
+ const model = insightSet.model[label as keyof Trace.Insights.Types.InsightModels];
1504
+ if (model) {
1505
+ return Trace.Insights.Common.insightBounds(model, insightSet.bounds);
1506
+ }
1507
+ }
1508
+
1509
+ for (const is of parsedTrace.insights?.values() ?? []) {
1510
+ const model = is.model[label as keyof Trace.Insights.Types.InsightModels];
1511
+ if (model) {
1512
+ return Trace.Insights.Common.insightBounds(model, is.bounds);
1513
+ }
1514
+ }
1515
+
1516
+ return null;
1517
+ }
1518
+
1365
1519
  async addElementAnnotation(elementId: string, annotationMessage: string):
1366
1520
  Promise<FunctionCallHandlerResult<unknown>> {
1367
1521
  if (!Annotations.AnnotationRepository.annotationsEnabled()) {
@@ -155,6 +155,10 @@ const issueCodeHandlers = new Map<
155
155
  ],
156
156
  ]);
157
157
 
158
+ export function isIssueCodeSupported(code: Protocol.Audits.InspectorIssueCode): boolean {
159
+ return issueCodeHandlers.has(code);
160
+ }
161
+
158
162
  /**
159
163
  * Each issue reported by the backend can result in multiple `Issue` instances.
160
164
  * Handlers are simple functions hard-coded into a map.