chrome-devtools-frontend 1.0.1672388 → 1.0.1672557

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 (103) hide show
  1. package/eslint.config.mjs +3 -3
  2. package/front_end/core/root/Runtime.ts +0 -5
  3. package/front_end/generated/{SupportedCSSProperties.js → SupportedCSSProperties.ts} +16 -0
  4. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
  5. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +4 -3
  6. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +1 -1
  7. package/front_end/models/emulation/EmulatedDevices.ts +1 -1
  8. package/front_end/models/trace/Processor.ts +42 -10
  9. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +12 -19
  10. package/front_end/models/trace/handlers/MetaHandler.ts +38 -5
  11. package/front_end/models/trace/insights/CLSCulprits.ts +1 -2
  12. package/front_end/models/trace/insights/CharacterSet.ts +1 -1
  13. package/front_end/models/trace/insights/Common.ts +21 -2
  14. package/front_end/models/trace/insights/DocumentLatency.ts +1 -1
  15. package/front_end/models/trace/insights/LCPBreakdown.ts +7 -6
  16. package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
  17. package/front_end/models/trace/insights/ModernHTTP.ts +7 -3
  18. package/front_end/models/trace/insights/NetworkDependencyTree.ts +1 -1
  19. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  20. package/front_end/models/trace/insights/ThirdParties.ts +5 -2
  21. package/front_end/models/trace/insights/types.ts +11 -6
  22. package/front_end/models/trace/types/Configuration.ts +5 -0
  23. package/front_end/panels/elements/ElementsTreeElement.ts +1 -2
  24. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +3 -1
  25. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +463 -13
  26. package/front_end/panels/timeline/TimelinePanel.ts +2 -0
  27. package/front_end/panels/timeline/components/CWVMetrics.ts +16 -3
  28. package/front_end/panels/timeline/components/cwvMetrics.css +4 -0
  29. package/front_end/panels/timeline/components/liveMetricsView.css +0 -17
  30. package/front_end/panels/timeline/components/metricValueStyles.css +17 -0
  31. package/front_end/third_party/chromium/README.chromium +1 -1
  32. package/front_end/third_party/puppeteer/README.chromium +2 -2
  33. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +64 -15
  34. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +65 -16
  35. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +50 -7
  36. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  37. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  38. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts +2 -1
  39. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts.map +1 -1
  40. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +5 -5
  41. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
  42. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts +2 -1
  43. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts.map +1 -1
  44. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js +8 -6
  45. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js.map +1 -1
  46. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.d.ts.map +1 -1
  47. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.js +3 -0
  48. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Dialog.js.map +1 -1
  49. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  50. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +16 -1
  51. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  52. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.d.ts +5 -1
  53. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.d.ts.map +1 -1
  54. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js +11 -6
  55. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js.map +1 -1
  56. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.d.ts.map +1 -1
  57. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.js +5 -0
  58. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Dialog.js.map +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +10 -0
  61. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +4 -3
  63. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +27 -2
  65. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +12 -1
  67. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
  68. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +2 -2
  69. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
  70. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +2 -2
  71. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
  72. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js +2 -0
  74. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +2 -1
  76. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
  77. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +5 -4
  78. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
  79. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  80. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  81. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/types.d.ts +64 -15
  84. package/front_end/third_party/puppeteer/package/package.json +2 -2
  85. package/front_end/third_party/puppeteer/package/src/api/Page.ts +50 -7
  86. package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +9 -7
  87. package/front_end/third_party/puppeteer/package/src/bidi/Connection.ts +9 -6
  88. package/front_end/third_party/puppeteer/package/src/bidi/Dialog.ts +4 -0
  89. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +24 -1
  90. package/front_end/third_party/puppeteer/package/src/cdp/Connection.ts +11 -6
  91. package/front_end/third_party/puppeteer/package/src/cdp/Dialog.ts +7 -0
  92. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +11 -0
  93. package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +7 -3
  94. package/front_end/third_party/puppeteer/package/src/common/Debug.ts +30 -5
  95. package/front_end/third_party/puppeteer/package/src/common/util.ts +2 -2
  96. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +2 -0
  97. package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +6 -4
  98. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  99. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  100. package/front_end/ui/visual_logging/KnownContextValues.ts +16 -0
  101. package/package.json +1 -1
  102. /package/front_end/core/host/{UserMetricsEnums.d.ts → UserMetricsEnums.ts} +0 -0
  103. /package/front_end/generated/{ARIAProperties.js → ARIAProperties.ts} +0 -0
package/eslint.config.mjs CHANGED
@@ -29,7 +29,7 @@ export default defineConfig([
29
29
  'front_end/diff/diff_match_patch.js',
30
30
  'front_end/models/javascript_metadata/NativeFunctions.js',
31
31
  // All of these scripts are auto-generated so don't lint them.
32
- 'front_end/generated/ARIAProperties.js',
32
+ 'front_end/generated/ARIAProperties.ts',
33
33
  'front_end/generated/Deprecation.ts',
34
34
  'front_end/generated/InspectorBackendCommands.ts',
35
35
  'front_end/generated/protocol-mapping.d.ts',
@@ -197,7 +197,7 @@ export default defineConfig([
197
197
  radix: 'error',
198
198
  'valid-typeof': 'error',
199
199
  'no-return-assign': ['error', 'always'],
200
- 'no-implicit-coercion': ['error', { allow: ['!!'] }],
200
+ 'no-implicit-coercion': ['error', {allow: ['!!']}],
201
201
 
202
202
  'no-array-constructor': 'error',
203
203
 
@@ -833,7 +833,7 @@ export default defineConfig([
833
833
  },
834
834
  {
835
835
  name: 'Supported CSS properties rules',
836
- files: ['front_end/generated/SupportedCSSProperties.js'],
836
+ files: ['front_end/generated/SupportedCSSProperties.ts'],
837
837
  rules: {
838
838
  '@devtools/jslog-context-list': 'error',
839
839
  },
@@ -453,10 +453,6 @@ interface AiGeneratedTimelineLabels {
453
453
  enabled: boolean;
454
454
  }
455
455
 
456
- interface AllowPopoverForcing {
457
- enabled: boolean;
458
- }
459
-
460
456
  interface GlobalAiButton {
461
457
  enabled: boolean;
462
458
  promotionEnabled: boolean;
@@ -576,7 +572,6 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
576
572
  devToolsAnimationStylesInStylesTab: HostConfigAnimationStylesInStylesTab,
577
573
  devToolsJpegXlImageFormat: HostConfigJpegXlImageFormat,
578
574
  devToolsAiGeneratedTimelineLabels: AiGeneratedTimelineLabels,
579
- devToolsAllowPopoverForcing: AllowPopoverForcing,
580
575
  devToolsGlobalAiButton: GlobalAiButton,
581
576
  devToolsGdpProfiles: GdpProfiles,
582
577
  devToolsGdpProfilesAvailability: GdpProfilesAvailability,
@@ -668,6 +668,7 @@ export const generatedProperties = [
668
668
  "math-shift",
669
669
  "math-style",
670
670
  "max-block-size",
671
+ "max-content-sizing",
671
672
  "max-height",
672
673
  "max-inline-size",
673
674
  "max-lines",
@@ -3915,6 +3916,15 @@ export const generatedProperties = [
3915
3916
  ],
3916
3917
  "name": "max-block-size"
3917
3918
  },
3919
+ {
3920
+ "keywords": [
3921
+ "auto",
3922
+ "shrink-to-fit"
3923
+ ],
3924
+ "name": "max-content-sizing",
3925
+ "runtime_flag": "CssMaxContentSizing",
3926
+ "runtime_flag_status": "test"
3927
+ },
3918
3928
  {
3919
3929
  "keywords": [
3920
3930
  "none"
@@ -8046,6 +8056,12 @@ export const generatedPropertyValues = {
8046
8056
  "none"
8047
8057
  ]
8048
8058
  },
8059
+ "max-content-sizing": {
8060
+ "values": [
8061
+ "auto",
8062
+ "shrink-to-fit"
8063
+ ]
8064
+ },
8049
8065
  "max-height": {
8050
8066
  "values": [
8051
8067
  "none"
@@ -6,7 +6,7 @@ Content:
6
6
  "details": [
7
7
  {
8
8
  "title": "Trace details",
9
- "text": "Trace summary:\nURL: https://web.dev/\nTrace bounds: {min: 465455241690µs, max: 465460435979µs}\nCPU throttling: 1x\nNetwork throttling: No throttling\n\n# Available insight sets\n\nThe following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.\n\n## insight set id: NO_NAVIGATION\n\nURL: https://web.dev/\nBounds: {min: 465455241690µs, max: 465456489730µs}\nMetrics (lab / observed):\n - CLS: 0.00\nMetrics (field / real users): n/a – no data for this page in CrUX\nAvailable insights:\n - insight name: ThirdParties\n description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page’s content.\n relevant trace bounds: {min: 465456492168µs, max: 465460052616µs}\n example question: Which third parties are having the largest impact on my page performance?\n\n## insight set id: NAVIGATION_1\n\nURL: https://web.dev/\nBounds: {min: 465456489730µs, max: 465460435979µs}\nMetrics (lab / observed):\n - LCP: 676 ms, event: (eventKey: r-21246, ts: 465457166052), nodeId: 1680\n - LCP breakdown:\n - TTFB: 553 ms, bounds: {min: 465456489730µs, max: 465457042737µs}\n - Render delay: 123 ms, bounds: {min: 465457042737µs, max: 465457166052µs}\n - CLS: 0.02, event: (eventKey: s-14250, ts: 465457121239)\nMetrics (field / real users): n/a – no data for this page in CrUX\nAvailable insights:\n - insight name: RenderBlocking\n description: Requests are blocking the page’s initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.\n relevant trace bounds: {min: 465457046567µs, max: 465457086893µs}\n estimated metric savings: FCP 118 ms, LCP 118 ms\n example question: Show me the most impactful render-blocking requests that I should focus on\n example question: How can I reduce the number of render-blocking requests?\n - insight name: LCPBreakdown\n description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.\n relevant trace bounds: {min: 465456489730µs, max: 465457166052µs}\n example question: Help me optimize my LCP score\n example question: Which LCP subpart was most problematic?\n example question: What can I do to reduce the LCP time for this page load?\n - insight name: CLSCulprits\n description: Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://developer.chrome.com/docs/performance/insights/cls-culprit), such as elements being added, removed, or their fonts changing as the page loads.\n relevant trace bounds: {min: 465457121239µs, max: 465459012394µs}\n example question: Help me optimize my CLS score\n example question: How can I prevent layout shifts on this page?\n - insight name: NetworkDependencyTree\n description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load.\n relevant trace bounds: {min: 465456490723µs, max: 465458472724µs}\n example question: How do I optimize my network dependency tree?\n - insight name: DOMSize\n description: A large DOM can increase the duration of style calculations and layout reflows, impacting page responsiveness. A large DOM will also increase memory usage. [Learn how to avoid an excessive DOM size](https://developer.chrome.com/docs/performance/insights/dom-size).\n relevant trace bounds: {min: 465458287196µs, max: 465458340745µs}\n example question: How can I reduce the size of my DOM?\n - insight name: ThirdParties\n description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page’s content.\n relevant trace bounds: {min: 465456492168µs, max: 465460052616µs}\n example question: Which third parties are having the largest impact on my page performance?\n - insight name: ForcedReflow\n description: A forced reflow occurs when JavaScript queries geometric properties (such as offsetWidth) after styles have been invalidated by a change to the DOM state. This can result in poor performance. Learn more about [forced reflows](https://developer.chrome.com/docs/performance/insights/forced-reflow) and possible mitigations.\n relevant trace bounds: {min: 465456489730µs, max: 465460435979µs}\n example question: How can I avoid forced reflows and layout thrashing?\n example question: What is forced reflow and why is it problematic?\n - insight name: Cache\n description: A long cache lifetime can speed up repeat visits to your page. [Learn more about caching](https://developer.chrome.com/docs/performance/insights/cache).\n relevant trace bounds: {min: 465457179567µs, max: 465459110674µs}\n estimated metric savings: FCP 0 ms, LCP 0 ms\n estimated wasted bytes: 16 kB\n example question: What caching strategies can I apply to improve my page performance?\n# Critical network requests\n\n## insight set id: NO_NAVIGATION\n\nnone\n\n## insight set id: NAVIGATION_1\n\n\nNetwork requests data:\n\n\n\nallUrls = [0: https://web.dev/, 1: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCxc4AMP6lbBP.woff2, 2: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBxc4AMP6lbBP.woff2, 3: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fABc4AMP6lbBP.woff2, 4: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2, 5: https://fonts.gstatic.com/s/materialicons/v142/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2, 6: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2, 7: https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2, 8: https://web.dev/_pwa/web/manifest.json, 9: https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap, 10: https://fonts.gstatic.com/s/googlesans/v59/4UasrENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RPjIUvbQoi-E.woff2, 11: https://fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block, 12: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/web/css/app.css, 13: https://web.dev/extras.css]\n\n0;s-7302;1 ms;2 ms;568 ms;569 ms;568 ms;15 ms;0.5 ms;200;text/html;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[content-security-policy: base-uri 'self'; object-src 'none'; script-src 'strict-dynamic' 'unsafe-inline' https: http: 'nonce-pLl1WHuNABXXiQLLmUesvDyvzBJZdE' 'unsafe-eval'; report-uri https://csp.withgoogle.com/csp/devsite/v2|content-encoding: gzip|x-content-type-options: nosniff|date: Mon, 29 Apr 2024 11:01:15 GMT|strict-transport-security: max-age=63072000; includeSubdomains; preload|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|pragma: no-cache|last-modified: Fri, 26 Apr 2024 16:43:17 GMT|server: Google Frontend|vary: Cookie, Accept-Encoding|x-frame-options: SAMEORIGIN|content-type: text/html; charset=utf-8|x-cloud-trace-context: <redacted>|cache-control: no-cache, must-revalidate|expires: 0]\n1;s-49309;1,395 ms;1,402 ms;1,415 ms;1,423 ms;28 ms;94 μs;9 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Wed, 24 Apr 2024 15:02:33 GMT|x-content-type-options: nosniff|age: 417214|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:58 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Thu, 24 Apr 2025 15:02:33 GMT]\n2;s-46519;1,348 ms;1,355 ms;1,361 ms;1,423 ms;75 ms;73 μs;62 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Mon, 29 Apr 2024 03:50:51 GMT|x-content-type-options: nosniff|age: 25516|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:41 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Tue, 29 Apr 2025 03:50:51 GMT]\n3;s-46196;1,331 ms;1,339 ms;1,355 ms;1,420 ms;89 ms;0.1 ms;65 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Fri, 26 Apr 2024 20:29:46 GMT|x-content-type-options: nosniff|age: 224781|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:39 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 20:29:46 GMT]\n4;s-45814;1,326 ms;1,331 ms;1,348 ms;1,419 ms;93 ms;77 μs;71 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 13:27:47 GMT|x-content-type-options: nosniff|age: 336500|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:56 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 13:27:47 GMT]\n5;s-44751;1,286 ms;1,307 ms;1,343 ms;1,416 ms;130 ms;1 ms;73 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Fri, 26 Apr 2024 09:49:05 GMT|x-content-type-options: nosniff|age: 263222|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Mon, 08 Apr 2024 19:04:51 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 09:49:05 GMT]\n6;s-44728;1,285 ms;1,307 ms;1,343 ms;1,406 ms;120 ms;1 ms;62 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Sun, 28 Apr 2024 21:44:44 GMT|x-content-type-options: nosniff|age: 47483|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:53 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Mon, 28 Apr 2025 21:44:44 GMT]\n7;s-44701;1,284 ms;1,300 ms;1,339 ms;1,405 ms;120 ms;0.2 ms;65 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 09:35:28 GMT|x-content-type-options: nosniff|age: 350439|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:50 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 09:35:28 GMT]\n8;s-43119;1,751 ms;1,751 ms;1,771 ms;1,771 ms;20 ms;27 μs;0.2 ms;200;application/json;Medium;Medium;Medium;f;unknown;t;0;[];[date: Sun, 28 Apr 2024 14:07:49 GMT|last-modified: Wed, 24 Apr 2024 11:02:59 GMT|server: Google Frontend|age: 75208|content-type: application/json|x-cloud-trace-context: <redacted>|cache-control: public, max-age=86400|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>]\n9;s-7695;557 ms;557 ms;597 ms;597 ms;40 ms;3 ms;0.6 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 11:01:15 GMT|content-encoding: gzip|x-content-type-options: nosniff|strict-transport-security: max-age=31536000|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|x-xss-protection: 0|last-modified: Mon, 29 Apr 2024 10:51:49 GMT|server: ESF|cross-origin-opener-policy: <redacted>|x-frame-options: SAMEORIGIN|content-type: text/css; charset=utf-8|access-control-allow-origin: *|cache-control: private, max-age=86400, stale-while-revalidate=604800|timing-allow-origin: *|link: <https://fonts.gstatic.com>; rel=preconnect; crossorigin|expires: Mon, 29 Apr 2024 11:01:15 GMT]\n7;s-34909;770 ms;770 ms;771 ms;776 ms;6 ms;40 μs;5 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[x-google-security-signals: <redacted>|x-google-gfe-service-trace: <redacted>|content-security-policy-report-only: <redacted>|x-google-scs-row-timestamp: <redacted>|x-google-gfe-response-code-details-trace: <redacted>|cross-origin-resource-policy: <redacted>|x-google-scs-row-key: <redacted>|content-type: font/woff2|access-control-allow-origin: *|x-google-data-version: <redacted>|cache-control: public, max-age=31536000|x-google-gfe-backend-request-info: <redacted>|x-google-dos-service-trace: <redacted>|x-google-backends: <redacted>|date: Thu, 26 Oct 2023 10:46:00 GMT|x-content-type-options: nosniff|expires: Fri, 25 Oct 2024 10:46:00 GMT|x-google-gfe-version: <redacted>|x-google-netmon-label: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-google-service: <redacted>|x-xss-protection: 0|x-google-gfe-handshake-trace: <redacted>|x-google-shellfish-status: <redacted>|last-modified: Wed, 11 May 2022 19:24:50 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|x-google-gfe-request-trace: <redacted>|accept-ranges: bytes|timing-allow-origin: *|x-google-scs-repo: <redacted>]\n10;s-11121;602 ms;602 ms;603 ms;611 ms;9 ms;27 μs;8 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 15:44:03 GMT|x-content-type-options: nosniff|age: 328319|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 24 Apr 2024 23:37:14 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 15:44:03 GMT]\n11;s-7703;557 ms;557 ms;597 ms;597 ms;40 ms;90 μs;0.1 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 11:01:15 GMT|content-encoding: gzip|x-content-type-options: nosniff|strict-transport-security: max-age=31536000|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|x-xss-protection: 0|last-modified: Mon, 29 Apr 2024 11:01:15 GMT|server: ESF|cross-origin-opener-policy: <redacted>|x-frame-options: SAMEORIGIN|content-type: text/css; charset=utf-8|access-control-allow-origin: *|cache-control: private, max-age=86400, stale-while-revalidate=604800|timing-allow-origin: *|link: <https://fonts.gstatic.com>; rel=preconnect; crossorigin|expires: Mon, 29 Apr 2024 11:01:15 GMT]\n5;s-11334;606 ms;606 ms;607 ms;615 ms;9 ms;30 μs;8 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;11;[];[date: Fri, 26 Apr 2024 09:49:05 GMT|x-content-type-options: nosniff|age: 263217|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Mon, 08 Apr 2024 19:04:51 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 09:49:05 GMT]\n12;s-7722;557 ms;557 ms;562 ms;568 ms;11 ms;0.5 ms;6 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 10:56:02 GMT|content-encoding: gzip|x-content-type-options: nosniff|age: 256|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Thu, 25 Apr 2024 19:58:26 GMT|server: sffe|cross-origin-opener-policy: <redacted>|vary: Accept-Encoding|report-to: {\"group\":\"devrel-devsite\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/devrel-devsite\"}]}|content-type: text/css|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|expires: Tue, 29 Apr 2025 10:56:02 GMT]\n13;s-7737;557 ms;557 ms;561 ms;561 ms;4 ms;0.4 ms;0.2 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[content-security-policy: base-uri 'self'; object-src 'none'; script-src 'strict-dynamic' 'unsafe-inline' https: http: 'nonce-laTwEoovJjOKcMoBUjSFaYO6rrF8dU' 'unsafe-eval'; report-uri https://csp.withgoogle.com/csp/devsite/v2|content-encoding: gzip|x-content-type-options: nosniff|date: Mon, 29 Apr 2024 11:00:18 GMT|strict-transport-security: max-age=63072000; includeSubdomains; preload|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|pragma: no-cache|last-modified: Tue, 19 Mar 2024 18:37:07 GMT|server: Google Frontend|vary: Cookie, Accept-Encoding|x-frame-options: SAMEORIGIN|content-type: text/css|x-cloud-trace-context: <redacted>|cache-control: no-cache, must-revalidate|expires: 0]\n\n# Main thread bottom-up summary\n\nThis is the bottom-up summary for the entire trace. Only the top 10 activities (sorted by self time) are shown. An activity is all the aggregated time spent on the same type of work. For example, it can be all the time spent in a specific JavaScript function, or all the time spent in a specific browser rendering stage (like layout, v8 compile, parsing html). \"Self time\" represents the aggregated time spent directly in an activity, across all occurrences. \"Total time\" represents the aggregated time spent in an activity or any of its children.\n\n## insight set id: NO_NAVIGATION\n\n- self: 12 ms, total: 12 ms, source: Profiling overhead\n- self: 4 ms, total: 28 ms, source: Task\n- self: 3 ms, total: 4 ms, source: Recalculate style (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 98, column: 12)\n- self: 2 ms, total: 2 ms, source: Commit\n- self: 0.9 ms, total: 2 ms, source: Function call (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 102, column: 35)\n- self: 0.8 ms, total: 13 ms, source: Evaluate script\n- self: 0.7 ms, total: 3 ms, source: Event: pointerover\n- self: 0.1 ms, total: 1 ms, source: Xh (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 104, column: 61)\n\n## insight set id: NAVIGATION_1\n\n- self: 46 ms, total: 49 ms, source: Recalculate style\n- self: 37 ms, total: 211 ms, source: Task\n- self: 21 ms, total: 22 ms, source: Layout\n- self: 17 ms, total: 19 ms, source: Compile code\n- self: 7 ms, total: 7 ms, source: Cache script code\n- self: 6 ms, total: 26 ms, source: Function call (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 288, column: 146)\n- self: 5 ms, total: 5 ms, source: Parse stylesheet\n- self: 5 ms, total: 5 ms, source: Pre-paint\n- self: 5 ms, total: 5 ms, source: Commit\n- self: 5 ms, total: 10 ms, source: appendChild\n\n# 3rd party summary\n\n## insight set id: NO_NAVIGATION\n\n- name: Google CDN, main thread time: 1 ms, network transfer size: 0 B\n\n## insight set id: NAVIGATION_1\n\n- name: Google CDN, main thread time: 38 ms, network transfer size: 990 B\n- name: web.dev, main thread time: 3 ms, network transfer size: 84.3 kB\n- name: Google Analytics, main thread time: 0.6 ms, network transfer size: 52.9 kB\n- name: Google Fonts, main thread time: 0 ms, network transfer size: 42.2 kB\n\n# Longest tasks\n\n## insight set id: NO_NAVIGATION\n\n- total time: 13 ms, event: (eventKey: r-96, ts: 465455241964)\n- total time: 2 ms, event: (eventKey: r-934, ts: 465455475572)\n- total time: 1 ms, event: (eventKey: r-2310, ts: 465455879141)\n\n## insight set id: NAVIGATION_1\n\n- total time: 18 ms, event: (eventKey: r-20182, ts: 465457150438)\n- total time: 14 ms, event: (eventKey: r-12184, ts: 465457104625)\n- total time: 12 ms, event: (eventKey: r-10779, ts: 465457087373)\n\nUser selected the following call tree:\n\n\n\n# Call tree:\n\n1;r-10779;Task;3;;;2;;\n2;r-11902;Layout;3;3;;;;;S\n\n\n# User query\n\ntest"
9
+ "text": "Trace summary:\nURL: https://web.dev/\nTrace bounds: {min: 465455241690µs, max: 465460435979µs}\nCPU throttling: 1x\nNetwork throttling: No throttling\n\n# Available insight sets\n\nThe following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.\n\n## insight set id: NO_NAVIGATION\n\nURL: https://web.dev/\nBounds: {min: 465455241690µs, max: 465456489729µs}\nMetrics (lab / observed):\n - CLS: 0.00\nMetrics (field / real users): n/a – no data for this page in CrUX\nAvailable insights:\n - insight name: ThirdParties\n description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page’s content.\n relevant trace bounds: {min: 465456492168µs, max: 465460052616µs}\n example question: Which third parties are having the largest impact on my page performance?\n\n## insight set id: NAVIGATION_1\n\nURL: https://web.dev/\nBounds: {min: 465456489730µs, max: 465460435979µs}\nMetrics (lab / observed):\n - LCP: 676 ms, event: (eventKey: r-21246, ts: 465457166052), nodeId: 1680\n - LCP breakdown:\n - TTFB: 553 ms, bounds: {min: 465456489730µs, max: 465457042737µs}\n - Render delay: 123 ms, bounds: {min: 465457042737µs, max: 465457166052µs}\n - CLS: 0.02, event: (eventKey: s-14250, ts: 465457121239)\nMetrics (field / real users): n/a – no data for this page in CrUX\nAvailable insights:\n - insight name: RenderBlocking\n description: Requests are blocking the page’s initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.\n relevant trace bounds: {min: 465457046567µs, max: 465457086893µs}\n estimated metric savings: FCP 118 ms, LCP 118 ms\n example question: Show me the most impactful render-blocking requests that I should focus on\n example question: How can I reduce the number of render-blocking requests?\n - insight name: LCPBreakdown\n description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.\n relevant trace bounds: {min: 465456489730µs, max: 465457166052µs}\n example question: Help me optimize my LCP score\n example question: Which LCP subpart was most problematic?\n example question: What can I do to reduce the LCP time for this page load?\n - insight name: CLSCulprits\n description: Layout shifts occur when elements move absent any user interaction. [Investigate the causes of layout shifts](https://developer.chrome.com/docs/performance/insights/cls-culprit), such as elements being added, removed, or their fonts changing as the page loads.\n relevant trace bounds: {min: 465457121239µs, max: 465459012394µs}\n example question: Help me optimize my CLS score\n example question: How can I prevent layout shifts on this page?\n - insight name: NetworkDependencyTree\n description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load.\n relevant trace bounds: {min: 465456490723µs, max: 465458472724µs}\n example question: How do I optimize my network dependency tree?\n - insight name: DOMSize\n description: A large DOM can increase the duration of style calculations and layout reflows, impacting page responsiveness. A large DOM will also increase memory usage. [Learn how to avoid an excessive DOM size](https://developer.chrome.com/docs/performance/insights/dom-size).\n relevant trace bounds: {min: 465458287196µs, max: 465458340745µs}\n example question: How can I reduce the size of my DOM?\n - insight name: ThirdParties\n description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page’s content.\n relevant trace bounds: {min: 465456492168µs, max: 465460052616µs}\n example question: Which third parties are having the largest impact on my page performance?\n - insight name: ForcedReflow\n description: A forced reflow occurs when JavaScript queries geometric properties (such as offsetWidth) after styles have been invalidated by a change to the DOM state. This can result in poor performance. Learn more about [forced reflows](https://developer.chrome.com/docs/performance/insights/forced-reflow) and possible mitigations.\n relevant trace bounds: {min: 465456489730µs, max: 465460435979µs}\n example question: How can I avoid forced reflows and layout thrashing?\n example question: What is forced reflow and why is it problematic?\n - insight name: Cache\n description: A long cache lifetime can speed up repeat visits to your page. [Learn more about caching](https://developer.chrome.com/docs/performance/insights/cache).\n relevant trace bounds: {min: 465457179567µs, max: 465459110674µs}\n estimated metric savings: FCP 0 ms, LCP 0 ms\n estimated wasted bytes: 16 kB\n example question: What caching strategies can I apply to improve my page performance?\n# Critical network requests\n\n## insight set id: NO_NAVIGATION\n\nnone\n\n## insight set id: NAVIGATION_1\n\n\nNetwork requests data:\n\n\n\nallUrls = [0: https://web.dev/, 1: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCxc4AMP6lbBP.woff2, 2: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBxc4AMP6lbBP.woff2, 3: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fABc4AMP6lbBP.woff2, 4: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2, 5: https://fonts.gstatic.com/s/materialicons/v142/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2, 6: https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2, 7: https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2, 8: https://web.dev/_pwa/web/manifest.json, 9: https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap, 10: https://fonts.gstatic.com/s/googlesans/v59/4UasrENHsxJlGDuGo1OIlJfC6l_24rlCK1Yo_Iqcsih3SAyH6cAwhX9RPjIUvbQoi-E.woff2, 11: https://fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block, 12: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/web/css/app.css, 13: https://web.dev/extras.css]\n\n0;s-7302;1 ms;2 ms;568 ms;569 ms;568 ms;15 ms;0.5 ms;200;text/html;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[content-security-policy: base-uri 'self'; object-src 'none'; script-src 'strict-dynamic' 'unsafe-inline' https: http: 'nonce-pLl1WHuNABXXiQLLmUesvDyvzBJZdE' 'unsafe-eval'; report-uri https://csp.withgoogle.com/csp/devsite/v2|content-encoding: gzip|x-content-type-options: nosniff|date: Mon, 29 Apr 2024 11:01:15 GMT|strict-transport-security: max-age=63072000; includeSubdomains; preload|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|pragma: no-cache|last-modified: Fri, 26 Apr 2024 16:43:17 GMT|server: Google Frontend|vary: Cookie, Accept-Encoding|x-frame-options: SAMEORIGIN|content-type: text/html; charset=utf-8|x-cloud-trace-context: <redacted>|cache-control: no-cache, must-revalidate|expires: 0]\n1;s-49309;1,395 ms;1,402 ms;1,415 ms;1,423 ms;28 ms;94 μs;9 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Wed, 24 Apr 2024 15:02:33 GMT|x-content-type-options: nosniff|age: 417214|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:58 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Thu, 24 Apr 2025 15:02:33 GMT]\n2;s-46519;1,348 ms;1,355 ms;1,361 ms;1,423 ms;75 ms;73 μs;62 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Mon, 29 Apr 2024 03:50:51 GMT|x-content-type-options: nosniff|age: 25516|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:41 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Tue, 29 Apr 2025 03:50:51 GMT]\n3;s-46196;1,331 ms;1,339 ms;1,355 ms;1,420 ms;89 ms;0.1 ms;65 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Fri, 26 Apr 2024 20:29:46 GMT|x-content-type-options: nosniff|age: 224781|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:39 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 20:29:46 GMT]\n4;s-45814;1,326 ms;1,331 ms;1,348 ms;1,419 ms;93 ms;77 μs;71 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 13:27:47 GMT|x-content-type-options: nosniff|age: 336500|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:56 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 13:27:47 GMT]\n5;s-44751;1,286 ms;1,307 ms;1,343 ms;1,416 ms;130 ms;1 ms;73 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Fri, 26 Apr 2024 09:49:05 GMT|x-content-type-options: nosniff|age: 263222|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Mon, 08 Apr 2024 19:04:51 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 09:49:05 GMT]\n6;s-44728;1,285 ms;1,307 ms;1,343 ms;1,406 ms;120 ms;1 ms;62 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Sun, 28 Apr 2024 21:44:44 GMT|x-content-type-options: nosniff|age: 47483|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:53 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Mon, 28 Apr 2025 21:44:44 GMT]\n7;s-44701;1,284 ms;1,300 ms;1,339 ms;1,405 ms;120 ms;0.2 ms;65 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 09:35:28 GMT|x-content-type-options: nosniff|age: 350439|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 11 May 2022 19:24:50 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 09:35:28 GMT]\n8;s-43119;1,751 ms;1,751 ms;1,771 ms;1,771 ms;20 ms;27 μs;0.2 ms;200;application/json;Medium;Medium;Medium;f;unknown;t;0;[];[date: Sun, 28 Apr 2024 14:07:49 GMT|last-modified: Wed, 24 Apr 2024 11:02:59 GMT|server: Google Frontend|age: 75208|content-type: application/json|x-cloud-trace-context: <redacted>|cache-control: public, max-age=86400|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>]\n9;s-7695;557 ms;557 ms;597 ms;597 ms;40 ms;3 ms;0.6 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 11:01:15 GMT|content-encoding: gzip|x-content-type-options: nosniff|strict-transport-security: max-age=31536000|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|x-xss-protection: 0|last-modified: Mon, 29 Apr 2024 10:51:49 GMT|server: ESF|cross-origin-opener-policy: <redacted>|x-frame-options: SAMEORIGIN|content-type: text/css; charset=utf-8|access-control-allow-origin: *|cache-control: private, max-age=86400, stale-while-revalidate=604800|timing-allow-origin: *|link: <https://fonts.gstatic.com>; rel=preconnect; crossorigin|expires: Mon, 29 Apr 2024 11:01:15 GMT]\n7;s-34909;770 ms;770 ms;771 ms;776 ms;6 ms;40 μs;5 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[x-google-security-signals: <redacted>|x-google-gfe-service-trace: <redacted>|content-security-policy-report-only: <redacted>|x-google-scs-row-timestamp: <redacted>|x-google-gfe-response-code-details-trace: <redacted>|cross-origin-resource-policy: <redacted>|x-google-scs-row-key: <redacted>|content-type: font/woff2|access-control-allow-origin: *|x-google-data-version: <redacted>|cache-control: public, max-age=31536000|x-google-gfe-backend-request-info: <redacted>|x-google-dos-service-trace: <redacted>|x-google-backends: <redacted>|date: Thu, 26 Oct 2023 10:46:00 GMT|x-content-type-options: nosniff|expires: Fri, 25 Oct 2024 10:46:00 GMT|x-google-gfe-version: <redacted>|x-google-netmon-label: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-google-service: <redacted>|x-xss-protection: 0|x-google-gfe-handshake-trace: <redacted>|x-google-shellfish-status: <redacted>|last-modified: Wed, 11 May 2022 19:24:50 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|x-google-gfe-request-trace: <redacted>|accept-ranges: bytes|timing-allow-origin: *|x-google-scs-repo: <redacted>]\n10;s-11121;602 ms;602 ms;603 ms;611 ms;9 ms;27 μs;8 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;;[];[date: Thu, 25 Apr 2024 15:44:03 GMT|x-content-type-options: nosniff|age: 328319|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Wed, 24 Apr 2024 23:37:14 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Fri, 25 Apr 2025 15:44:03 GMT]\n11;s-7703;557 ms;557 ms;597 ms;597 ms;40 ms;90 μs;0.1 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 11:01:15 GMT|content-encoding: gzip|x-content-type-options: nosniff|strict-transport-security: max-age=31536000|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|x-xss-protection: 0|last-modified: Mon, 29 Apr 2024 11:01:15 GMT|server: ESF|cross-origin-opener-policy: <redacted>|x-frame-options: SAMEORIGIN|content-type: text/css; charset=utf-8|access-control-allow-origin: *|cache-control: private, max-age=86400, stale-while-revalidate=604800|timing-allow-origin: *|link: <https://fonts.gstatic.com>; rel=preconnect; crossorigin|expires: Mon, 29 Apr 2024 11:01:15 GMT]\n5;s-11334;606 ms;606 ms;607 ms;615 ms;9 ms;30 μs;8 ms;200;font/woff2;VeryHigh;VeryHigh;VeryHigh;f;unknown;t;11;[];[date: Fri, 26 Apr 2024 09:49:05 GMT|x-content-type-options: nosniff|age: 263217|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Mon, 08 Apr 2024 19:04:51 GMT|server: sffe|cross-origin-opener-policy: <redacted>|report-to: {\"group\":\"apps-themes\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/apps-themes\"}]}|content-type: font/woff2|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|timing-allow-origin: *|expires: Sat, 26 Apr 2025 09:49:05 GMT]\n12;s-7722;557 ms;557 ms;562 ms;568 ms;11 ms;0.5 ms;6 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[date: Mon, 29 Apr 2024 10:56:02 GMT|content-encoding: gzip|x-content-type-options: nosniff|age: 256|content-security-policy-report-only: <redacted>|cross-origin-resource-policy: <redacted>|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|last-modified: Thu, 25 Apr 2024 19:58:26 GMT|server: sffe|cross-origin-opener-policy: <redacted>|vary: Accept-Encoding|report-to: {\"group\":\"devrel-devsite\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/devrel-devsite\"}]}|content-type: text/css|access-control-allow-origin: *|cache-control: public, max-age=31536000|accept-ranges: bytes|expires: Tue, 29 Apr 2025 10:56:02 GMT]\n13;s-7737;557 ms;557 ms;561 ms;561 ms;4 ms;0.4 ms;0.2 ms;200;text/css;VeryHigh;VeryHigh;VeryHigh;t;unknown;t;0;[];[content-security-policy: base-uri 'self'; object-src 'none'; script-src 'strict-dynamic' 'unsafe-inline' https: http: 'nonce-laTwEoovJjOKcMoBUjSFaYO6rrF8dU' 'unsafe-eval'; report-uri https://csp.withgoogle.com/csp/devsite/v2|content-encoding: gzip|x-content-type-options: nosniff|date: Mon, 29 Apr 2024 11:00:18 GMT|strict-transport-security: max-age=63072000; includeSubdomains; preload|alt-svc: h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000|content-length: <redacted>|x-xss-protection: 0|pragma: no-cache|last-modified: Tue, 19 Mar 2024 18:37:07 GMT|server: Google Frontend|vary: Cookie, Accept-Encoding|x-frame-options: SAMEORIGIN|content-type: text/css|x-cloud-trace-context: <redacted>|cache-control: no-cache, must-revalidate|expires: 0]\n\n# Main thread bottom-up summary\n\nThis is the bottom-up summary for the entire trace. Only the top 10 activities (sorted by self time) are shown. An activity is all the aggregated time spent on the same type of work. For example, it can be all the time spent in a specific JavaScript function, or all the time spent in a specific browser rendering stage (like layout, v8 compile, parsing html). \"Self time\" represents the aggregated time spent directly in an activity, across all occurrences. \"Total time\" represents the aggregated time spent in an activity or any of its children.\n\n## insight set id: NO_NAVIGATION\n\n- self: 12 ms, total: 12 ms, source: Profiling overhead\n- self: 4 ms, total: 28 ms, source: Task\n- self: 3 ms, total: 4 ms, source: Recalculate style (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 98, column: 12)\n- self: 2 ms, total: 2 ms, source: Commit\n- self: 0.9 ms, total: 2 ms, source: Function call (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 102, column: 35)\n- self: 0.8 ms, total: 13 ms, source: Evaluate script\n- self: 0.7 ms, total: 3 ms, source: Event: pointerover\n- self: 0.1 ms, total: 1 ms, source: Xh (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 104, column: 61)\n\n## insight set id: NAVIGATION_1\n\n- self: 46 ms, total: 49 ms, source: Recalculate style\n- self: 37 ms, total: 211 ms, source: Task\n- self: 21 ms, total: 22 ms, source: Layout\n- self: 17 ms, total: 19 ms, source: Compile code\n- self: 7 ms, total: 7 ms, source: Cache script code\n- self: 6 ms, total: 26 ms, source: Function call (url: https://www.gstatic.com/devrel-devsite/prod/vafe2e13ca17bb026e70df42a2ead1c8192750e86a12923a88eda839025dabf95/js/devsite_app_module.js, line: 288, column: 146)\n- self: 5 ms, total: 5 ms, source: Parse stylesheet\n- self: 5 ms, total: 5 ms, source: Pre-paint\n- self: 5 ms, total: 5 ms, source: Commit\n- self: 5 ms, total: 10 ms, source: appendChild\n\n# 3rd party summary\n\n## insight set id: NO_NAVIGATION\n\n- name: Google CDN, main thread time: 1 ms, network transfer size: 0 B\n\n## insight set id: NAVIGATION_1\n\n- name: Google CDN, main thread time: 38 ms, network transfer size: 990 B\n- name: web.dev, main thread time: 3 ms, network transfer size: 84.3 kB\n- name: Google Analytics, main thread time: 0.6 ms, network transfer size: 52.9 kB\n- name: Google Fonts, main thread time: 0 ms, network transfer size: 42.2 kB\n\n# Longest tasks\n\n## insight set id: NO_NAVIGATION\n\n- total time: 13 ms, event: (eventKey: r-96, ts: 465455241964)\n- total time: 2 ms, event: (eventKey: r-934, ts: 465455475572)\n- total time: 1 ms, event: (eventKey: r-2310, ts: 465455879141)\n\n## insight set id: NAVIGATION_1\n\n- total time: 18 ms, event: (eventKey: r-20182, ts: 465457150438)\n- total time: 14 ms, event: (eventKey: r-12184, ts: 465457104625)\n- total time: 12 ms, event: (eventKey: r-10779, ts: 465457087373)\n\nUser selected the following call tree:\n\n\n\n# Call tree:\n\n1;r-10779;Task;3;;;2;;\n2;r-11902;Layout;3;3;;;;;S\n\n\n# User query\n\ntest"
10
10
  }
11
11
  ],
12
12
  "widgets": [
@@ -14,8 +14,8 @@ import {bytes, millis} from './UnitFormatters.js';
14
14
  /**
15
15
  * For a given frame ID and navigation ID, returns the LCP Event and the LCP Request, if the resource was an image.
16
16
  */
17
- function getLCPData(
18
- parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string, navigation: Trace.Types.Events.NavigationStart): {
17
+ function getLCPData(parsedTrace: Trace.TraceModel.ParsedTrace, frameId: string,
18
+ navigation: Trace.Types.Events.NavigationStart|Trace.Types.Events.SoftNavigationStart): {
19
19
  lcpEvent: Trace.Types.Events.LargestContentfulPaintCandidate,
20
20
  metricScore: Trace.Handlers.ModelHandlers.PageLoadMetrics.LCPMetricScore,
21
21
  lcpRequest?: Trace.Types.Events.SyntheticNetworkRequest,
@@ -34,7 +34,8 @@ function getLCPData(
34
34
  return null;
35
35
  }
36
36
 
37
- const navigationId = navigation.args.data?.navigationId;
37
+ const navigationId =
38
+ Trace.Types.Events.isSoftNavigationStart(navigation) ? undefined : navigation.args.data?.navigationId;
38
39
 
39
40
  return {
40
41
  lcpEvent,
@@ -574,7 +574,7 @@ The following is a list of insight sets. An insight set covers a specific part o
574
574
  ## insight set id: NAVIGATION_0
575
575
 
576
576
  URL: http://localhost:8080/render-blocking
577
- Bounds: {min: 171607579779µs, max: 171613750571µs}
577
+ Bounds: {min: 171607579779µs, max: 171613750570µs}
578
578
  Metrics (lab / observed):
579
579
  - LCP: 1317 ms, event: (eventKey: r-6686, ts: 171608897210), nodeId: 10
580
580
  - LCP breakdown:
@@ -1803,7 +1803,7 @@ const emulatedDevices = [
1803
1803
  {
1804
1804
  'order': 42,
1805
1805
  'show-by-default': true,
1806
- 'title': 'iPad Pro 13"',
1806
+ 'title': 'iPad Pro 13',
1807
1807
  'screen': {
1808
1808
  'horizontal': {
1809
1809
  'width': 1376,
@@ -440,7 +440,12 @@ export class TraceProcessor extends EventTarget {
440
440
  let id, urlString, navigation;
441
441
  if (context.navigation) {
442
442
  id = `NAVIGATION_${this.#insights.size}`;
443
- urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;
443
+ if (Types.Events.isSoftNavigationStart(context.navigation)) {
444
+ urlString = context.navigation.args.context.URL;
445
+ } else {
446
+ urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigation.args.data?.navigationId ?? '') ??
447
+ data.Meta.mainFrameURL;
448
+ }
444
449
  navigation = context.navigation;
445
450
  } else {
446
451
  id = Types.Events.NO_NAVIGATION;
@@ -523,17 +528,28 @@ export class TraceProcessor extends EventTarget {
523
528
 
524
529
  // Filter main frame navigations to those that have the necessary data (frameId and navigationId).
525
530
  // TODO(cjamcl): Does this filtering makes the "use the next nav as the end time" logic potentially broken? Are navs without nav id or frame even real?
526
- const navigations = data.Meta.mainFrameNavigations.filter(
527
- navigation => navigation.args.frame && navigation.args.data?.navigationId);
531
+ const hardNavigations = data.Meta.mainFrameNavigations.filter(navigation => navigation.args.frame &&
532
+ navigation.args.data?.navigationId);
533
+
534
+ const softNavigations =
535
+ this.#modelConfiguration.enableSoftNavigation ? Array.from(data.Meta.softNavigationsById.values()) : [];
536
+ const navigations = [...hardNavigations, ...softNavigations].sort((a, b) => a.ts - b.ts);
528
537
 
529
538
  this.#computeInsightsForInitialTracePeriod(data, navigations, options);
530
539
 
531
540
  for (const [index, navigation] of navigations.entries()) {
532
541
  const min = navigation.ts;
533
- // Use trace end for the last navigation, otherwise use the start of the next navigation.
534
- const max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;
542
+ // Use trace end for the last navigation, otherwise use the start of the next navigation (minus 1 to avoid overlap).
543
+ let max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;
544
+ if (index + 1 < navigations.length) {
545
+ max = Types.Timing.Micro(max - 1);
546
+ }
535
547
  const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);
536
- this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);
548
+ if (Types.Events.isSoftNavigationStart(navigation)) {
549
+ this.#computeInsightsForSoftNavigation(navigation, bounds, data, options);
550
+ } else {
551
+ this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);
552
+ }
537
553
  }
538
554
  }
539
555
 
@@ -541,12 +557,13 @@ export class TraceProcessor extends EventTarget {
541
557
  * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.
542
558
  */
543
559
  #computeInsightsForInitialTracePeriod(
544
- data: Handlers.Types.HandlerData, navigations: readonly Types.Events.NavigationStart[],
560
+ data: Handlers.Types.HandlerData,
561
+ navigations: ReadonlyArray<Types.Events.NavigationStart|Types.Events.SoftNavigationStart>,
545
562
  options: Types.Configuration.ParseOptions): void {
546
563
  // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.
547
- const bounds = navigations.length > 0 ?
548
- Helpers.Timing.traceWindowFromMicroSeconds(data.Meta.traceBounds.min, navigations[0].ts) :
549
- data.Meta.traceBounds;
564
+ const bounds = navigations.length > 0 ? Helpers.Timing.traceWindowFromMicroSeconds(
565
+ data.Meta.traceBounds.min, Types.Timing.Micro(navigations[0].ts - 1)) :
566
+ data.Meta.traceBounds;
550
567
 
551
568
  const context: Insights.Types.InsightSetContext = {
552
569
  options,
@@ -609,6 +626,21 @@ export class TraceProcessor extends EventTarget {
609
626
  };
610
627
  this.#computeInsightSet(data, context);
611
628
  }
629
+
630
+ /**
631
+ * Computes insights for a specific soft navigation event.
632
+ */
633
+ #computeInsightsForSoftNavigation(navigation: Types.Events.SoftNavigationStart, bounds: Types.Timing.TraceWindowMicro,
634
+ data: Handlers.Types.HandlerData, options: Types.Configuration.ParseOptions): void {
635
+ const frameId = navigation.args.frame;
636
+ const context: Insights.Types.InsightSetContextWithSoftNavigation = {
637
+ options,
638
+ bounds,
639
+ frameId,
640
+ navigation,
641
+ };
642
+ this.#computeInsightSet(data, context);
643
+ }
612
644
  }
613
645
 
614
646
  /**
@@ -39,7 +39,6 @@ import type {HandlerName} from './types.js';
39
39
 
40
40
  interface LayoutShiftsData {
41
41
  clusters: readonly Types.Events.SyntheticLayoutShiftCluster[];
42
- clustersByNavigationId: Map<Types.Events.NavigationId, Types.Events.SyntheticLayoutShiftCluster[]>;
43
42
  sessionMaxScore: number;
44
43
  // The session window which contains the SessionMaxScore
45
44
  clsWindowID: number;
@@ -110,7 +109,6 @@ let sessionMaxScore = 0;
110
109
  let clsWindowID = -1;
111
110
 
112
111
  let clusters: Types.Events.SyntheticLayoutShiftCluster[] = [];
113
- let clustersByNavigationId = new Map<Types.Events.NavigationId, Types.Events.SyntheticLayoutShiftCluster[]>();
114
112
 
115
113
  /**
116
114
  * Represents a point in time in which a LS score change
@@ -141,7 +139,6 @@ export function reset(): void {
141
139
  sessionMaxScore = 0;
142
140
  scoreRecords = [];
143
141
  clsWindowID = -1;
144
- clustersByNavigationId = new Map();
145
142
  }
146
143
 
147
144
  export function handleEvent(event: Types.Events.Event): void {
@@ -292,8 +289,9 @@ export async function finalize(): Promise<void> {
292
289
  }
293
290
 
294
291
  async function buildLayoutShiftsClusters(): Promise<void> {
295
- const {navigationsByFrameId, mainFrameId, traceBounds} = metaHandlerData();
296
- const navigations = navigationsByFrameId.get(mainFrameId) || [];
292
+ const {navigationsByFrameId, mainFrameId, traceBounds, softNavigationsById} = metaHandlerData();
293
+ const navigations: Types.Events.Event[] =
294
+ [...(navigationsByFrameId.get(mainFrameId) || []), ...softNavigationsById.values()].sort((a, b) => a.ts - b.ts);
297
295
  if (layoutShiftEvents.length === 0) {
298
296
  return;
299
297
  }
@@ -348,13 +346,15 @@ async function buildLayoutShiftsClusters(): Promise<void> {
348
346
  // If this cluster happened after a navigation, set the navigationId to
349
347
  // the current navigation. This lets us easily group clusters by
350
348
  // navigation.
351
- const navigationId = currentShiftNavigation === null ?
352
- Types.Events.NO_NAVIGATION :
353
- navigations[currentShiftNavigation].args.data?.navigationId;
354
- // TODO: `navigationId` is `string | undefined`, but the undefined portion
355
- // comes from `data.navigationId`. I don't think that is possible for this
356
- // event type. Can we make this typing stronger? In the meantime, we allow
357
- // `navigationId` to include undefined values.
349
+ let navigationId: string|undefined = undefined;
350
+ if (currentShiftNavigation !== null) {
351
+ const nav = navigations[currentShiftNavigation];
352
+ if (Types.Events.isNavigationStart(nav)) {
353
+ navigationId = nav.args.data?.navigationId;
354
+ }
355
+ } else {
356
+ navigationId = Types.Events.NO_NAVIGATION;
357
+ }
358
358
 
359
359
  clusters.push(Helpers.SyntheticEvents.SyntheticEventsManager
360
360
  .registerSyntheticEvent<Types.Events.SyntheticLayoutShiftCluster>({
@@ -519,12 +519,6 @@ async function buildLayoutShiftsClusters(): Promise<void> {
519
519
  sessionMaxScore = weightedScore;
520
520
  }
521
521
 
522
- if (cluster.navigationId) {
523
- const clustersForId = Platform.MapUtilities.getWithDefault(clustersByNavigationId, cluster.navigationId, () => {
524
- return [];
525
- });
526
- clustersForId.push(cluster);
527
- }
528
522
  }
529
523
  }
530
524
 
@@ -543,7 +537,6 @@ export function data(): LayoutShiftsData {
543
537
  remoteFonts,
544
538
  scoreRecords,
545
539
  backendNodeIds,
546
- clustersByNavigationId,
547
540
  paintImageEvents,
548
541
  };
549
542
  }
@@ -62,6 +62,7 @@ let navigationsByNavigationId = new Map<string, Types.Events.NavigationStart>();
62
62
  let softNavigationsById = new Map<number, Types.Events.SoftNavigationStart>();
63
63
  let finalDisplayUrlByNavigationId = new Map<string, string>();
64
64
  let mainFrameNavigations: Types.Events.NavigationStart[] = [];
65
+ let sameDocumentNavigations: Types.Events.DidCommitSameDocumentNavigation[] = [];
65
66
 
66
67
  // Represents all the threads in the trace, organized by process. This is mostly for internal
67
68
  // bookkeeping so that during the finalize pass we can obtain the main and browser thread IDs.
@@ -97,6 +98,7 @@ export function reset(): void {
97
98
  finalDisplayUrlByNavigationId = new Map();
98
99
  processNames = new Map();
99
100
  mainFrameNavigations = [];
101
+ sameDocumentNavigations = [];
100
102
 
101
103
  browserProcessId = Types.Events.ProcessID(-1);
102
104
  browserThreadId = Types.Events.ThreadID(-1);
@@ -346,15 +348,12 @@ export function handleEvent(event: Types.Events.Event): void {
346
348
  return;
347
349
  }
348
350
 
349
- // Update `finalDisplayUrlByNavigationId` to reflect history API navigations.
351
+ // Track history API navigations to compute final display URLs in finalize.
350
352
  if (Types.Events.isDidCommitSameDocumentNavigation(event)) {
351
353
  if (event.args.render_frame_host.frame_type !== 'PRIMARY_MAIN_FRAME') {
352
354
  return;
353
355
  }
354
-
355
- const navigation = mainFrameNavigations.at(-1);
356
- const key = navigation?.args.data?.navigationId ?? '';
357
- finalDisplayUrlByNavigationId.set(key, event.args.url);
356
+ sameDocumentNavigations.push(event);
358
357
  return;
359
358
  }
360
359
  }
@@ -440,6 +439,40 @@ export async function finalize(options?: FinalizeOptions): Promise<void> {
440
439
  mainFrameURL = firstMainFrameNav.args.data.documentLoaderURL;
441
440
  }
442
441
  }
442
+
443
+ // Compute final display URLs for each hard navigation.
444
+ // A hard navigation's final URL is updated by history API navigations (e.g. pushState).
445
+ // However, if a soft navigation occurs, subsequent history API navigations belong to the
446
+ // soft navigation and should not update the hard navigation's URL.
447
+ const softNavs = Array.from(softNavigationsById.values()).sort((a, b) => a.ts - b.ts);
448
+
449
+ // Create an array of intervals for each hard navigation.
450
+ const hardNavs = [...mainFrameNavigations];
451
+
452
+ // Add a faux navigation to cover the time before the first hard navigation, or the whole trace if there are none.
453
+ const intervals = [
454
+ {minTs: 0, maxTs: hardNavs.length > 0 ? hardNavs[0].ts : Infinity, key: ''},
455
+ ...hardNavs.map((nav, i) => ({
456
+ minTs: nav.ts,
457
+ maxTs: i + 1 < hardNavs.length ? hardNavs[i + 1].ts : Infinity,
458
+ key: nav.args.data?.navigationId ?? '',
459
+ })),
460
+ ];
461
+
462
+ for (const {minTs, maxTs, key} of intervals) {
463
+ // Find the first soft navigation within this hard navigation's time window.
464
+ const firstSoftNav = softNavs.find(sn => sn.ts >= minTs && sn.ts < maxTs);
465
+ // If a soft navigation occurred, we only consider history events before it.
466
+ const effectiveMaxTs = firstSoftNav ? firstSoftNav.ts : maxTs;
467
+
468
+ // Find the last history API navigation in the effective window.
469
+ const historyEvents = sameDocumentNavigations.filter(hn => hn.ts >= minTs && hn.ts < effectiveMaxTs);
470
+
471
+ const lastHistoryEvent = historyEvents.at(-1);
472
+ if (lastHistoryEvent) {
473
+ finalDisplayUrlByNavigationId.set(key, lastHistoryEvent.args.url);
474
+ }
475
+ }
443
476
  }
444
477
 
445
478
  export interface MetaHandlerData {
@@ -599,8 +599,7 @@ export function generateInsight(data: Handlers.Types.HandlerData, context: Insig
599
599
  const domLoadingEvents = data.LayoutShifts.domLoadingEvents.filter(isWithinContext);
600
600
  const unsizedImageEvents = data.LayoutShifts.layoutImageUnsizedEvents.filter(isWithinContext);
601
601
 
602
- const clusterKey = context.navigation ? context.navigationId : Types.Events.NO_NAVIGATION;
603
- const clusters = data.LayoutShifts.clustersByNavigationId.get(clusterKey) ?? [];
602
+ const clusters = data.LayoutShifts.clusters.filter(isWithinContext);
604
603
  const clustersByScore = clusters.toSorted((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore);
605
604
  const worstCluster = clustersByScore.at(0);
606
605
  const layoutShifts = clusters.flatMap(cluster => cluster.events);
@@ -127,7 +127,7 @@ function metaCharsetLabel(disposition: Types.Events.MetaCharsetDisposition|undef
127
127
 
128
128
  export function generateInsight(
129
129
  data: Handlers.Types.HandlerData, context: InsightSetContext): CharacterSetInsightModel {
130
- if (!context.navigation) {
130
+ if (!context.navigation || !('navigationId' in context)) {
131
131
  return finalize({});
132
132
  }
133
133
 
@@ -160,7 +160,26 @@ export function getFieldMetricsForInsightSet(
160
160
  return null;
161
161
  }
162
162
 
163
- const pageResult = getPageResult(cruxFieldData, insightSet.url.href, insightSet.url.origin, scope);
163
+ let pageResult = getPageResult(cruxFieldData, insightSet.url.href, insightSet.url.origin, scope);
164
+
165
+ if (!pageResult && insightSet.navigation && Types.Events.isSoftNavigationStart(insightSet.navigation)) {
166
+ pageResult = cruxFieldData.find(result => {
167
+ const key = scope ? result[`${scope.pageScope}-${scope.deviceScope}`]?.record.key :
168
+ (result['url-ALL'] || result['origin-ALL'])?.record.key;
169
+ if (!key) {
170
+ return false;
171
+ }
172
+ if (key.url) {
173
+ try {
174
+ return new URL(key.url).origin === insightSet.url.origin;
175
+ } catch {
176
+ return false;
177
+ }
178
+ }
179
+ return key.origin === insightSet.url.origin;
180
+ });
181
+ }
182
+
164
183
  if (!pageResult) {
165
184
  return null;
166
185
  }
@@ -266,7 +285,7 @@ function estimateSavingsWithGraphs(
266
285
  */
267
286
  export function metricSavingsForWastedBytes(
268
287
  wastedBytesByRequestId: Map<string, number>, context: InsightSetContext): MetricSavings|undefined {
269
- if (!context.navigation || !context.lantern) {
288
+ if (!context.navigation || !('lantern' in context) || !context.lantern) {
270
289
  return;
271
290
  }
272
291
 
@@ -191,7 +191,7 @@ function finalize(partialModel: PartialInsightModel<DocumentLatencyInsightModel>
191
191
 
192
192
  export function generateInsight(
193
193
  data: Handlers.Types.HandlerData, context: InsightSetContext): DocumentLatencyInsightModel {
194
- if (!context.navigation) {
194
+ if (!context.navigation || !('navigationId' in context)) {
195
195
  return finalize({});
196
196
  }
197
197
 
@@ -110,10 +110,10 @@ function anyValuesNaN(...values: number[]): boolean {
110
110
  * them to be missing on newer traces, but old trace files may lack some of the
111
111
  * data we rely on, so we want to handle that case.
112
112
  */
113
- function determineSubparts(
114
- nav: Types.Events.NavigationStart, docRequest: Types.Events.SyntheticNetworkRequest,
115
- lcpEvent: Types.Events.AnyLargestContentfulPaintCandidate,
116
- lcpRequest: Types.Events.SyntheticNetworkRequest|undefined): LCPSubparts|null {
113
+ function determineSubparts(nav: Types.Events.NavigationStart|Types.Events.SoftNavigationStart,
114
+ docRequest: Types.Events.SyntheticNetworkRequest,
115
+ lcpEvent: Types.Events.AnyLargestContentfulPaintCandidate,
116
+ lcpRequest: Types.Events.SyntheticNetworkRequest|undefined): LCPSubparts|null {
117
117
  const firstDocByteTs = calculateDocFirstByteTs(docRequest);
118
118
  if (firstDocByteTs === null) {
119
119
  return null;
@@ -232,9 +232,10 @@ export function generateInsight(
232
232
  const lcpMs = Helpers.Timing.microToMilli(metricScore.timing);
233
233
  // This helps position things on the timeline's UI accurately for a trace.
234
234
  const lcpTs = metricScore.event?.ts ? Helpers.Timing.microToMilli(metricScore.event?.ts) : undefined;
235
- const lcpRequest = data.LargestImagePaint.lcpRequestByNavigationId.get(context.navigationId);
235
+ const lcpRequest =
236
+ 'navigationId' in context ? data.LargestImagePaint.lcpRequestByNavigationId.get(context.navigationId) : undefined;
236
237
 
237
- const docRequest = networkRequests.byId.get(context.navigationId);
238
+ const docRequest = 'navigationId' in context ? networkRequests.byId.get(context.navigationId) : undefined;
238
239
  if (!docRequest) {
239
240
  return finalize({lcpMs, lcpTs, lcpEvent, lcpRequest, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});
240
241
  }
@@ -101,7 +101,7 @@ function finalize(partialModel: PartialInsightModel<LCPDiscoveryInsightModel>):
101
101
 
102
102
  export function generateInsight(
103
103
  data: Handlers.Types.HandlerData, context: InsightSetContext): LCPDiscoveryInsightModel {
104
- if (!context.navigation) {
104
+ if (!context.navigation || !('navigationId' in context)) {
105
105
  return finalize({});
106
106
  }
107
107
 
@@ -7,7 +7,7 @@ import * as Platform from '../../../core/platform/platform.js';
7
7
  import * as Handlers from '../handlers/handlers.js';
8
8
  import * as Helpers from '../helpers/helpers.js';
9
9
  import type * as Lantern from '../lantern/lantern.js';
10
- import type * as Types from '../types/types.js';
10
+ import * as Types from '../types/types.js';
11
11
 
12
12
  import {
13
13
  InsightCategory,
@@ -199,7 +199,7 @@ function computeWasteWithGraph(
199
199
 
200
200
  function computeMetricSavings(
201
201
  http1Requests: Types.Events.SyntheticNetworkRequest[], context: InsightSetContext): MetricSavings|undefined {
202
- if (!context.navigation || !context.lantern) {
202
+ if (!context.navigation || !('lantern' in context) || !context.lantern) {
203
203
  return;
204
204
  }
205
205
 
@@ -234,7 +234,11 @@ export function generateInsight(data: Handlers.Types.HandlerData, context: Insig
234
234
  const contextRequests = data.NetworkRequests.byTime.filter(isWithinContext);
235
235
 
236
236
  const entityMappings = data.NetworkRequests.entityMappings;
237
- const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? data.Meta.mainFrameURL;
237
+ let firstPartyUrl = data.Meta.mainFrameURL;
238
+ if (context.navigation && !Types.Events.isSoftNavigationStart(context.navigation)) {
239
+ firstPartyUrl = context.navigation.args.data?.documentLoaderURL ?? firstPartyUrl;
240
+ }
241
+
238
242
  const firstPartyEntity = Handlers.Helpers.getEntityForUrl(firstPartyUrl, entityMappings);
239
243
  const http1Requests = determineHttp1Requests(contextRequests, entityMappings, firstPartyEntity ?? null);
240
244