@paulirish/trace_engine 0.0.42 → 0.0.44

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 (141) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/locales/en-US.json +5 -14
  3. package/locales/en-XL.json +5 -14
  4. package/models/cpu_profile/CPUProfileDataModel.js +2 -2
  5. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
  6. package/models/trace/LanternComputationData.js +1 -1
  7. package/models/trace/LanternComputationData.js.map +1 -1
  8. package/models/trace/ModelImpl.d.ts +0 -1
  9. package/models/trace/ModelImpl.js +0 -3
  10. package/models/trace/ModelImpl.js.map +1 -1
  11. package/models/trace/extras/ThirdParties.d.ts +2 -1
  12. package/models/trace/extras/ThirdParties.js +26 -7
  13. package/models/trace/extras/ThirdParties.js.map +1 -1
  14. package/models/trace/extras/TraceTree.d.ts +15 -2
  15. package/models/trace/extras/TraceTree.js +2 -2
  16. package/models/trace/extras/TraceTree.js.map +1 -1
  17. package/models/trace/extras/extras.d.ts +0 -1
  18. package/models/trace/extras/extras.js +0 -1
  19. package/models/trace/handlers/InitiatorsHandler.js +0 -46
  20. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  21. package/models/trace/handlers/MetaHandler.js +3 -3
  22. package/models/trace/handlers/MetaHandler.js.map +1 -1
  23. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  24. package/models/trace/handlers/RendererHandler.d.ts +1 -1
  25. package/models/trace/handlers/RendererHandler.js +1 -1
  26. package/models/trace/handlers/RendererHandler.js.map +1 -1
  27. package/models/trace/handlers/ScreenshotsHandler.js +1 -1
  28. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  29. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
  30. package/models/trace/helpers/SamplesIntegrator.js +2 -2
  31. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  32. package/models/trace/helpers/Timing.d.ts +0 -1
  33. package/models/trace/helpers/Timing.js +0 -7
  34. package/models/trace/helpers/Timing.js.map +1 -1
  35. package/models/trace/helpers/Trace.d.ts +1 -2
  36. package/models/trace/helpers/Trace.js +1 -4
  37. package/models/trace/helpers/Trace.js.map +1 -1
  38. package/models/trace/helpers/TreeHelpers.js +1 -1
  39. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  40. package/models/trace/insights/CLSCulprits.d.ts +2 -0
  41. package/models/trace/insights/CLSCulprits.js +42 -9
  42. package/models/trace/insights/CLSCulprits.js.map +1 -1
  43. package/models/trace/insights/DOMSize.js +1 -1
  44. package/models/trace/insights/DocumentLatency.d.ts +2 -12
  45. package/models/trace/insights/DocumentLatency.js +24 -15
  46. package/models/trace/insights/DocumentLatency.js.map +1 -1
  47. package/models/trace/insights/FontDisplay.js +1 -1
  48. package/models/trace/insights/ForcedReflow.js +1 -1
  49. package/models/trace/insights/ImageDelivery.d.ts +1 -0
  50. package/models/trace/insights/ImageDelivery.js +9 -2
  51. package/models/trace/insights/ImageDelivery.js.map +1 -1
  52. package/models/trace/insights/InteractionToNextPaint.js +1 -1
  53. package/models/trace/insights/LCPDiscovery.d.ts +6 -14
  54. package/models/trace/insights/LCPDiscovery.js +18 -17
  55. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  56. package/models/trace/insights/LCPPhases.js +1 -1
  57. package/models/trace/insights/LongCriticalNetworkTree.js +1 -1
  58. package/models/trace/insights/RenderBlocking.js +1 -1
  59. package/models/trace/insights/SlowCSSSelector.js +1 -1
  60. package/models/trace/insights/ThirdParties.d.ts +4 -2
  61. package/models/trace/insights/ThirdParties.js +5 -3
  62. package/models/trace/insights/ThirdParties.js.map +1 -1
  63. package/models/trace/insights/Viewport.js +1 -1
  64. package/models/trace/insights/types.d.ts +6 -2
  65. package/models/trace/insights/types.js.map +1 -1
  66. package/models/trace/lantern/graph/BaseNode.d.ts +1 -1
  67. package/models/trace/lantern/graph/BaseNode.js +2 -1
  68. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  69. package/models/trace/lantern/graph/PageDependencyGraph.js +1 -0
  70. package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
  71. package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +1 -1
  72. package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
  73. package/models/trace/lantern/simulation/ConnectionPool.js +1 -1
  74. package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
  75. package/models/trace/lantern/simulation/Simulator.d.ts +2 -2
  76. package/models/trace/lantern/simulation/Simulator.js +4 -3
  77. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  78. package/models/trace/lantern/simulation/TCPConnection.d.ts +0 -1
  79. package/models/trace/lantern/simulation/TCPConnection.js +0 -3
  80. package/models/trace/lantern/simulation/TCPConnection.js.map +1 -1
  81. package/models/trace/lantern/types/Lantern.d.ts +2 -2
  82. package/models/trace/lantern/types/Lantern.js.map +1 -1
  83. package/models/trace/root-causes/LayoutShift.d.ts +1 -1
  84. package/models/trace/root-causes/LayoutShift.js +4 -4
  85. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  86. package/models/trace/types/Extensions.d.ts +0 -1
  87. package/models/trace/types/Extensions.js +0 -3
  88. package/models/trace/types/Extensions.js.map +1 -1
  89. package/models/trace/types/TraceEvents.d.ts +2 -11
  90. package/models/trace/types/TraceEvents.js +0 -3
  91. package/models/trace/types/TraceEvents.js.map +1 -1
  92. package/package.json +1 -1
  93. package/core/platform/PromiseUtilities.d.ts +0 -10
  94. package/core/platform/PromiseUtilities.js +0 -18
  95. package/core/platform/PromiseUtilities.js.map +0 -1
  96. package/core/platform/SetUtilities.d.ts +0 -2
  97. package/core/platform/SetUtilities.js +0 -23
  98. package/core/platform/SetUtilities.js.map +0 -1
  99. package/models/trace/EntriesFilter.d.ts +0 -72
  100. package/models/trace/EntriesFilter.js +0 -296
  101. package/models/trace/EntriesFilter.js.map +0 -1
  102. package/models/trace/LegacyTracingModel.js.map +0 -1
  103. package/models/trace/extras/URLForEntry.d.ts +0 -13
  104. package/models/trace/extras/URLForEntry.js +0 -44
  105. package/models/trace/extras/URLForEntry.js.map +0 -1
  106. package/models/trace/handlers/EnhancedTracesHandler.d.ts +0 -48
  107. package/models/trace/handlers/EnhancedTracesHandler.js +0 -165
  108. package/models/trace/handlers/EnhancedTracesHandler.js.map +0 -1
  109. package/models/trace/insights/CumulativeLayoutShift.d.ts +0 -34
  110. package/models/trace/insights/CumulativeLayoutShift.js +0 -209
  111. package/models/trace/insights/CumulativeLayoutShift.js.map +0 -1
  112. package/models/trace/insights/InsightRunners.d.ts +0 -6
  113. package/models/trace/insights/InsightRunners.js +0 -10
  114. package/models/trace/insights/InsightRunners.js.map +0 -1
  115. package/models/trace/insights/LargestContentfulPaint.d.ts +0 -25
  116. package/models/trace/insights/LargestContentfulPaint.js +0 -93
  117. package/models/trace/insights/LargestContentfulPaint.js.map +0 -1
  118. package/models/trace/lantern/BaseNode.d.ts +0 -91
  119. package/models/trace/lantern/BaseNode.js +0 -268
  120. package/models/trace/lantern/BaseNode.js.map +0 -1
  121. package/models/trace/lantern/CPUNode.d.ts +0 -24
  122. package/models/trace/lantern/CPUNode.js +0 -64
  123. package/models/trace/lantern/CPUNode.js.map +0 -1
  124. package/models/trace/lantern/LanternError.d.ts +0 -3
  125. package/models/trace/lantern/LanternError.js +0 -7
  126. package/models/trace/lantern/LanternError.js.map +0 -1
  127. package/models/trace/lantern/MetricsModule.d.ts +0 -11
  128. package/models/trace/lantern/MetricsModule.js +0 -14
  129. package/models/trace/lantern/MetricsModule.js.map +0 -1
  130. package/models/trace/lantern/NetworkNode.d.ts +0 -22
  131. package/models/trace/lantern/NetworkNode.js +0 -83
  132. package/models/trace/lantern/NetworkNode.js.map +0 -1
  133. package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
  134. package/models/trace/lantern/PageDependencyGraph.js +0 -509
  135. package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
  136. package/models/trace/lantern/SimulationModule.d.ts +0 -17
  137. package/models/trace/lantern/SimulationModule.js +0 -13
  138. package/models/trace/lantern/SimulationModule.js.map +0 -1
  139. package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
  140. package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
  141. package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
@@ -44,9 +44,6 @@ class TCPConnection {
44
44
  setWarmed(warmed) {
45
45
  this.warmed = warmed;
46
46
  }
47
- isWarm() {
48
- return this.warmed;
49
- }
50
47
  isH2() {
51
48
  return this.h2;
52
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TCPConnection.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {ConnectionTiming} from './SimulationTimingMap.js';\n\ninterface DownloadOptions {\n dnsResolutionTime?: number;\n timeAlreadyElapsed?: number;\n maximumTimeToElapse?: number;\n}\n\ninterface DownloadResults {\n roundTrips: number;\n timeElapsed: number;\n bytesDownloaded: number;\n extraBytesDownloaded: number;\n congestionWindow: number;\n connectionTiming: ConnectionTiming;\n}\n\nconst INITIAL_CONGESTION_WINDOW = 10;\nconst TCP_SEGMENT_SIZE = 1460;\n\nclass TCPConnection {\n warmed: boolean;\n ssl: boolean;\n h2: boolean;\n rtt: number;\n throughput: number;\n serverLatency: number;\n _congestionWindow: number;\n h2OverflowBytesDownloaded: number;\n\n constructor(rtt: number, throughput: number, serverLatency = 0, ssl = true, h2 = false) {\n this.warmed = false;\n this.ssl = ssl;\n this.h2 = h2;\n this.rtt = rtt;\n this.throughput = throughput;\n this.serverLatency = serverLatency;\n this._congestionWindow = INITIAL_CONGESTION_WINDOW;\n this.h2OverflowBytesDownloaded = 0;\n }\n\n static maximumSaturatedConnections(rtt: number, availableThroughput: number): number {\n const roundTripsPerSecond = 1000 / rtt;\n const bytesPerRoundTrip = TCP_SEGMENT_SIZE;\n const bytesPerSecond = roundTripsPerSecond * bytesPerRoundTrip;\n const minimumThroughputRequiredPerRequest = bytesPerSecond * 8;\n return Math.floor(availableThroughput / minimumThroughputRequiredPerRequest);\n }\n\n computeMaximumCongestionWindowInSegments(): number {\n const bytesPerSecond = this.throughput / 8;\n const secondsPerRoundTrip = this.rtt / 1000;\n const bytesPerRoundTrip = bytesPerSecond * secondsPerRoundTrip;\n return Math.floor(bytesPerRoundTrip / TCP_SEGMENT_SIZE);\n }\n\n setThroughput(throughput: number): void {\n this.throughput = throughput;\n }\n\n setCongestionWindow(congestion: number): void {\n this._congestionWindow = congestion;\n }\n\n setWarmed(warmed: boolean): void {\n this.warmed = warmed;\n }\n\n isWarm(): boolean {\n return this.warmed;\n }\n\n isH2(): boolean {\n return this.h2;\n }\n\n get congestionWindow(): number {\n return this._congestionWindow;\n }\n\n /**\n * Sets the number of excess bytes that are available to this connection on future downloads, only\n * applies to H2 connections.\n */\n setH2OverflowBytesDownloaded(bytes: number): void {\n if (!this.h2) {\n return;\n }\n this.h2OverflowBytesDownloaded = bytes;\n }\n\n clone(): TCPConnection {\n return Object.assign(new TCPConnection(this.rtt, this.throughput), this);\n }\n\n /**\n * Simulates a network download of a particular number of bytes over an optional maximum amount of time\n * and returns information about the ending state.\n *\n * See https://hpbn.co/building-blocks-of-tcp/#three-way-handshake and\n * https://hpbn.co/transport-layer-security-tls/#tls-handshake for details.\n */\n simulateDownloadUntil(bytesToDownload: number, options?: DownloadOptions): DownloadResults {\n const {timeAlreadyElapsed = 0, maximumTimeToElapse = Infinity, dnsResolutionTime = 0} = options || {};\n\n if (this.warmed && this.h2) {\n bytesToDownload -= this.h2OverflowBytesDownloaded;\n }\n const twoWayLatency = this.rtt;\n const oneWayLatency = twoWayLatency / 2;\n const maximumCongestionWindow = this.computeMaximumCongestionWindowInSegments();\n\n let handshakeAndRequest = oneWayLatency;\n if (!this.warmed) {\n handshakeAndRequest =\n // DNS lookup\n dnsResolutionTime +\n // SYN\n oneWayLatency +\n // SYN ACK\n oneWayLatency +\n // ACK + initial request\n oneWayLatency +\n // ClientHello/ServerHello assuming TLS False Start is enabled (https://istlsfastyet.com/#server-performance).\n (this.ssl ? twoWayLatency : 0);\n }\n\n let roundTrips = Math.ceil(handshakeAndRequest / twoWayLatency);\n let timeToFirstByte = handshakeAndRequest + this.serverLatency + oneWayLatency;\n if (this.warmed && this.h2) {\n timeToFirstByte = 0;\n }\n\n const timeElapsedForTTFB = Math.max(timeToFirstByte - timeAlreadyElapsed, 0);\n const maximumDownloadTimeToElapse = maximumTimeToElapse - timeElapsedForTTFB;\n\n let congestionWindow = Math.min(this._congestionWindow, maximumCongestionWindow);\n let totalBytesDownloaded = 0;\n if (timeElapsedForTTFB > 0) {\n totalBytesDownloaded = congestionWindow * TCP_SEGMENT_SIZE;\n } else {\n roundTrips = 0;\n }\n\n let downloadTimeElapsed = 0;\n let bytesRemaining = bytesToDownload - totalBytesDownloaded;\n while (bytesRemaining > 0 && downloadTimeElapsed <= maximumDownloadTimeToElapse) {\n roundTrips++;\n downloadTimeElapsed += twoWayLatency;\n congestionWindow = Math.max(Math.min(maximumCongestionWindow, congestionWindow * 2), 1);\n\n const bytesDownloadedInWindow = congestionWindow * TCP_SEGMENT_SIZE;\n totalBytesDownloaded += bytesDownloadedInWindow;\n bytesRemaining -= bytesDownloadedInWindow;\n }\n\n const timeElapsed = timeElapsedForTTFB + downloadTimeElapsed;\n const extraBytesDownloaded = this.h2 ? Math.max(totalBytesDownloaded - bytesToDownload, 0) : 0;\n const bytesDownloaded = Math.max(Math.min(totalBytesDownloaded, bytesToDownload), 0);\n\n let connectionTiming: ConnectionTiming;\n if (!this.warmed) {\n connectionTiming = {\n dnsResolutionTime,\n connectionTime: handshakeAndRequest - dnsResolutionTime,\n sslTime: this.ssl ? twoWayLatency : undefined,\n timeToFirstByte,\n };\n } else if (this.h2) {\n // TODO: timing information currently difficult to model for warm h2 connections.\n connectionTiming = {\n timeToFirstByte,\n };\n } else {\n connectionTiming = {\n connectionTime: handshakeAndRequest,\n timeToFirstByte,\n };\n }\n\n return {\n roundTrips,\n timeElapsed,\n bytesDownloaded,\n extraBytesDownloaded,\n congestionWindow,\n connectionTiming,\n };\n }\n}\n\nexport {TCPConnection};\n"]}
1
+ {"version":3,"file":"TCPConnection.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {ConnectionTiming} from './SimulationTimingMap.js';\n\ninterface DownloadOptions {\n dnsResolutionTime?: number;\n timeAlreadyElapsed?: number;\n maximumTimeToElapse?: number;\n}\n\ninterface DownloadResults {\n roundTrips: number;\n timeElapsed: number;\n bytesDownloaded: number;\n extraBytesDownloaded: number;\n congestionWindow: number;\n connectionTiming: ConnectionTiming;\n}\n\nconst INITIAL_CONGESTION_WINDOW = 10;\nconst TCP_SEGMENT_SIZE = 1460;\n\nclass TCPConnection {\n warmed: boolean;\n ssl: boolean;\n h2: boolean;\n rtt: number;\n throughput: number;\n serverLatency: number;\n _congestionWindow: number;\n h2OverflowBytesDownloaded: number;\n\n constructor(rtt: number, throughput: number, serverLatency = 0, ssl = true, h2 = false) {\n this.warmed = false;\n this.ssl = ssl;\n this.h2 = h2;\n this.rtt = rtt;\n this.throughput = throughput;\n this.serverLatency = serverLatency;\n this._congestionWindow = INITIAL_CONGESTION_WINDOW;\n this.h2OverflowBytesDownloaded = 0;\n }\n\n static maximumSaturatedConnections(rtt: number, availableThroughput: number): number {\n const roundTripsPerSecond = 1000 / rtt;\n const bytesPerRoundTrip = TCP_SEGMENT_SIZE;\n const bytesPerSecond = roundTripsPerSecond * bytesPerRoundTrip;\n const minimumThroughputRequiredPerRequest = bytesPerSecond * 8;\n return Math.floor(availableThroughput / minimumThroughputRequiredPerRequest);\n }\n\n computeMaximumCongestionWindowInSegments(): number {\n const bytesPerSecond = this.throughput / 8;\n const secondsPerRoundTrip = this.rtt / 1000;\n const bytesPerRoundTrip = bytesPerSecond * secondsPerRoundTrip;\n return Math.floor(bytesPerRoundTrip / TCP_SEGMENT_SIZE);\n }\n\n setThroughput(throughput: number): void {\n this.throughput = throughput;\n }\n\n setCongestionWindow(congestion: number): void {\n this._congestionWindow = congestion;\n }\n\n setWarmed(warmed: boolean): void {\n this.warmed = warmed;\n }\n\n isH2(): boolean {\n return this.h2;\n }\n\n get congestionWindow(): number {\n return this._congestionWindow;\n }\n\n /**\n * Sets the number of excess bytes that are available to this connection on future downloads, only\n * applies to H2 connections.\n */\n setH2OverflowBytesDownloaded(bytes: number): void {\n if (!this.h2) {\n return;\n }\n this.h2OverflowBytesDownloaded = bytes;\n }\n\n clone(): TCPConnection {\n return Object.assign(new TCPConnection(this.rtt, this.throughput), this);\n }\n\n /**\n * Simulates a network download of a particular number of bytes over an optional maximum amount of time\n * and returns information about the ending state.\n *\n * See https://hpbn.co/building-blocks-of-tcp/#three-way-handshake and\n * https://hpbn.co/transport-layer-security-tls/#tls-handshake for details.\n */\n simulateDownloadUntil(bytesToDownload: number, options?: DownloadOptions): DownloadResults {\n const {timeAlreadyElapsed = 0, maximumTimeToElapse = Infinity, dnsResolutionTime = 0} = options || {};\n\n if (this.warmed && this.h2) {\n bytesToDownload -= this.h2OverflowBytesDownloaded;\n }\n const twoWayLatency = this.rtt;\n const oneWayLatency = twoWayLatency / 2;\n const maximumCongestionWindow = this.computeMaximumCongestionWindowInSegments();\n\n let handshakeAndRequest = oneWayLatency;\n if (!this.warmed) {\n handshakeAndRequest =\n // DNS lookup\n dnsResolutionTime +\n // SYN\n oneWayLatency +\n // SYN ACK\n oneWayLatency +\n // ACK + initial request\n oneWayLatency +\n // ClientHello/ServerHello assuming TLS False Start is enabled (https://istlsfastyet.com/#server-performance).\n (this.ssl ? twoWayLatency : 0);\n }\n\n let roundTrips = Math.ceil(handshakeAndRequest / twoWayLatency);\n let timeToFirstByte = handshakeAndRequest + this.serverLatency + oneWayLatency;\n if (this.warmed && this.h2) {\n timeToFirstByte = 0;\n }\n\n const timeElapsedForTTFB = Math.max(timeToFirstByte - timeAlreadyElapsed, 0);\n const maximumDownloadTimeToElapse = maximumTimeToElapse - timeElapsedForTTFB;\n\n let congestionWindow = Math.min(this._congestionWindow, maximumCongestionWindow);\n let totalBytesDownloaded = 0;\n if (timeElapsedForTTFB > 0) {\n totalBytesDownloaded = congestionWindow * TCP_SEGMENT_SIZE;\n } else {\n roundTrips = 0;\n }\n\n let downloadTimeElapsed = 0;\n let bytesRemaining = bytesToDownload - totalBytesDownloaded;\n while (bytesRemaining > 0 && downloadTimeElapsed <= maximumDownloadTimeToElapse) {\n roundTrips++;\n downloadTimeElapsed += twoWayLatency;\n congestionWindow = Math.max(Math.min(maximumCongestionWindow, congestionWindow * 2), 1);\n\n const bytesDownloadedInWindow = congestionWindow * TCP_SEGMENT_SIZE;\n totalBytesDownloaded += bytesDownloadedInWindow;\n bytesRemaining -= bytesDownloadedInWindow;\n }\n\n const timeElapsed = timeElapsedForTTFB + downloadTimeElapsed;\n const extraBytesDownloaded = this.h2 ? Math.max(totalBytesDownloaded - bytesToDownload, 0) : 0;\n const bytesDownloaded = Math.max(Math.min(totalBytesDownloaded, bytesToDownload), 0);\n\n let connectionTiming: ConnectionTiming;\n if (!this.warmed) {\n connectionTiming = {\n dnsResolutionTime,\n connectionTime: handshakeAndRequest - dnsResolutionTime,\n sslTime: this.ssl ? twoWayLatency : undefined,\n timeToFirstByte,\n };\n } else if (this.h2) {\n // TODO: timing information currently difficult to model for warm h2 connections.\n connectionTiming = {\n timeToFirstByte,\n };\n } else {\n connectionTiming = {\n connectionTime: handshakeAndRequest,\n timeToFirstByte,\n };\n }\n\n return {\n roundTrips,\n timeElapsed,\n bytesDownloaded,\n extraBytesDownloaded,\n congestionWindow,\n connectionTiming,\n };\n }\n}\n\nexport {TCPConnection};\n"]}
@@ -84,7 +84,7 @@ export interface NetworkRequest<T = AnyNetworkObject> {
84
84
  networkRequestTime: number;
85
85
  /**
86
86
  * When the last byte of the response headers is received, in milliseconds.
87
- * Equal to networkRequestTime if no data is recieved over the
87
+ * Equal to networkRequestTime if no data is received over the
88
88
  * network (ex: cached requests or data urls).
89
89
  */
90
90
  responseHeadersEndTime: number;
@@ -122,7 +122,7 @@ export interface NetworkRequest<T = AnyNetworkObject> {
122
122
  */
123
123
  serverResponseTime?: number;
124
124
  /**
125
- * Implementation-specific canoncial data structure that this Lantern NetworkRequest
125
+ * Implementation-specific canonical data structure that this Lantern NetworkRequest
126
126
  * was derived from.
127
127
  * Users of Lantern create a NetworkRequest matching this interface,
128
128
  * but can store the source-of-truth for their network model in this property.
@@ -1 +1 @@
1
- {"version":3,"file":"Lantern.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/types/Lantern.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,gBAAgB;IAChC,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,WAAW;IACtB,kBAAkB,EAAE,oBAAoB;IACxC,QAAQ,EAAE,UAAU;CACZ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../../generated/protocol.js';\n\nexport const NetworkRequestTypes = {\n XHR: 'XHR',\n Fetch: 'Fetch',\n EventSource: 'EventSource',\n Script: 'Script',\n Stylesheet: 'Stylesheet',\n Image: 'Image',\n Media: 'Media',\n Font: 'Font',\n Document: 'Document',\n TextTrack: 'TextTrack',\n WebSocket: 'WebSocket',\n Other: 'Other',\n Manifest: 'Manifest',\n SignedExchange: 'SignedExchange',\n Ping: 'Ping',\n Preflight: 'Preflight',\n CSPViolationReport: 'CSPViolationReport',\n Prefetch: 'Prefetch',\n} as const;\n\nexport interface TraceEvent {\n name: string;\n args: {\n name?: string,\n data?: {\n frame?: string,\n readyState?: number,\n stackTrace?: {\n url: string,\n }[],\n url?: string,\n },\n };\n pid: number;\n tid: number;\n /** Timestamp of the event in microseconds. */\n ts: number;\n dur: number;\n}\nexport interface Trace {\n traceEvents: TraceEvent[];\n}\nexport type ResourcePriority = ('VeryLow'|'Low'|'Medium'|'High'|'VeryHigh');\nexport type ResourceType = keyof typeof NetworkRequestTypes;\ntype InitiatorType = ('parser'|'script'|'preload'|'SignedExchange'|'preflight'|'other');\nexport type ResourceTiming = Protocol.Network.ResourceTiming;\nexport interface CallStack {\n callFrames: Array<{\n scriptId: string,\n url: string,\n lineNumber: number,\n columnNumber: number,\n functionName: string,\n }>;\n parent?: CallStack;\n}\n\nexport interface ParsedURL {\n /**\n * Equivalent to a `new URL(url).protocol` BUT w/o the trailing colon (:)\n */\n scheme: string;\n /**\n * Equivalent to a `new URL(url).hostname`\n */\n host: string;\n securityOrigin: string;\n}\n\n// When Lantern NetworkRequests are constructed, the source-of-truth of the network record is given as `rawRequest`.\n// Internally Lantern doesn't care about the type of this field, so a default type is given to simplify internal code\n// by avoiding unnecessary typescript overhead.\n// If callers want to access the underlying network record, they are expected to make use of this generic on top-level\n// interfaces like Simulator.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyNetworkObject = any;\n\nexport interface NetworkRequest<T = AnyNetworkObject> {\n requestId: string;\n connectionId: number;\n connectionReused: boolean;\n url: string;\n protocol: string;\n parsedURL: ParsedURL;\n documentURL: string;\n /** When the renderer process initially discovers a network request, in milliseconds. */\n rendererStartTime: number;\n /**\n * When the network service is about to handle a request, ie. just before going to the\n * HTTP cache or going to the network for DNS/connection setup, in milliseconds.\n */\n networkRequestTime: number;\n /**\n * When the last byte of the response headers is received, in milliseconds.\n * Equal to networkRequestTime if no data is recieved over the\n * network (ex: cached requests or data urls).\n */\n responseHeadersEndTime: number;\n /** When the last byte of the response body is received, in milliseconds. */\n networkEndTime: number;\n transferSize: number;\n resourceSize: number;\n fromDiskCache: boolean;\n fromMemoryCache: boolean;\n isLinkPreload: boolean;\n finished: boolean;\n failed: boolean;\n statusCode: number;\n /** The network request that redirected to this one */\n redirectSource: NetworkRequest<T>|undefined;\n /** The network request that this one redirected to */\n redirectDestination: NetworkRequest<T>|undefined;\n // TODO: can't use Protocol.Network.Initiator because of type mismatch in Lighthouse initiator.\n initiator: {\n type: InitiatorType,\n url?: string,\n stack?: CallStack,\n };\n initiatorRequest: NetworkRequest<T>|undefined;\n /** The chain of network requests that redirected to this one */\n redirects: NetworkRequest[]|undefined;\n timing: Protocol.Network.ResourceTiming|undefined;\n resourceType: ResourceType|undefined;\n mimeType: string;\n priority: ResourcePriority;\n frameId: string|undefined;\n fromWorker: boolean;\n /**\n * Optional value for how long the server took to respond to this request.\n * When not provided, the server response time is derived from the timing object.\n */\n serverResponseTime?: number;\n /**\n * Implementation-specific canoncial data structure that this Lantern NetworkRequest\n * was derived from.\n * Users of Lantern create a NetworkRequest matching this interface,\n * but can store the source-of-truth for their network model in this property.\n * This is then accessible as a read-only property on NetworkNode.\n */\n rawRequest?: T;\n}\n\nexport namespace Simulation {\n export interface URL {\n /** URL of the initially requested URL */\n requestedUrl?: string;\n /** URL of the last document request */\n mainDocumentUrl?: string;\n }\n\n /** Simulation settings that control the amount of network & cpu throttling in the run. */\n export interface ThrottlingSettings {\n /** The round trip time in milliseconds. */\n rttMs?: number;\n /** The network throughput in kilobits per second. */\n throughputKbps?: number;\n // devtools settings\n /** The network request latency in milliseconds. */\n requestLatencyMs?: number;\n /** The network download throughput in kilobits per second. */\n downloadThroughputKbps?: number;\n /** The network upload throughput in kilobits per second. */\n uploadThroughputKbps?: number;\n // used by both\n /** The amount of slowdown applied to the cpu (1/<cpuSlowdownMultiplier>). */\n cpuSlowdownMultiplier?: number;\n }\n\n export interface PrecomputedLanternData {\n additionalRttByOrigin: {[origin: string]: number};\n serverResponseTimeByOrigin: {[origin: string]: number};\n }\n\n export interface Settings {\n networkAnalysis: {\n rtt: number,\n additionalRttByOrigin: Map<string, number>,\n serverResponseTimeByOrigin: Map<string, number>,\n throughput: number,\n };\n /** The method used to throttle the network. */\n throttlingMethod: 'devtools'|'simulate'|'provided';\n /** The throttling config settings. */\n throttling?: Required<ThrottlingSettings>;\n /** Precomputed lantern estimates to use instead of observed analysis. */\n precomputedLanternData?: PrecomputedLanternData|null;\n }\n\n export interface Options {\n rtt?: number;\n throughput?: number;\n observedThroughput: number;\n maximumConcurrentRequests?: number;\n cpuSlowdownMultiplier?: number;\n layoutTaskMultiplier?: number;\n additionalRttByOrigin?: Map<string, number>;\n serverResponseTimeByOrigin?: Map<string, number>;\n }\n\n export interface ProcessedNavigation {\n timestamps: {\n firstContentfulPaint: number,\n largestContentfulPaint?: number,\n };\n }\n\n export interface NodeTiming {\n startTime: number;\n endTime: number;\n duration: number;\n }\n}\n"]}
1
+ {"version":3,"file":"Lantern.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/types/Lantern.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,gBAAgB;IAChC,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,WAAW;IACtB,kBAAkB,EAAE,oBAAoB;IACxC,QAAQ,EAAE,UAAU;CACZ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../../generated/protocol.js';\n\nexport const NetworkRequestTypes = {\n XHR: 'XHR',\n Fetch: 'Fetch',\n EventSource: 'EventSource',\n Script: 'Script',\n Stylesheet: 'Stylesheet',\n Image: 'Image',\n Media: 'Media',\n Font: 'Font',\n Document: 'Document',\n TextTrack: 'TextTrack',\n WebSocket: 'WebSocket',\n Other: 'Other',\n Manifest: 'Manifest',\n SignedExchange: 'SignedExchange',\n Ping: 'Ping',\n Preflight: 'Preflight',\n CSPViolationReport: 'CSPViolationReport',\n Prefetch: 'Prefetch',\n} as const;\n\nexport interface TraceEvent {\n name: string;\n args: {\n name?: string,\n data?: {\n frame?: string,\n readyState?: number,\n stackTrace?: {\n url: string,\n }[],\n url?: string,\n },\n };\n pid: number;\n tid: number;\n /** Timestamp of the event in microseconds. */\n ts: number;\n dur: number;\n}\nexport interface Trace {\n traceEvents: TraceEvent[];\n}\nexport type ResourcePriority = ('VeryLow'|'Low'|'Medium'|'High'|'VeryHigh');\nexport type ResourceType = keyof typeof NetworkRequestTypes;\ntype InitiatorType = ('parser'|'script'|'preload'|'SignedExchange'|'preflight'|'other');\nexport type ResourceTiming = Protocol.Network.ResourceTiming;\nexport interface CallStack {\n callFrames: Array<{\n scriptId: string,\n url: string,\n lineNumber: number,\n columnNumber: number,\n functionName: string,\n }>;\n parent?: CallStack;\n}\n\nexport interface ParsedURL {\n /**\n * Equivalent to a `new URL(url).protocol` BUT w/o the trailing colon (:)\n */\n scheme: string;\n /**\n * Equivalent to a `new URL(url).hostname`\n */\n host: string;\n securityOrigin: string;\n}\n\n// When Lantern NetworkRequests are constructed, the source-of-truth of the network record is given as `rawRequest`.\n// Internally Lantern doesn't care about the type of this field, so a default type is given to simplify internal code\n// by avoiding unnecessary typescript overhead.\n// If callers want to access the underlying network record, they are expected to make use of this generic on top-level\n// interfaces like Simulator.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyNetworkObject = any;\n\nexport interface NetworkRequest<T = AnyNetworkObject> {\n requestId: string;\n connectionId: number;\n connectionReused: boolean;\n url: string;\n protocol: string;\n parsedURL: ParsedURL;\n documentURL: string;\n /** When the renderer process initially discovers a network request, in milliseconds. */\n rendererStartTime: number;\n /**\n * When the network service is about to handle a request, ie. just before going to the\n * HTTP cache or going to the network for DNS/connection setup, in milliseconds.\n */\n networkRequestTime: number;\n /**\n * When the last byte of the response headers is received, in milliseconds.\n * Equal to networkRequestTime if no data is received over the\n * network (ex: cached requests or data urls).\n */\n responseHeadersEndTime: number;\n /** When the last byte of the response body is received, in milliseconds. */\n networkEndTime: number;\n transferSize: number;\n resourceSize: number;\n fromDiskCache: boolean;\n fromMemoryCache: boolean;\n isLinkPreload: boolean;\n finished: boolean;\n failed: boolean;\n statusCode: number;\n /** The network request that redirected to this one */\n redirectSource: NetworkRequest<T>|undefined;\n /** The network request that this one redirected to */\n redirectDestination: NetworkRequest<T>|undefined;\n // TODO: can't use Protocol.Network.Initiator because of type mismatch in Lighthouse initiator.\n initiator: {\n type: InitiatorType,\n url?: string,\n stack?: CallStack,\n };\n initiatorRequest: NetworkRequest<T>|undefined;\n /** The chain of network requests that redirected to this one */\n redirects: NetworkRequest[]|undefined;\n timing: Protocol.Network.ResourceTiming|undefined;\n resourceType: ResourceType|undefined;\n mimeType: string;\n priority: ResourcePriority;\n frameId: string|undefined;\n fromWorker: boolean;\n /**\n * Optional value for how long the server took to respond to this request.\n * When not provided, the server response time is derived from the timing object.\n */\n serverResponseTime?: number;\n /**\n * Implementation-specific canonical data structure that this Lantern NetworkRequest\n * was derived from.\n * Users of Lantern create a NetworkRequest matching this interface,\n * but can store the source-of-truth for their network model in this property.\n * This is then accessible as a read-only property on NetworkNode.\n */\n rawRequest?: T;\n}\n\nexport namespace Simulation {\n export interface URL {\n /** URL of the initially requested URL */\n requestedUrl?: string;\n /** URL of the last document request */\n mainDocumentUrl?: string;\n }\n\n /** Simulation settings that control the amount of network & cpu throttling in the run. */\n export interface ThrottlingSettings {\n /** The round trip time in milliseconds. */\n rttMs?: number;\n /** The network throughput in kilobits per second. */\n throughputKbps?: number;\n // devtools settings\n /** The network request latency in milliseconds. */\n requestLatencyMs?: number;\n /** The network download throughput in kilobits per second. */\n downloadThroughputKbps?: number;\n /** The network upload throughput in kilobits per second. */\n uploadThroughputKbps?: number;\n // used by both\n /** The amount of slowdown applied to the cpu (1/<cpuSlowdownMultiplier>). */\n cpuSlowdownMultiplier?: number;\n }\n\n export interface PrecomputedLanternData {\n additionalRttByOrigin: {[origin: string]: number};\n serverResponseTimeByOrigin: {[origin: string]: number};\n }\n\n export interface Settings {\n networkAnalysis: {\n rtt: number,\n additionalRttByOrigin: Map<string, number>,\n serverResponseTimeByOrigin: Map<string, number>,\n throughput: number,\n };\n /** The method used to throttle the network. */\n throttlingMethod: 'devtools'|'simulate'|'provided';\n /** The throttling config settings. */\n throttling?: Required<ThrottlingSettings>;\n /** Precomputed lantern estimates to use instead of observed analysis. */\n precomputedLanternData?: PrecomputedLanternData|null;\n }\n\n export interface Options {\n rtt?: number;\n throughput?: number;\n observedThroughput: number;\n maximumConcurrentRequests?: number;\n cpuSlowdownMultiplier?: number;\n layoutTaskMultiplier?: number;\n additionalRttByOrigin?: Map<string, number>;\n serverResponseTimeByOrigin?: Map<string, number>;\n }\n\n export interface ProcessedNavigation {\n timestamps: {\n firstContentfulPaint: number,\n largestContentfulPaint?: number,\n };\n }\n\n export interface NodeTiming {\n startTime: number;\n endTime: number;\n duration: number;\n }\n}\n"]}
@@ -109,7 +109,7 @@ export declare class LayoutShiftRootCauses {
109
109
  /**
110
110
  * Returns a function that retrieves the active value of a given
111
111
  * CSS property within the matched styles of the param node.
112
- * The first occurence within the matched styles is returned and the
112
+ * The first occurrence within the matched styles is returned and the
113
113
  * value is looked up in the following order, which follows CSS
114
114
  * specificity:
115
115
  * 1. Inline styles.
@@ -81,7 +81,7 @@ export class LayoutShiftRootCauses {
81
81
  for (let i = 0; i < backendNodeIds.length; i++) {
82
82
  nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);
83
83
  }
84
- // Maps from PrePaint events to LayoutShifts that occured in each one.
84
+ // Maps from PrePaint events to LayoutShifts that occurred in each one.
85
85
  const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);
86
86
  for (const layoutInvalidation of eventsForLayoutInvalidation) {
87
87
  // Get the first PrePaint event that happened after the current LayoutInvalidation event.
@@ -150,7 +150,7 @@ export class LayoutShiftRootCauses {
150
150
  */
151
151
  linkShiftsToLayoutEvents(layoutShifts, modelData) {
152
152
  const { prePaintEvents } = modelData.LayoutShifts;
153
- // Maps from PrePaint events to LayoutShifts that occured in each one.
153
+ // Maps from PrePaint events to LayoutShifts that occurred in each one.
154
154
  const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);
155
155
  const eventTriggersLayout = ({ name }) => {
156
156
  const knownName = name;
@@ -349,7 +349,7 @@ export class LayoutShiftRootCauses {
349
349
  /**
350
350
  * Returns a function that retrieves the active value of a given
351
351
  * CSS property within the matched styles of the param node.
352
- * The first occurence within the matched styles is returned and the
352
+ * The first occurrence within the matched styles is returned and the
353
353
  * value is looked up in the following order, which follows CSS
354
354
  * specificity:
355
355
  * 1. Inline styles.
@@ -493,7 +493,7 @@ function dimensionsAreExplicit(dimensions) {
493
493
  * PrePaint events to layout shifts dispatched within it.
494
494
  */
495
495
  function getShiftsByPrePaintEvents(layoutShifts, prePaintEvents) {
496
- // Maps from PrePaint events to LayoutShifts that occured in each one.
496
+ // Maps from PrePaint events to LayoutShifts that occurred in each one.
497
497
  const shiftsByPrePaint = new Map();
498
498
  // Associate all shifts to their corresponding PrePaint.
499
499
  for (const prePaintEvent of prePaintEvents) {
@@ -1 +1 @@
1
- {"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type {ParsedTrace} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {RootCauseProtocolInterface} from './RootCauses.js';\n\nexport interface CSSDimensions {\n width?: string;\n height?: string;\n aspectRatio?: string;\n}\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.Events.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.Events.CallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map<Types.Events.PrePaint, FontChange[]|null>();\nconst renderBlocksByPrePaint = new Map<Types.Events.PrePaint, RenderBlockingRequest[]|null>();\n\nfunction setDefaultValue(\n map: Map<Types.Events.SyntheticLayoutShift, LayoutShiftRootCausesData>,\n shift: Types.Events.SyntheticLayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\nfunction networkRequestIsRenderBlockingInFrame(event: Types.Events.SyntheticNetworkRequest, frameId: string): boolean {\n return event.args.data.frame === frameId && Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event);\n}\n\ninterface Options {\n /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */\n enableIframeRootCauses?: boolean;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map<Types.Events.SyntheticLayoutShift, LayoutShiftRootCausesData>();\n #nodeDetailsCache = new Map<Protocol.DOM.NodeId, Protocol.DOM.Node|null>();\n #iframeRootCausesEnabled: boolean;\n\n constructor(protocolInterface: RootCauseProtocolInterface, options?: Options) {\n this.#protocolInterface = protocolInterface;\n this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: ParsedTrace, event: Types.Events.SyntheticLayoutShift):\n Promise<Readonly<LayoutShiftRootCausesData>|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.Events.SyntheticLayoutShift[],\n modelData: ParsedTrace,\n ): Promise<void> {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(layoutShifts: Types.Events.SyntheticLayoutShift[], modelData: ParsedTrace):\n Promise<void> {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation:\n Array<Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking> =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map<Protocol.DOM.BackendNodeId, Protocol.DOM.NodeId>();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined && Types.Events.isLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.Events.SyntheticLayoutShift[], modelData: ParsedTrace): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.Events.Name;\n return knownName === Types.Events.Name.LAYOUT;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<UnsizedMedia|null> {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe|null> {\n if (!this.#iframeRootCausesEnabled) {\n return null;\n }\n\n if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n async getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node|null> {\n let nodeDetails = this.#nodeDetailsCache.get(nodeId);\n if (nodeDetails !== undefined) {\n return nodeDetails;\n }\n\n nodeDetails = await this.#protocolInterface.getNode(nodeId);\n this.#nodeDetailsCache.set(nodeId, nodeDetails);\n\n return nodeDetails;\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n modelData: ParsedTrace): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicro(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions> {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map<string, string>): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map<string, string>): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map<string, string>): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map<string, string>): Promise<boolean> {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.Events.SyntheticLayoutShift[],\n prePaintEvents: Types.Events.PrePaint[],\n ): Map<Types.Events.PrePaint, Types.Events.SyntheticLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map<Types.Events.PrePaint, Types.Events.SyntheticLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]}
1
+ {"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAG/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAuC3C,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA4C,CAAC;AACnF,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAuD,CAAC;AAE9F,SAAS,eAAe,CACpB,GAAsE,EACtE,KAAwC;IAC1C,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;QACpD,OAAO;YACL,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,WAAW,EAAE,EAAE;YACf,sBAAsB,EAAE,EAAE;YAC1B,gBAAgB,EAAE,EAAE;SACrB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qCAAqC,CAAC,KAA2C,EAAE,OAAe;IACzG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,4CAA4C,CAAC,KAAK,CAAC,CAAC;AAClH,CAAC;AAOD,MAAM,OAAO,qBAAqB;IAChC,kBAAkB,CAA6B;IAC/C,kBAAkB,GAAG,IAAI,GAAG,EAAgE,CAAC;IAC7F,iBAAiB,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,wBAAwB,CAAU;IAElC,YAAY,iBAA6C,EAAE,OAAiB;QAC1E,IAAI,CAAC,kBAAkB,GAAG,iBAAiB,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,OAAO,EAAE,sBAAsB,IAAI,KAAK,CAAC;IAC3E,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAsB,EAAE,KAAwC;QAEvF,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3F,sFAAsF;QACtF,oFAAoF;QACpF,uDAAuD;QACvD,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;QAElF,qBAAqB;QACrB,MAAM,IAAI,CAAC,WAAW,CAClB,eAAe,EACf,SAAS,CACZ,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,kDAAkD;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACb,YAAiD,EACjD,SAAsB;QAExB,MAAM,IAAI,CAAC,+BAA+B,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,wBAAwB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,+BAA+B,CAAC,YAAiD,EAAE,SAAsB;QAE7G,MAAM,EAAC,cAAc,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,cAAc,EAAC,GAC7F,SAAS,CAAC,YAAY,CAAC;QAE3B,mEAAmE;QACnE,iDAAiD;QACjD,uEAAuE;QACvE,6BAA6B;QAC7B,MAAM,2BAA2B,GAEzB,CAAC,GAAG,wBAAwB,EAAE,GAAG,+BAA+B,CAAC,CAAC;QAE1E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,cAAc,CAAC,CAAC;QAC5F,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAmD,CAAC;QACzF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,qBAAqB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,uEAAuE;QACvE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QACjF,KAAK,MAAM,kBAAkB,IAAI,2BAA2B,EAAE,CAAC;YAC7D,yFAAyF;YACzF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACrG,MAAM,oBAAoB,GAAG,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACvG,MAAM,wBAAwB,GAAG,qBAAqB,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChG,IAAI,qBAAqB,GAAsB,IAAI,CAAC;YACpD,IAAI,eAAe,GAAwB,IAAI,CAAC;YAChD,IAAI,wBAAwB,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,4BAA4B,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC5G,qBAAqB,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;gBAC1G,eAAe,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;YAChG,CAAC;YAED,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,IAAI,CAAC,mBAAmB,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAChG,SAAS;YACX,CAAC;YAED,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,qBAAqB;oBACrB,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,qBAAqB,EAAE,IAAI,CAAC,MAAM,CAAC;oBACxG,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC5D,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;gBAC9D,CAAC;gBACD,IAAI,eAAe;oBACf,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAC5B,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3F,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,mBAAmB,EAAE,CAAC;oBACxB,0EAA0E;oBAC1E,yEAAyE;oBACzE,SAAS;oBACT,kBAAkB,CAAC,WAAW,GAAG,mBAAmB,CAAC;gBACvD,CAAC;gBACD,IAAI,oBAAoB,EAAE,CAAC;oBACzB,kBAAkB,CAAC,sBAAsB,GAAG,oBAAoB,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,wBAAwB,CAAC,YAAiD,EAAE,SAAsB;QAChG,MAAM,EAAC,cAAc,EAAC,GAAG,SAAS,CAAC,YAAY,CAAC;QAChD,uEAAuE;QACvE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAEjF,MAAM,mBAAmB,GAAG,CAAC,EAAC,IAAI,EAAiB,EAAW,EAAE;YAC9D,MAAM,SAAS,GAAG,IAAyB,CAAC;YAC5C,OAAO,SAAS,4CAA6B,CAAC;QAChD,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpF,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,6EAA6E;YAC7E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClG,MAAM,UAAU,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC;YACrD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrD,kBAAkB,CAAC,gBAAgB,GAAG,UAAU,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC1B,kBAA2D,EAC3D,wBAA6C;QAC/C,iCAAiC;QACjC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,4EAAuD,EAAE,CAAC;YAC/F,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,cAAc,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YAC1F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;QACxF,IAAI,qBAAqB,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3F,OAAO,EAAC,IAAI,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,EAAC,CAAC;IAChF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CACpB,kBAA2D,EAC3D,wBAA6C;QAC/C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC;YAC5D,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,8EAAwD;YAC3F,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,kFAA0D,EAAE,CAAC;YAClG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAC,MAAM,EAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAA2B;QAC9C,IAAI,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,4BAA4B,CACxB,kBAA0G,EAC1G,SAAsB;QACxB,MAAM,uBAAuB,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACnF,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,OAAO,WAAW,GAAG,WAAW,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAChE,uBAAuB,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC1F,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,MAAM,4BAA4B,GAAuB,EAAE,CAAC;QAE5D,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,eAAe,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,sBAAsB,GAAG,eAAe,CAAC,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC;YACxE,IAAI,kBAAkB,CAAC,EAAE,GAAG,sBAAsB,GAAG,0BAA0B,EAAE,CAAC;gBAChF,MAAM,2BAA2B,GAAqB,EAAC,OAAO,EAAE,eAAe,EAAC,CAAC;gBAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,CAC5D,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC,CAAC;gBACtE,2BAA2B,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,CAAC;gBAC/D,4BAA4B,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,2CAA2C;gBAC3C,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,4BAA4B,CAAC;IACtC,CAAC;IAED;;;;;;;;OAQG;IACH,sBAAsB,CAClB,kBAA0G,EAC1G,YAAmC,EAAE,SAAsB;QAC7D,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,8EAAwD,EAAE,CAAC;YAChG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mFAAmF;QACnF,MAAM,uBAAuB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACzE,IAAI,uBAAuB,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,uBAAuB,CAAC;QACjC,CAAC;QAED,MAAM,0BAA0B,GAC5B,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QAC/G,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,mCAAmC,CAAC,4BAAgD;QAClF,MAAM,YAAY,GAAiB,EAAE,CAAC;QAEtC,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAe,CAAC;YAClE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9F,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBACrD,iEAAiE;gBACjE,oEAAoE;gBACpE,uCAAuC;gBACvC,SAAS;YACX,CAAC;YACD,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,uBAAuB,CACnB,kBAA0G,EAC1G,YAAmC,EAAE,SAAsB;QAC7D,mFAAmF;QACnF,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACxE,IAAI,sBAAsB,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,sBAAsB,CAAC;QAChC,CAAC;QAED,MAAM,0BAA0B,GAC5B,0CAA0C,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QACjH,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,+BAA+B,CAAC,IAAuB;QAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,SAAS,sBAAsB,CAAC,WAAmB;YACjD,IAAI,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,QAAQ,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;gBACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;gBAC9E,IAAI,IAAI,EAAE,CAAC;oBACT,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,IAAI,GAAG,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,yBAAyB,CAAC,IAAuB;QACrD,MAAM,kBAAkB,GAAkB,EAAE,CAAC;QAE7C,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC3B,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,UAAU,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,EAAC,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpG,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QAElG,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;QAElF,IAAI,UAAU,IAAI,SAAS,IAAI,sBAAsB,EAAE,CAAC;YACtD,OAAO,EAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;QACjG,CAAC;QAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;QAC/D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;QAC7D,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;IACnF,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,0CAA0C,CAAC,4BAAgD;IAElG,MAAM,sBAAsB,GAA4B,EAAE,CAAC;IAE3D,qDAAqD;IACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5E,IAAI,CAAC,qCAAqC,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YACjG,SAAS;QACX,CAAC;QACD,sBAAsB,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAA0B,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAuB;IACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,aAAa,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,aAAqB;IACvD,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAqB;IACpD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,8BAA8B,CAAC,aAAkC;IACxE,MAAM,aAAa,GAAG,oBAAoB,CAAC;IAC3C,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9D,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,6BAA6B,CAAC,aAAkC;IACvE,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,UAAU,CAAC;AACzD,CAAC;AAED,SAAS,yBAAyB,CAAC,aAAkC;IACnE,MAAM,kBAAkB,GAAkB,EAAE,CAAC;IAC7C,kBAAkB,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,kBAAkB,CAAC,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,kBAAkB,CAAC,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnE,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,IAAuB,EAAE,aAAkC;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACjC,MAAM,iBAAiB,GAAG,8BAA8B,CAAC,aAAa,CAAC,CAAC;IACxE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvE,uBAAuB;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;IAC7D,OAAO,CAAC,OAAO,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,UAAyB;IACtD,MAAM,EAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAC,GAAG,UAAU,CAAC;IAEhD,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,IAAI,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,IAAI,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,IAAI,0BAA0B,CAAC,WAAW,CAAC,CAAC,CAAC;IAE5F,MAAM,cAAc,GAAG,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,mBAAmB,CAAC;IAChF,OAAO,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,cAAc,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAC9B,YAAiD,EACjD,cAAuC;IAEzC,uEAAuE;IACvE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA8D,CAAC;IAE/F,wDAAwD;IACxD,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;QAC3G,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7B,mEAAmE;YACnE,SAAS;QACX,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACrF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACpD,8DAA8D;gBAC9D,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type {ParsedTrace} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {RootCauseProtocolInterface} from './RootCauses.js';\n\nexport interface CSSDimensions {\n width?: string;\n height?: string;\n aspectRatio?: string;\n}\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.Events.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.Events.CallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map<Types.Events.PrePaint, FontChange[]|null>();\nconst renderBlocksByPrePaint = new Map<Types.Events.PrePaint, RenderBlockingRequest[]|null>();\n\nfunction setDefaultValue(\n map: Map<Types.Events.SyntheticLayoutShift, LayoutShiftRootCausesData>,\n shift: Types.Events.SyntheticLayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\nfunction networkRequestIsRenderBlockingInFrame(event: Types.Events.SyntheticNetworkRequest, frameId: string): boolean {\n return event.args.data.frame === frameId && Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event);\n}\n\ninterface Options {\n /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */\n enableIframeRootCauses?: boolean;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map<Types.Events.SyntheticLayoutShift, LayoutShiftRootCausesData>();\n #nodeDetailsCache = new Map<Protocol.DOM.NodeId, Protocol.DOM.Node|null>();\n #iframeRootCausesEnabled: boolean;\n\n constructor(protocolInterface: RootCauseProtocolInterface, options?: Options) {\n this.#protocolInterface = protocolInterface;\n this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: ParsedTrace, event: Types.Events.SyntheticLayoutShift):\n Promise<Readonly<LayoutShiftRootCausesData>|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.Events.SyntheticLayoutShift[],\n modelData: ParsedTrace,\n ): Promise<void> {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(layoutShifts: Types.Events.SyntheticLayoutShift[], modelData: ParsedTrace):\n Promise<void> {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation:\n Array<Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking> =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map<Protocol.DOM.BackendNodeId, Protocol.DOM.NodeId>();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occurred in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined && Types.Events.isLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.Events.SyntheticLayoutShift[], modelData: ParsedTrace): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occurred in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.Events.Name;\n return knownName === Types.Events.Name.LAYOUT;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<UnsizedMedia|null> {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe|null> {\n if (!this.#iframeRootCausesEnabled) {\n return null;\n }\n\n if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n async getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node|null> {\n let nodeDetails = this.#nodeDetailsCache.get(nodeId);\n if (nodeDetails !== undefined) {\n return nodeDetails;\n }\n\n nodeDetails = await this.#protocolInterface.getNode(nodeId);\n this.#nodeDetailsCache.set(nodeId, nodeDetails);\n\n return nodeDetails;\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n modelData: ParsedTrace): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicro(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurrence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions> {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map<string, string>): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map<string, string>): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map<string, string>): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map<string, string>): Promise<boolean> {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.Events.SyntheticLayoutShift[],\n prePaintEvents: Types.Events.PrePaint[],\n ): Map<Types.Events.PrePaint, Types.Events.SyntheticLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occurred in each one.\n const shiftsByPrePaint = new Map<Types.Events.PrePaint, Types.Events.SyntheticLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]}
@@ -2,7 +2,6 @@ import type { Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasure
2
2
  export type ExtensionEntryType = 'track-entry' | 'marker';
3
3
  export declare const extensionPalette: readonly ["primary", "primary-light", "primary-dark", "secondary", "secondary-light", "secondary-dark", "tertiary", "tertiary-light", "tertiary-dark", "error", "warning"];
4
4
  export type ExtensionColorFromPalette = typeof extensionPalette[number];
5
- export declare function colorIsValid(color: string): boolean;
6
5
  export interface ExtensionDataPayloadBase {
7
6
  color?: ExtensionColorFromPalette;
8
7
  properties?: [string, string][];
@@ -14,9 +14,6 @@ export const extensionPalette = [
14
14
  'error',
15
15
  'warning',
16
16
  ];
17
- export function colorIsValid(color) {
18
- return extensionPalette.includes(color);
19
- }
20
17
  export function isExtensionPayloadMarker(payload) {
21
18
  return payload.dataType === 'marker';
22
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAQ7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;AAIX,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AA+CD,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {\n Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased} from\n './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nexport const extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n 'warning',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport function colorIsValid(color: string): boolean {\n return (extensionPalette as readonly string[]).includes(color);\n}\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n properties?: [string, string][];\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends\n SyntheticBased<Phase.COMPLETE, PerformanceMeasureBegin|PerformanceMark|ConsoleTimeStamp> {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased<Phase.COMPLETE, PerformanceMark> {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: {\n [x: string]: SyntheticExtensionTrackEntry[],\n };\n}\n"]}
1
+ {"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAQ7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;AAiDX,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {\n Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased} from\n './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nexport const extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n 'warning',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n properties?: [string, string][];\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends\n SyntheticBased<Phase.COMPLETE, PerformanceMeasureBegin|PerformanceMark|ConsoleTimeStamp> {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased<Phase.COMPLETE, PerformanceMark> {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: {\n [x: string]: SyntheticExtensionTrackEntry[],\n };\n}\n"]}
@@ -1151,7 +1151,7 @@ interface ChromeFrameReporter {
1151
1151
  /** Identifies a BeginFrameArgs (along with the source_id).
1152
1152
  See comments in components/viz/common/frame_sinks/begin_frame_args.h. */
1153
1153
  frame_sequence: number;
1154
- /** If this is a droped frame (i.e. if |state| is set to |STATE_DROPPED| or
1154
+ /** If this is a dropped frame (i.e. if |state| is set to |STATE_DROPPED| or
1155
1155
  |STATE_PRESENTED_PARTIAL|), then indicates whether this frame impacts smoothness. */
1156
1156
  affects_smoothness: boolean;
1157
1157
  /** The type of active scroll. */
@@ -1272,7 +1272,7 @@ export interface SyntheticInteractionPair extends SyntheticEventPair<EventTiming
1272
1272
  * trace event.
1273
1273
  *
1274
1274
  * We store the sampleIndex, profileId and nodeId so that we can easily link
1275
- * back a Synthetic Trace Entry to an indivdual Sample trace event within a
1275
+ * back a Synthetic Trace Entry to an individual Sample trace event within a
1276
1276
  * Profile.
1277
1277
  *
1278
1278
  * Because a sample contains a set of call frames representing the stack at the
@@ -1326,15 +1326,6 @@ export interface DrawFrame extends Instant {
1326
1326
  };
1327
1327
  }
1328
1328
  export declare function isDrawFrame(event: Event): event is DrawFrame;
1329
- export interface LegacyDrawFrameBegin extends Async {
1330
- name: Name.DRAW_FRAME;
1331
- ph: Phase.ASYNC_NESTABLE_START;
1332
- args: Args & {
1333
- layerTreeId: number;
1334
- frameSeqId: number;
1335
- };
1336
- }
1337
- export declare function isLegacyTraceEventDrawFrameBegin(event: Event): event is LegacyDrawFrameBegin;
1338
1329
  export interface BeginFrame extends Instant {
1339
1330
  name: Name.BEGIN_FRAME;
1340
1331
  args: Args & {
@@ -112,9 +112,6 @@ export function isDrawFrame(event) {
112
112
  // The extra check for INSTANT here is because in the past DrawFrame events had an ASYNC_NESTABLE_START and ASYNC_NESTABLE_END pair. We don't want to support those old events, so we have to check we are dealing with an instant event.
113
113
  return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "I" /* Phase.INSTANT */;
114
114
  }
115
- export function isLegacyTraceEventDrawFrameBegin(event) {
116
- return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "b" /* Phase.ASYNC_NESTABLE_START */;
117
- }
118
115
  export function isBeginFrame(event) {
119
116
  // Old traces did not have frameSeqId; but we do not want to support these.
120
117
  return Boolean(event.name === "BeginFrame" /* Name.BEGIN_FRAME */ && event.args && 'frameSeqId' in event.args);