@paulirish/trace_engine 0.0.32 → 0.0.33

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 (282) hide show
  1. package/README.md +6 -10
  2. package/analyze-trace.mjs +9 -10
  3. package/core/platform/ArrayUtilities.js +1 -0
  4. package/core/platform/ArrayUtilities.js.map +1 -1
  5. package/core/platform/DevToolsPath.d.ts +1 -1
  6. package/core/platform/DevToolsPath.js.map +1 -1
  7. package/core/platform/MimeType.js +4 -2
  8. package/core/platform/MimeType.js.map +1 -1
  9. package/core/platform/NumberUtilities.js +8 -0
  10. package/core/platform/NumberUtilities.js.map +1 -1
  11. package/core/platform/ServerTiming.d.ts +31 -0
  12. package/core/platform/ServerTiming.js +212 -0
  13. package/core/platform/ServerTiming.js.map +1 -0
  14. package/core/platform/Timing.d.ts +1 -1
  15. package/core/platform/Timing.js.map +1 -1
  16. package/core/platform/TypescriptUtilities.d.ts +3 -0
  17. package/core/platform/TypescriptUtilities.js.map +1 -1
  18. package/core/platform/UIString.d.ts +1 -1
  19. package/core/platform/UIString.js.map +1 -1
  20. package/core/platform/UserVisibleError.d.ts +1 -1
  21. package/core/platform/UserVisibleError.js.map +1 -1
  22. package/core/platform/platform-tsconfig.json +1 -1
  23. package/core/platform/platform.d.ts +2 -2
  24. package/core/platform/platform.js +2 -2
  25. package/core/platform/platform.js.map +1 -1
  26. package/generated/protocol.d.ts +258 -14
  27. package/models/trace/LanternComputationData.d.ts +4 -4
  28. package/models/trace/LanternComputationData.js +22 -23
  29. package/models/trace/LanternComputationData.js.map +1 -1
  30. package/models/trace/ModelImpl.d.ts +11 -12
  31. package/models/trace/ModelImpl.js +22 -33
  32. package/models/trace/ModelImpl.js.map +1 -1
  33. package/models/trace/Processor.d.ts +21 -12
  34. package/models/trace/Processor.js +148 -67
  35. package/models/trace/Processor.js.map +1 -1
  36. package/models/trace/TracingManager.js.map +1 -1
  37. package/models/trace/extras/FetchNodes.d.ts +8 -8
  38. package/models/trace/extras/FetchNodes.js +16 -11
  39. package/models/trace/extras/FetchNodes.js.map +1 -1
  40. package/models/trace/extras/FilmStrip.d.ts +2 -2
  41. package/models/trace/extras/FilmStrip.js +8 -8
  42. package/models/trace/extras/FilmStrip.js.map +1 -1
  43. package/models/trace/extras/MainThreadActivity.d.ts +1 -1
  44. package/models/trace/extras/MainThreadActivity.js +1 -1
  45. package/models/trace/extras/MainThreadActivity.js.map +1 -1
  46. package/models/trace/extras/Metadata.js +2 -2
  47. package/models/trace/extras/Metadata.js.map +1 -1
  48. package/models/trace/extras/URLForEntry.d.ts +9 -1
  49. package/models/trace/extras/URLForEntry.js +18 -10
  50. package/models/trace/extras/URLForEntry.js.map +1 -1
  51. package/models/trace/extras/extras.js +1 -1
  52. package/models/trace/handlers/AnimationHandler.d.ts +2 -2
  53. package/models/trace/handlers/AnimationHandler.js +1 -1
  54. package/models/trace/handlers/AnimationHandler.js.map +1 -1
  55. package/models/trace/handlers/AuctionWorkletsHandler.d.ts +2 -2
  56. package/models/trace/handlers/AuctionWorkletsHandler.js +11 -11
  57. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
  58. package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +6 -6
  59. package/models/trace/handlers/ExtensionTraceDataHandler.js +12 -8
  60. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  61. package/models/trace/handlers/FramesHandler.d.ts +24 -19
  62. package/models/trace/handlers/FramesHandler.js +46 -25
  63. package/models/trace/handlers/FramesHandler.js.map +1 -1
  64. package/models/trace/handlers/GPUHandler.d.ts +4 -4
  65. package/models/trace/handlers/GPUHandler.js +3 -3
  66. package/models/trace/handlers/GPUHandler.js.map +1 -1
  67. package/models/trace/handlers/ImagePaintingHandler.d.ts +3 -3
  68. package/models/trace/handlers/ImagePaintingHandler.js +6 -8
  69. package/models/trace/handlers/ImagePaintingHandler.js.map +1 -1
  70. package/models/trace/handlers/InitiatorsHandler.d.ts +3 -3
  71. package/models/trace/handlers/InitiatorsHandler.js +14 -14
  72. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  73. package/models/trace/handlers/InvalidationsHandler.d.ts +4 -2
  74. package/models/trace/handlers/InvalidationsHandler.js +29 -11
  75. package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
  76. package/models/trace/handlers/LargestImagePaintHandler.d.ts +2 -2
  77. package/models/trace/handlers/LargestImagePaintHandler.js +1 -1
  78. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
  79. package/models/trace/handlers/LargestTextPaintHandler.d.ts +2 -2
  80. package/models/trace/handlers/LargestTextPaintHandler.js +1 -1
  81. package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -1
  82. package/models/trace/handlers/LayerTreeHandler.d.ts +6 -6
  83. package/models/trace/handlers/LayerTreeHandler.js +6 -6
  84. package/models/trace/handlers/LayerTreeHandler.js.map +1 -1
  85. package/models/trace/handlers/LayoutShiftsHandler.d.ts +12 -20
  86. package/models/trace/handlers/LayoutShiftsHandler.js +73 -12
  87. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  88. package/models/trace/handlers/MemoryHandler.d.ts +2 -2
  89. package/models/trace/handlers/MemoryHandler.js +1 -1
  90. package/models/trace/handlers/MemoryHandler.js.map +1 -1
  91. package/models/trace/handlers/MetaHandler.d.ts +15 -14
  92. package/models/trace/handlers/MetaHandler.js +32 -30
  93. package/models/trace/handlers/MetaHandler.js.map +1 -1
  94. package/models/trace/handlers/ModelHandlers.d.ts +1 -1
  95. package/models/trace/handlers/ModelHandlers.js +1 -1
  96. package/models/trace/handlers/ModelHandlers.js.map +1 -1
  97. package/models/trace/handlers/NetworkRequestsHandler.d.ts +13 -12
  98. package/models/trace/handlers/NetworkRequestsHandler.js +68 -66
  99. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  100. package/models/trace/handlers/PageFramesHandler.d.ts +2 -2
  101. package/models/trace/handlers/PageFramesHandler.js +2 -2
  102. package/models/trace/handlers/PageFramesHandler.js.map +1 -1
  103. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +7 -7
  104. package/models/trace/handlers/PageLoadMetricsHandler.js +21 -24
  105. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  106. package/models/trace/handlers/RendererHandler.d.ts +19 -19
  107. package/models/trace/handlers/RendererHandler.js +5 -5
  108. package/models/trace/handlers/RendererHandler.js.map +1 -1
  109. package/models/trace/handlers/SamplesHandler.d.ts +6 -6
  110. package/models/trace/handlers/SamplesHandler.js +3 -3
  111. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  112. package/models/trace/handlers/ScreenshotsHandler.d.ts +6 -4
  113. package/models/trace/handlers/ScreenshotsHandler.js +11 -9
  114. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  115. package/models/trace/handlers/SelectorStatsHandler.d.ts +3 -3
  116. package/models/trace/handlers/SelectorStatsHandler.js +2 -2
  117. package/models/trace/handlers/SelectorStatsHandler.js.map +1 -1
  118. package/models/trace/handlers/ServerTimingsHandler.d.ts +10 -0
  119. package/models/trace/handlers/ServerTimingsHandler.js +118 -0
  120. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -0
  121. package/models/trace/handlers/Threads.d.ts +7 -7
  122. package/models/trace/handlers/Threads.js +5 -5
  123. package/models/trace/handlers/Threads.js.map +1 -1
  124. package/models/trace/handlers/UserInteractionsHandler.d.ts +13 -11
  125. package/models/trace/handlers/UserInteractionsHandler.js +13 -7
  126. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  127. package/models/trace/handlers/UserTimingsHandler.d.ts +5 -5
  128. package/models/trace/handlers/UserTimingsHandler.js +52 -9
  129. package/models/trace/handlers/UserTimingsHandler.js.map +1 -1
  130. package/models/trace/handlers/WarningsHandler.d.ts +5 -5
  131. package/models/trace/handlers/WarningsHandler.js +4 -5
  132. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  133. package/models/trace/handlers/WorkersHandler.d.ts +4 -4
  134. package/models/trace/handlers/WorkersHandler.js +1 -1
  135. package/models/trace/handlers/WorkersHandler.js.map +1 -1
  136. package/models/trace/handlers/handlers-tsconfig.json +1 -1
  137. package/models/trace/handlers/types.d.ts +7 -7
  138. package/models/trace/handlers/types.js.map +1 -1
  139. package/models/trace/helpers/Extensions.d.ts +2 -2
  140. package/models/trace/helpers/Extensions.js.map +1 -1
  141. package/models/trace/helpers/Network.d.ts +2 -2
  142. package/models/trace/helpers/Network.js +19 -2
  143. package/models/trace/helpers/Network.js.map +1 -1
  144. package/models/trace/helpers/SamplesIntegrator.d.ts +5 -5
  145. package/models/trace/helpers/SamplesIntegrator.js +10 -11
  146. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  147. package/models/trace/helpers/SyntheticEvents.d.ts +8 -14
  148. package/models/trace/helpers/SyntheticEvents.js +20 -31
  149. package/models/trace/helpers/SyntheticEvents.js.map +1 -1
  150. package/models/trace/helpers/Timing.d.ts +16 -4
  151. package/models/trace/helpers/Timing.js +33 -1
  152. package/models/trace/helpers/Timing.js.map +1 -1
  153. package/models/trace/helpers/Trace.d.ts +46 -32
  154. package/models/trace/helpers/Trace.js +53 -24
  155. package/models/trace/helpers/Trace.js.map +1 -1
  156. package/models/trace/helpers/TreeHelpers.d.ts +29 -8
  157. package/models/trace/helpers/TreeHelpers.js +87 -19
  158. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  159. package/models/trace/insights/Common.d.ts +4 -3
  160. package/models/trace/insights/Common.js +22 -7
  161. package/models/trace/insights/Common.js.map +1 -1
  162. package/models/trace/insights/CumulativeLayoutShift.d.ts +34 -13
  163. package/models/trace/insights/CumulativeLayoutShift.js +151 -59
  164. package/models/trace/insights/CumulativeLayoutShift.js.map +1 -1
  165. package/models/trace/insights/DocumentLatency.d.ts +9 -4
  166. package/models/trace/insights/DocumentLatency.js +82 -7
  167. package/models/trace/insights/DocumentLatency.js.map +1 -1
  168. package/models/trace/insights/FontDisplay.d.ts +11 -0
  169. package/models/trace/insights/FontDisplay.js +44 -0
  170. package/models/trace/insights/FontDisplay.js.map +1 -0
  171. package/models/trace/insights/InsightRunners.d.ts +3 -0
  172. package/models/trace/insights/InsightRunners.js +3 -0
  173. package/models/trace/insights/InsightRunners.js.map +1 -1
  174. package/models/trace/insights/InteractionToNextPaint.d.ts +4 -5
  175. package/models/trace/insights/InteractionToNextPaint.js +5 -3
  176. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  177. package/models/trace/insights/LargestContentfulPaint.d.ts +20 -7
  178. package/models/trace/insights/LargestContentfulPaint.js +57 -37
  179. package/models/trace/insights/LargestContentfulPaint.js.map +1 -1
  180. package/models/trace/insights/RenderBlocking.d.ts +3 -3
  181. package/models/trace/insights/RenderBlocking.js +29 -24
  182. package/models/trace/insights/RenderBlocking.js.map +1 -1
  183. package/models/trace/insights/SlowCSSSelector.d.ts +11 -0
  184. package/models/trace/insights/SlowCSSSelector.js +67 -0
  185. package/models/trace/insights/SlowCSSSelector.js.map +1 -0
  186. package/models/trace/insights/ThirdPartyWeb.d.ts +18 -0
  187. package/models/trace/insights/ThirdPartyWeb.js +174 -0
  188. package/models/trace/insights/ThirdPartyWeb.js.map +1 -0
  189. package/models/trace/insights/Viewport.d.ts +5 -2
  190. package/models/trace/insights/Viewport.js +14 -9
  191. package/models/trace/insights/Viewport.js.map +1 -1
  192. package/models/trace/insights/insights-tsconfig.json +9 -0
  193. package/models/trace/insights/insights.d.ts +1 -0
  194. package/models/trace/insights/insights.js +1 -0
  195. package/models/trace/insights/insights.js.map +1 -1
  196. package/models/trace/insights/types.d.ts +43 -25
  197. package/models/trace/insights/types.js.map +1 -1
  198. package/models/trace/lantern/core/NetworkAnalyzer.d.ts +6 -6
  199. package/models/trace/lantern/core/NetworkAnalyzer.js +12 -12
  200. package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
  201. package/models/trace/lantern/graph/BaseNode.d.ts +4 -4
  202. package/models/trace/lantern/graph/BaseNode.js +21 -21
  203. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  204. package/models/trace/lantern/graph/CPUNode.d.ts +1 -1
  205. package/models/trace/lantern/graph/CPUNode.js +5 -5
  206. package/models/trace/lantern/graph/CPUNode.js.map +1 -1
  207. package/models/trace/lantern/graph/PageDependencyGraph.d.ts +4 -4
  208. package/models/trace/lantern/graph/PageDependencyGraph.js +5 -5
  209. package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
  210. package/models/trace/lantern/simulation/ConnectionPool.d.ts +7 -7
  211. package/models/trace/lantern/simulation/ConnectionPool.js +26 -26
  212. package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
  213. package/models/trace/lantern/simulation/DNSCache.d.ts +3 -3
  214. package/models/trace/lantern/simulation/DNSCache.js +11 -11
  215. package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
  216. package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +1 -1
  217. package/models/trace/lantern/simulation/SimulationTimingMap.js +15 -15
  218. package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
  219. package/models/trace/lantern/simulation/Simulator.d.ts +28 -28
  220. package/models/trace/lantern/simulation/Simulator.js +113 -113
  221. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  222. package/models/trace/lantern/simulation/TCPConnection.d.ts +9 -9
  223. package/models/trace/lantern/simulation/TCPConnection.js +36 -36
  224. package/models/trace/lantern/simulation/TCPConnection.js.map +1 -1
  225. package/models/trace/root-causes/LayoutShift.d.ts +13 -13
  226. package/models/trace/root-causes/LayoutShift.js +7 -25
  227. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  228. package/models/trace/types/Configuration.d.ts +16 -0
  229. package/models/trace/types/Configuration.js +1 -0
  230. package/models/trace/types/Configuration.js.map +1 -1
  231. package/models/trace/types/Extensions.d.ts +9 -12
  232. package/models/trace/types/Extensions.js +2 -1
  233. package/models/trace/types/Extensions.js.map +1 -1
  234. package/models/trace/types/File.d.ts +55 -23
  235. package/models/trace/types/File.js +15 -3
  236. package/models/trace/types/File.js.map +1 -1
  237. package/models/trace/types/TraceEvents.d.ts +818 -713
  238. package/models/trace/types/TraceEvents.js +270 -277
  239. package/models/trace/types/TraceEvents.js.map +1 -1
  240. package/models/trace/types/types.d.ts +1 -1
  241. package/models/trace/types/types.js +1 -1
  242. package/models/trace/types/types.js.map +1 -1
  243. package/package.json +4 -2
  244. package/test/test-trace-engine.mjs +47 -2
  245. package/third_party/third-party-web/third-party-web.js +1 -0
  246. package/core/platform/PromiseUtilities.d.ts +0 -10
  247. package/core/platform/PromiseUtilities.js +0 -18
  248. package/core/platform/PromiseUtilities.js.map +0 -1
  249. package/core/platform/SetUtilities.d.ts +0 -2
  250. package/core/platform/SetUtilities.js +0 -23
  251. package/core/platform/SetUtilities.js.map +0 -1
  252. package/models/trace/EntriesFilter.d.ts +0 -72
  253. package/models/trace/EntriesFilter.js +0 -296
  254. package/models/trace/EntriesFilter.js.map +0 -1
  255. package/models/trace/LegacyTracingModel.js.map +0 -1
  256. package/models/trace/handlers/EnhancedTracesHandler.d.ts +0 -48
  257. package/models/trace/handlers/EnhancedTracesHandler.js +0 -165
  258. package/models/trace/handlers/EnhancedTracesHandler.js.map +0 -1
  259. package/models/trace/lantern/BaseNode.d.ts +0 -91
  260. package/models/trace/lantern/BaseNode.js +0 -268
  261. package/models/trace/lantern/BaseNode.js.map +0 -1
  262. package/models/trace/lantern/CPUNode.d.ts +0 -24
  263. package/models/trace/lantern/CPUNode.js +0 -64
  264. package/models/trace/lantern/CPUNode.js.map +0 -1
  265. package/models/trace/lantern/LanternError.d.ts +0 -3
  266. package/models/trace/lantern/LanternError.js +0 -7
  267. package/models/trace/lantern/LanternError.js.map +0 -1
  268. package/models/trace/lantern/MetricsModule.d.ts +0 -11
  269. package/models/trace/lantern/MetricsModule.js +0 -14
  270. package/models/trace/lantern/MetricsModule.js.map +0 -1
  271. package/models/trace/lantern/NetworkNode.d.ts +0 -22
  272. package/models/trace/lantern/NetworkNode.js +0 -83
  273. package/models/trace/lantern/NetworkNode.js.map +0 -1
  274. package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
  275. package/models/trace/lantern/PageDependencyGraph.js +0 -509
  276. package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
  277. package/models/trace/lantern/SimulationModule.d.ts +0 -17
  278. package/models/trace/lantern/SimulationModule.js +0 -13
  279. package/models/trace/lantern/SimulationModule.js.map +0 -1
  280. package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
  281. package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
  282. package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
@@ -2,6 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
  import * as Handlers from './handlers/handlers.js';
5
+ import * as Helpers from './helpers/helpers.js';
5
6
  import * as Insights from './insights/insights.js';
6
7
  import * as Lantern from './lantern/lantern.js';
7
8
  import * as LanternComputationData from './LanternComputationData.js';
@@ -14,6 +15,13 @@ export class TraceParseProgressEvent extends Event {
14
15
  this.data = data;
15
16
  }
16
17
  }
18
+ function calculateProgress(value, phase) {
19
+ // Finalize values should be [0.2...0.8]
20
+ if (phase === 0.8 /* ProgressPhase.FINALIZE */) {
21
+ return (value * (0.8 /* ProgressPhase.FINALIZE */ - 0.2 /* ProgressPhase.HANDLE_EVENT */)) + 0.2 /* ProgressPhase.HANDLE_EVENT */;
22
+ }
23
+ return value * phase;
24
+ }
17
25
  export class TraceProcessor extends EventTarget {
18
26
  // We force the Meta handler to be enabled, so the TraceHandlers type here is
19
27
  // the model handlers the user passes in and the Meta handler.
@@ -25,11 +33,11 @@ export class TraceProcessor extends EventTarget {
25
33
  static createWithAllHandlers() {
26
34
  return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());
27
35
  }
28
- static getEnabledInsightRunners(traceParsedData) {
36
+ static getEnabledInsightRunners(parsedTrace) {
29
37
  const enabledInsights = {};
30
38
  for (const [name, insight] of Object.entries(Insights.InsightRunners)) {
31
39
  const deps = insight.deps();
32
- if (deps.some(dep => !traceParsedData[dep])) {
40
+ if (deps.some(dep => !parsedTrace[dep])) {
33
41
  continue;
34
42
  }
35
43
  Object.assign(enabledInsights, { [name]: insight });
@@ -104,14 +112,14 @@ export class TraceProcessor extends EventTarget {
104
112
  this.#insights = null;
105
113
  this.#status = "IDLE" /* Status.IDLE */;
106
114
  }
107
- async parse(traceEvents, freshRecording = false) {
115
+ async parse(traceEvents, options) {
108
116
  if (this.#status !== "IDLE" /* Status.IDLE */) {
109
117
  throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);
110
118
  }
111
119
  try {
112
120
  this.#status = "PARSING" /* Status.PARSING */;
113
- await this.#computeTraceParsedData(traceEvents, freshRecording);
114
- if (this.#data) {
121
+ await this.#computeParsedTrace(traceEvents, Boolean(options.isFreshRecording));
122
+ if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.
115
123
  this.#computeInsights(this.#data, traceEvents);
116
124
  }
117
125
  this.#status = "FINISHED_PARSING" /* Status.FINISHED_PARSING */;
@@ -124,7 +132,7 @@ export class TraceProcessor extends EventTarget {
124
132
  /**
125
133
  * Run all the handlers and set the result to `#data`.
126
134
  */
127
- async #computeTraceParsedData(traceEvents, freshRecording) {
135
+ async #computeParsedTrace(traceEvents, freshRecording) {
128
136
  /**
129
137
  * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.
130
138
  * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.
@@ -149,7 +157,8 @@ export class TraceProcessor extends EventTarget {
149
157
  // Every so often we take a break just to render.
150
158
  if (i % eventsPerChunk === 0 && i) {
151
159
  // Take the opportunity to provide status update events.
152
- this.dispatchEvent(new TraceParseProgressEvent({ index: i, total: traceEvents.length }));
160
+ const percent = calculateProgress(i / traceEvents.length, 0.2 /* ProgressPhase.HANDLE_EVENT */);
161
+ this.dispatchEvent(new TraceParseProgressEvent({ percent }));
153
162
  // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`
154
163
  await new Promise(resolve => setTimeout(resolve, 0));
155
164
  }
@@ -159,13 +168,15 @@ export class TraceProcessor extends EventTarget {
159
168
  }
160
169
  }
161
170
  // Finalize.
162
- for (const handler of sortedHandlers) {
171
+ for (const [i, handler] of sortedHandlers.entries()) {
163
172
  if (handler.finalize) {
164
173
  // Yield to the UI because finalize() calls can be expensive
165
174
  // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`
166
175
  await new Promise(resolve => setTimeout(resolve, 0));
167
176
  await handler.finalize();
168
177
  }
178
+ const percent = calculateProgress(i / sortedHandlers.length, 0.8 /* ProgressPhase.FINALIZE */);
179
+ this.dispatchEvent(new TraceParseProgressEvent({ percent }));
169
180
  }
170
181
  // Handlers that depend on other handlers do so via .data(), which used to always
171
182
  // return a shallow clone of its internal data structures. However, that pattern
@@ -192,14 +203,15 @@ export class TraceProcessor extends EventTarget {
192
203
  }
193
204
  return value;
194
205
  };
195
- const traceParsedData = {};
206
+ const parsedTrace = {};
196
207
  for (const [name, handler] of Object.entries(this.#traceHandlers)) {
197
208
  const data = shallowClone(handler.data());
198
- Object.assign(traceParsedData, { [name]: data });
209
+ Object.assign(parsedTrace, { [name]: data });
199
210
  }
200
- this.#data = traceParsedData;
211
+ this.dispatchEvent(new TraceParseProgressEvent({ percent: 1 /* ProgressPhase.CLONE */ }));
212
+ this.#data = parsedTrace;
201
213
  }
202
- get traceParsedData() {
214
+ get parsedTrace() {
203
215
  if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
204
216
  return null;
205
217
  }
@@ -211,26 +223,36 @@ export class TraceProcessor extends EventTarget {
211
223
  }
212
224
  return this.#insights;
213
225
  }
214
- #createLanternContext(traceParsedData, traceEvents) {
226
+ #createLanternContext(parsedTrace, traceEvents, frameId, navigationId) {
215
227
  // Check for required handlers.
216
- if (!traceParsedData.NetworkRequests || !traceParsedData.Workers || !traceParsedData.PageLoadMetrics) {
228
+ if (!parsedTrace.NetworkRequests || !parsedTrace.Workers || !parsedTrace.PageLoadMetrics) {
217
229
  return;
218
230
  }
219
- if (!traceParsedData.NetworkRequests.byTime.length) {
231
+ if (!parsedTrace.NetworkRequests.byTime.length) {
220
232
  throw new Lantern.Core.LanternError('No network requests found in trace');
221
233
  }
222
- // Lantern.Types.TraceEvent and Types.TraceEvents.TraceEventData represent the same
234
+ const navStarts = parsedTrace.Meta.navigationsByFrameId.get(frameId);
235
+ const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);
236
+ if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {
237
+ throw new Lantern.Core.LanternError('Could not find navigation start');
238
+ }
239
+ const startTime = navStarts[navStartIndex].ts;
240
+ const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;
241
+ const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);
242
+ // Lantern.Types.TraceEvent and Types.Events.Event represent the same
223
243
  // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.
224
244
  const trace = {
225
- traceEvents: traceEvents,
245
+ traceEvents: boundedTraceEvents,
226
246
  };
227
- const requests = LanternComputationData.createNetworkRequests(trace, traceParsedData);
228
- const graph = LanternComputationData.createGraph(requests, trace, traceParsedData);
229
- const processedNavigation = LanternComputationData.createProcessedNavigation(traceParsedData);
247
+ const requests = LanternComputationData.createNetworkRequests(trace, parsedTrace, startTime, endTime);
248
+ const graph = LanternComputationData.createGraph(requests, trace, parsedTrace);
249
+ const processedNavigation = LanternComputationData.createProcessedNavigation(parsedTrace, frameId, navigationId);
230
250
  const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
231
251
  const simulator = Lantern.Simulation.Simulator.createSimulator({
252
+ // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture
253
+ // that? Do we need to set 'devtools' throttlingMethod?
232
254
  networkAnalysis,
233
- throttlingMethod: 'simulate',
255
+ throttlingMethod: 'provided',
234
256
  });
235
257
  const computeData = { graph, simulator, processedNavigation };
236
258
  const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);
@@ -245,63 +267,122 @@ export class TraceProcessor extends EventTarget {
245
267
  };
246
268
  return { graph, simulator, metrics };
247
269
  }
270
+ #computeInsightSets(insights, parsedTrace, insightRunners, context) {
271
+ const data = {};
272
+ for (const [name, insight] of Object.entries(insightRunners)) {
273
+ let insightResult;
274
+ try {
275
+ insightResult = insight.generateInsight(parsedTrace, context);
276
+ }
277
+ catch (err) {
278
+ insightResult = err;
279
+ }
280
+ Object.assign(data, { [name]: insightResult });
281
+ }
282
+ let id, urlString, navigation;
283
+ if (context.navigation) {
284
+ id = context.navigationId;
285
+ urlString = context.navigation.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;
286
+ navigation = context.navigation;
287
+ }
288
+ else {
289
+ id = Types.Events.NO_NAVIGATION;
290
+ urlString = parsedTrace.Meta.mainFrameURL;
291
+ }
292
+ let url;
293
+ try {
294
+ url = new URL(urlString);
295
+ }
296
+ catch {
297
+ // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't
298
+ // happen for real traces.
299
+ return;
300
+ }
301
+ const insightSets = {
302
+ id,
303
+ url,
304
+ navigation,
305
+ frameId: context.frameId,
306
+ bounds: context.bounds,
307
+ data,
308
+ };
309
+ insights.set(insightSets.id, insightSets);
310
+ }
248
311
  /**
249
312
  * Run all the insights and set the result to `#insights`.
250
313
  */
251
- #computeInsights(traceParsedData, traceEvents) {
314
+ #computeInsights(parsedTrace, traceEvents) {
252
315
  this.#insights = new Map();
253
- const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(traceParsedData);
254
- // The lantern sub-context is optional on NavigationInsightContext, so not setting it is OK.
255
- // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.
256
- // Additionally, many trace fixtures are too old to be processed by Lantern.
257
- // TODO(crbug.com/313905799): should be created and scoped per-navigation.
258
- let lantern;
259
- try {
260
- lantern = this.#createLanternContext(traceParsedData, traceEvents);
261
- }
262
- catch (e) {
263
- // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.
264
- // Log unexpected errors, but suppress anything that occurs from a trace being too old.
265
- // Otherwise tests using old fixtures become way too noisy.
266
- const expectedErrors = [
267
- 'mainDocumentRequest not found',
268
- 'missing metric scores for main frame',
269
- 'missing metric: FCP',
270
- 'missing metric: LCP',
271
- 'No network requests found in trace',
272
- 'Trace is too old',
273
- ];
274
- if (!(e instanceof Lantern.Core.LanternError)) {
275
- // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.
276
- console.error(e);
277
- }
278
- else if (!expectedErrors.some(err => e.message === err)) {
279
- // To reduce noise from tests, only print errors that are not expected to occur because a trace is
280
- // too old (for which there is no single check).
281
- console.error(e.message);
316
+ const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(parsedTrace);
317
+ const navigations = parsedTrace.Meta.mainFrameNavigations.filter(navigation => navigation.args.frame && navigation.args.data?.navigationId);
318
+ // Check if there is a meaningful chunk of work happening prior to the first navigation.
319
+ // If so, we run the insights on that initial bounds.
320
+ // Otherwise, there are no navigations and we do a no-navigation insights pass on the entire trace.
321
+ if (navigations.length) {
322
+ const bounds = Helpers.Timing.traceWindowFromMicroSeconds(parsedTrace.Meta.traceBounds.min, navigations[0].ts);
323
+ // When using "Record and reload" option, it typically takes ~5ms. So use 50ms to be safe.
324
+ const threshold = Helpers.Timing.millisecondsToMicroseconds(50);
325
+ if (bounds.range > threshold) {
326
+ const context = {
327
+ bounds,
328
+ frameId: parsedTrace.Meta.mainFrameId,
329
+ };
330
+ this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);
282
331
  }
332
+ // If threshold is not met, then the very beginning of the trace is ignored by the insights engine.
283
333
  }
284
- for (const nav of traceParsedData.Meta.mainFrameNavigations) {
285
- if (!nav.args.frame || !nav.args.data?.navigationId) {
286
- continue;
287
- }
334
+ else {
288
335
  const context = {
289
- frameId: nav.args.frame,
290
- navigationId: nav.args.data.navigationId,
291
- lantern,
336
+ bounds: parsedTrace.Meta.traceBounds,
337
+ frameId: parsedTrace.Meta.mainFrameId,
292
338
  };
293
- const navInsightData = {};
294
- for (const [name, insight] of Object.entries(enabledInsightRunners)) {
295
- let insightResult;
296
- try {
297
- insightResult = insight.generateInsight(traceParsedData, context);
339
+ this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);
340
+ }
341
+ // Now run the insights for each navigation in isolation.
342
+ for (const [i, navigation] of navigations.entries()) {
343
+ // The above filter guarantees these are present.
344
+ const frameId = navigation.args.frame;
345
+ const navigationId = navigation.args.data?.navigationId;
346
+ // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.
347
+ // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.
348
+ // Additionally, many trace fixtures are too old to be processed by Lantern.
349
+ let lantern;
350
+ try {
351
+ lantern = this.#createLanternContext(parsedTrace, traceEvents, frameId, navigationId);
352
+ }
353
+ catch (e) {
354
+ // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.
355
+ // Log unexpected errors, but suppress anything that occurs from a trace being too old.
356
+ // Otherwise tests using old fixtures become way too noisy.
357
+ const expectedErrors = [
358
+ 'mainDocumentRequest not found',
359
+ 'missing metric scores for main frame',
360
+ 'missing metric: FCP',
361
+ 'missing metric: LCP',
362
+ 'No network requests found in trace',
363
+ 'Trace is too old',
364
+ ];
365
+ if (!(e instanceof Lantern.Core.LanternError)) {
366
+ // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.
367
+ console.error(e);
298
368
  }
299
- catch (err) {
300
- insightResult = err;
369
+ else if (!expectedErrors.some(err => e.message === err)) {
370
+ // To reduce noise from tests, only print errors that are not expected to occur because a trace is
371
+ // too old (for which there is no single check).
372
+ console.error(e.message);
301
373
  }
302
- Object.assign(navInsightData, { [name]: insightResult });
303
374
  }
304
- this.#insights.set(context.navigationId, navInsightData);
375
+ const min = navigation.ts;
376
+ const max = i + 1 < navigations.length ? navigations[i + 1].ts : parsedTrace.Meta.traceBounds.max;
377
+ const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);
378
+ const context = {
379
+ bounds,
380
+ frameId,
381
+ navigation,
382
+ navigationId,
383
+ lantern,
384
+ };
385
+ this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);
305
386
  }
306
387
  }
307
388
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAc1C,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAE7B;IADnB,MAAM,CAAU,SAAS,GAAG,oBAAoB,CAAC;IACjD,YAAmB,IAAiC,EAAE,OAAkB,EAAC,OAAO,EAAE,IAAI,EAAC;QACrF,KAAK,CAAC,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAD9B,SAAI,GAAJ,IAAI,CAA6B;IAEpD,CAAC;;AAQH,MAAM,OAAO,cAAe,SAAQ,WAAW;IAC7C,6EAA6E;IAC7E,8DAA8D;IACrD,cAAc,CAAmC;IAC1D,OAAO,4BAAe;IACtB,mBAAmB,GAAG,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACrD,KAAK,GAAuC,IAAI,CAAC;IACjD,SAAS,GAAyC,IAAI,CAAC;IAEvD,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,cAAc,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,eAA8C;QAE5E,MAAM,eAAe,GAAG,EAAuC,CAAC;QAChE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC5C,SAAS;YACX,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,YAAY,aAA+C,EAAE,kBAAsD;QACjH,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QACpC,IAAI,CAAC,cAAc,GAAG;YACpB,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI;YACjC,GAAG,aAAa;SACjB,CAAC;QACF,IAAI,kBAAkB,EAAE,CAAC;YACvB,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,qBAAqB;QACnB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACzD,yEAAyE;YACzE,4DAA4D;YAC5D,IAAI,kBAAkB,IAAI,OAAO,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;gBAC9D,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;QAMI;IACJ,eAAe,CAAC,gBAAkD;QAChE,2EAA2E;QAC3E,wEAAwE;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,0BAA0B;QAC1B,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,MAAM,EAAE,CAAC;YACxF,OAAO;QACT,CAAC;QACD,MAAM,mBAAmB,GAA8C,IAAI,GAAG,EAAE,CAAC;QACjF,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACtE,mBAAmB,CAAC,GAAG,CAAC,WAAmD,CAAC,CAAC;YAC7E,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;gBAC3B,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACnE,mEAAmE;QACnE,2EAA2E;QAC3E,qCAAqC;QACrC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEnC,KAAK,MAAM,WAAW,IAAI,mBAAmB,EAAE,CAAC;YAC9C,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,oBAAoB,WAAW,gBAAgB,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,mCAAmB,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,2BAAc,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAwD,EAAE,cAAc,GAAG,KAAK;QAC1F,IAAI,IAAI,CAAC,OAAO,6BAAgB,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qEAAqE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,iCAAiB,CAAC;YAC9B,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAChE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;YACjD,CAAC;YACD,IAAI,CAAC,OAAO,mDAA0B,CAAC;QACzC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,6DAA+B,CAAC;YAC5C,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAAC,WAAwD,EAAE,cAAuB;QAE7G;;;;;;;WAOG;QACH,MAAM,cAAc,GAAG,MAAM,CAAC;QAC9B,+EAA+E;QAC/E,MAAM,cAAc,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAEvE,SAAS;QACT,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,cAAc;QACd,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,OAAO,CAAC,UAAU,EAAE,CAAC,cAAc,CAAC,CAAC;QACvC,CAAC;QAED,qBAAqB;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YAC5C,iDAAiD;YACjD,IAAI,CAAC,GAAG,cAAc,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,wDAAwD;gBACxD,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAC,CAAC,CAAC,CAAC;gBACvF,qHAAqH;gBACrH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC/C,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,YAAY;QACZ,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,4DAA4D;gBAC5D,yHAAyH;gBACzH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrD,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,iFAAiF;QACjF,gFAAgF;QAChF,iFAAiF;QACjF,gFAAgF;QAChF,+CAA+C;QAC/C,sBAAsB;QACtB,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,OAAO,GAAG,IAAI,EAAW,EAAE;YAC/D,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;gBACzB,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;gBACzB,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;YACpB,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;gBAClD,MAAM,GAAG,GAA4B,EAAE,CAAC;gBACxC,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7C,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBACpC,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,eAAe,GAAG,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,eAAgD,CAAC;IAChE,CAAC;IAED,IAAI,eAAe;QACjB,IAAI,IAAI,CAAC,OAAO,qDAA4B,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,QAAQ;QACV,IAAI,IAAI,CAAC,OAAO,qDAA4B,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,qBAAqB,CACjB,eAA8C,EAC9C,WAAwD;QAC1D,+BAA+B;QAC/B,IAAI,CAAC,eAAe,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,CAAC;YACrG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,oCAAoC,CAAC,CAAC;QAC5E,CAAC;QAED,mFAAmF;QACnF,4GAA4G;QAC5G,MAAM,KAAK,GAAwB;YACjC,WAAW,EAAE,WAAoD;SAClE,CAAC;QAEF,MAAM,QAAQ,GAAG,sBAAsB,CAAC,qBAAqB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,sBAAsB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;QACnF,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,yBAAyB,CAAC,eAAe,CAAC,CAAC;QAE9F,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvE,MAAM,SAAS,GACX,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC;YAC3C,eAAe;YACf,gBAAgB,EAAE,UAAU;SAC7B,CAAC,CAAC;QAEP,MAAM,WAAW,GAAG,EAAC,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;QAC3F,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;QACxF,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAE,iBAAiB,EAAC,CAAC,CAAC;QACzG,MAAM,OAAO,GAAG;YACd,oBAAoB,EAAE,SAAS;YAC/B,WAAW,EAAE,iBAAiB;YAC9B,sBAAsB,EAAE,SAAS;YACjC,iBAAiB,EAAE,SAAS;SAC7B,CAAC;QAEF,OAAO,EAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,gBAAgB,CACZ,eAA8C,EAAE,WAAwD;QAC1G,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QAE3B,MAAM,qBAAqB,GAAG,cAAc,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC;QAEvF,4FAA4F;QAC5F,2GAA2G;QAC3G,4EAA4E;QAC5E,0EAA0E;QAC1E,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,oGAAoG;YACpG,uFAAuF;YACvF,2DAA2D;YAC3D,MAAM,cAAc,GAAG;gBACrB,+BAA+B;gBAC/B,sCAAsC;gBACtC,qBAAqB;gBACrB,qBAAqB;gBACrB,oCAAoC;gBACpC,kBAAkB;aACnB,CAAC;YACF,IAAI,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9C,yFAAyF;gBACzF,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;iBAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC1D,kGAAkG;gBAClG,gDAAgD;gBAChD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAA4C;gBACvD,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;gBACvB,YAAY,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY;gBACxC,OAAO;aACR,CAAC;YAEF,MAAM,cAAc,GAAG,EAA0C,CAAC;YAClE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBACpE,IAAI,aAAa,CAAC;gBAClB,IAAI,CAAC;oBACH,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;gBACpE,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,aAAa,GAAG,GAAG,CAAC;gBACtB,CAAC;gBACD,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAC,CAAC,CAAC;YACzD,CAAC;YAED,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CACxB,aAAyG;IAE3G,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0E,CAAC;IACpG,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwC,CAAC;IAChE,MAAM,YAAY,GAAG,CAAC,WAAiD,EAAQ,EAAE;QAC/E,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;gBAC9B,IAAI,SAAS,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBACzC,SAAS,IAAI,GAAG,OAAO,IAAI,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,SAAS,IAAI,WAAW,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACrD,YAAY,CAAC,WAAmD,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,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.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.TraceParseData|null = null;\n #insights: Insights.Types.TraceInsightData|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n static getEnabledInsightRunners(traceParsedData: Handlers.Types.TraceParseData):\n Partial<Insights.Types.InsightRunnersType> {\n const enabledInsights = {} as Insights.Types.InsightRunnersType;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !traceParsedData[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight});\n }\n return enabledInsights;\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#computeTraceParsedData(traceEvents, freshRecording);\n if (this.#data) {\n this.#computeInsights(this.#data, traceEvents);\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeTraceParsedData(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n this.dispatchEvent(new TraceParseProgressEvent({index: i, total: traceEvents.length}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n if (handler.finalize) {\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize();\n }\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const traceParsedData = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(traceParsedData, {[name]: data});\n }\n\n this.#data = traceParsedData as Handlers.Types.TraceParseData;\n }\n\n get traceParsedData(): Handlers.Types.TraceParseData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n traceParsedData: Handlers.Types.TraceParseData,\n traceEvents: readonly Types.TraceEvents.TraceEventData[]): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!traceParsedData.NetworkRequests || !traceParsedData.Workers || !traceParsedData.PageLoadMetrics) {\n return;\n }\n if (!traceParsedData.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n // Lantern.Types.TraceEvent and Types.TraceEvents.TraceEventData represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: traceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, traceParsedData);\n const graph = LanternComputationData.createGraph(requests, trace, traceParsedData);\n const processedNavigation = LanternComputationData.createProcessedNavigation(traceParsedData);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n const simulator: Lantern.Simulation.Simulator<Types.TraceEvents.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator({\n networkAnalysis,\n throttlingMethod: 'simulate',\n });\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {graph, simulator, metrics};\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n traceParsedData: Handlers.Types.TraceParseData, traceEvents: readonly Types.TraceEvents.TraceEventData[]): void {\n this.#insights = new Map();\n\n const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(traceParsedData);\n\n // The lantern sub-context is optional on NavigationInsightContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n // TODO(crbug.com/313905799): should be created and scoped per-navigation.\n let lantern;\n try {\n lantern = this.#createLanternContext(traceParsedData, traceEvents);\n } catch (e) {\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e.message);\n }\n }\n\n for (const nav of traceParsedData.Meta.mainFrameNavigations) {\n if (!nav.args.frame || !nav.args.data?.navigationId) {\n continue;\n }\n\n const context: Insights.Types.NavigationInsightContext = {\n frameId: nav.args.frame,\n navigationId: nav.args.data.navigationId,\n lantern,\n };\n\n const navInsightData = {} as Insights.Types.NavigationInsightData;\n for (const [name, insight] of Object.entries(enabledInsightRunners)) {\n let insightResult;\n try {\n insightResult = insight.generateInsight(traceParsedData, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(navInsightData, {[name]: insightResult});\n }\n\n this.#insights.set(context.navigationId, navInsightData);\n }\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n"]}
1
+ {"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.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.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport type * as Model from './ModelImpl.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: Model.TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\n\n/**\n * Parsing a trace can take time. On large traces we see a breakdown of time like so:\n * - handleEvent() loop: ~20%\n * - finalize() loop: ~60%\n * - shallowClone calls: ~20%\n * The numbers below are set so we can report a progress percentage of [0...1]\n */\nconst enum ProgressPhase {\n HANDLE_EVENT = 0.2,\n FINALIZE = 0.8,\n CLONE = 1.0,\n}\nfunction calculateProgress(value: number, phase: ProgressPhase): number {\n // Finalize values should be [0.2...0.8]\n if (phase === ProgressPhase.FINALIZE) {\n return (value * (ProgressPhase.FINALIZE - ProgressPhase.HANDLE_EVENT)) + ProgressPhase.HANDLE_EVENT;\n }\n return value * phase;\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport interface ParseOptions {\n /**\n * If the trace was just recorded on the current page, rather than an imported file.\n * @default false\n */\n isFreshRecording?: boolean;\n /**\n * If the trace is a CPU Profile rather than a Chrome tracing trace.\n * @default false\n */\n isCPUProfile?: boolean;\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.ParsedTrace|null = null;\n #insights: Insights.Types.TraceInsightSets|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n static getEnabledInsightRunners(parsedTrace: Handlers.Types.ParsedTrace): Partial<Insights.Types.InsightRunnersType> {\n const enabledInsights = {} as Insights.Types.InsightRunnersType;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !parsedTrace[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight});\n }\n return enabledInsights;\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.HandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.HandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.Events.Event[], options: ParseOptions): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#computeParsedTrace(traceEvents, Boolean(options.isFreshRecording));\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n this.#computeInsights(this.#data, traceEvents);\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], freshRecording: boolean): Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n const percent = calculateProgress(i / traceEvents.length, ProgressPhase.HANDLE_EVENT);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const [i, handler] of sortedHandlers.entries()) {\n if (handler.finalize) {\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize();\n }\n const percent = calculateProgress(i / sortedHandlers.length, ProgressPhase.FINALIZE);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const parsedTrace = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(parsedTrace, {[name]: data});\n }\n this.dispatchEvent(new TraceParseProgressEvent({percent: ProgressPhase.CLONE}));\n\n this.#data = parsedTrace as Handlers.Types.ParsedTrace;\n }\n\n get parsedTrace(): Handlers.Types.ParsedTrace|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightSets|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[], frameId: string,\n navigationId: string): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!parsedTrace.NetworkRequests || !parsedTrace.Workers || !parsedTrace.PageLoadMetrics) {\n return;\n }\n if (!parsedTrace.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n const navStarts = parsedTrace.Meta.navigationsByFrameId.get(frameId);\n const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);\n if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {\n throw new Lantern.Core.LanternError('Could not find navigation start');\n }\n\n const startTime = navStarts[navStartIndex].ts;\n const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;\n const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);\n\n // Lantern.Types.TraceEvent and Types.Events.Event represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: boundedTraceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, parsedTrace, startTime, endTime);\n const graph = LanternComputationData.createGraph(requests, trace, parsedTrace);\n const processedNavigation = LanternComputationData.createProcessedNavigation(parsedTrace, frameId, navigationId);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator({\n // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture\n // that? Do we need to set 'devtools' throttlingMethod?\n networkAnalysis,\n throttlingMethod: 'provided',\n });\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {graph, simulator, metrics};\n }\n\n #computeInsightSets(\n insights: Insights.Types.TraceInsightSets, parsedTrace: Handlers.Types.ParsedTrace,\n insightRunners: Partial<typeof Insights.InsightRunners>, context: Insights.Types.InsightSetContext): void {\n const data = {} as Insights.Types.InsightSets['data'];\n\n for (const [name, insight] of Object.entries(insightRunners)) {\n let insightResult;\n try {\n insightResult = insight.generateInsight(parsedTrace, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(data, {[name]: insightResult});\n }\n\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString = context.navigation.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = parsedTrace.Meta.mainFrameURL;\n }\n\n let url;\n try {\n url = new URL(urlString);\n } catch {\n // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't\n // happen for real traces.\n return;\n }\n\n const insightSets = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n data,\n };\n insights.set(insightSets.id, insightSets);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[]): void {\n this.#insights = new Map();\n\n const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(parsedTrace);\n\n const navigations = parsedTrace.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n // Check if there is a meaningful chunk of work happening prior to the first navigation.\n // If so, we run the insights on that initial bounds.\n // Otherwise, there are no navigations and we do a no-navigation insights pass on the entire trace.\n if (navigations.length) {\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(parsedTrace.Meta.traceBounds.min, navigations[0].ts);\n // When using \"Record and reload\" option, it typically takes ~5ms. So use 50ms to be safe.\n const threshold = Helpers.Timing.millisecondsToMicroseconds(50 as Types.Timing.MilliSeconds);\n if (bounds.range > threshold) {\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId: parsedTrace.Meta.mainFrameId,\n };\n this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);\n }\n // If threshold is not met, then the very beginning of the trace is ignored by the insights engine.\n } else {\n const context: Insights.Types.InsightSetContext = {\n bounds: parsedTrace.Meta.traceBounds,\n frameId: parsedTrace.Meta.mainFrameId,\n };\n this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);\n }\n\n // Now run the insights for each navigation in isolation.\n for (const [i, navigation] of navigations.entries()) {\n // The above filter guarantees these are present.\n const frameId = navigation.args.frame;\n const navigationId = navigation.args.data?.navigationId as string;\n\n // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n let lantern;\n try {\n lantern = this.#createLanternContext(parsedTrace, traceEvents, frameId, navigationId);\n } catch (e) {\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e.message);\n }\n }\n\n const min = navigation.ts;\n const max = i + 1 < navigations.length ? navigations[i + 1].ts : parsedTrace.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n\n this.#computeInsightSets(this.#insights, parsedTrace, enabledInsightRunners, context);\n }\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<{[key in Handlers.Types.HandlerName]: Handlers.Types.Handler}>):\n Map<Handlers.Types.HandlerName, Handlers.Types.Handler> {\n const sortedMap = new Map<Handlers.Types.HandlerName, Handlers.Types.Handler>();\n const visited = new Set<Handlers.Types.HandlerName>();\n const visitHandler = (handlerName: Handlers.Types.HandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.HandlerName);\n }\n return sortedMap;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TracingManager.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/TracingManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2014 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 SDK from '../../core/sdk/sdk.js';\nimport type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';\nimport * as Protocol from '../../generated/protocol.js';\n\nimport type * as Types from './types/types.js';\n\nexport class TracingManager extends SDK.SDKModel.SDKModel<void> {\n readonly #tracingAgent: ProtocolProxyApi.TracingApi;\n #activeClient: TracingManagerClient|null;\n #eventBufferSize: number|null;\n #eventsRetrieved: number;\n #finishing?: boolean;\n constructor(target: SDK.Target.Target) {\n super(target);\n this.#tracingAgent = target.tracingAgent();\n target.registerTracingDispatcher(new TracingDispatcher(this));\n\n this.#activeClient = null;\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n }\n\n bufferUsage(usage?: number, eventCount?: number, percentFull?: number): void {\n this.#eventBufferSize = eventCount === undefined ? null : eventCount;\n if (this.#activeClient) {\n this.#activeClient.tracingBufferUsage(usage || percentFull || 0);\n }\n }\n\n eventsCollected(events: Types.TraceEvents.TraceEventData[]): void {\n if (!this.#activeClient) {\n return;\n }\n this.#activeClient.traceEventsCollected(events);\n this.#eventsRetrieved += events.length;\n if (!this.#eventBufferSize) {\n this.#activeClient.eventsRetrievalProgress(0);\n return;\n }\n\n if (this.#eventsRetrieved > this.#eventBufferSize) {\n this.#eventsRetrieved = this.#eventBufferSize;\n }\n this.#activeClient.eventsRetrievalProgress(this.#eventsRetrieved / this.#eventBufferSize);\n }\n\n tracingComplete(): void {\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n if (this.#activeClient) {\n this.#activeClient.tracingComplete();\n this.#activeClient = null;\n }\n this.#finishing = false;\n }\n\n async reset(): Promise<void> {\n // If we have an active client, we should try to stop\n // it before resetting it, else we will leave the\n // backend in a broken state where it thinks we are in\n // the middle of tracing, but we think we are not.\n // Then, any subsequent attempts to record will fail\n // because the backend will not let us start a second\n // tracing session.\n if (this.#activeClient) {\n await this.#tracingAgent.invoke_end();\n }\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n this.#activeClient = null;\n this.#finishing = false;\n }\n\n // TODO(petermarshall): Use the traceConfig argument instead of deprecated\n // categories + options.\n async start(client: TracingManagerClient, categoryFilter: string, options: string):\n Promise<Protocol.ProtocolResponseWithError> {\n if (this.#activeClient) {\n throw new Error('Tracing is already started');\n }\n const bufferUsageReportingIntervalMs = 500;\n this.#activeClient = client;\n const args = {\n bufferUsageReportingInterval: bufferUsageReportingIntervalMs,\n categories: categoryFilter,\n options: options,\n transferMode: Protocol.Tracing.StartRequestTransferMode.ReportEvents,\n };\n const response = await this.#tracingAgent.invoke_start(args);\n if (response.getError()) {\n this.#activeClient = null;\n }\n return response;\n }\n\n stop(): void {\n if (!this.#activeClient) {\n throw new Error('Tracing is not started');\n }\n if (this.#finishing) {\n throw new Error('Tracing is already being stopped');\n }\n this.#finishing = true;\n void this.#tracingAgent.invoke_end();\n }\n}\n\nexport interface TracingManagerClient {\n traceEventsCollected(events: Types.TraceEvents.TraceEventData[]): void;\n\n tracingComplete(): void;\n tracingBufferUsage(usage: number): void;\n eventsRetrievalProgress(progress: number): void;\n}\n\nclass TracingDispatcher implements ProtocolProxyApi.TracingDispatcher {\n readonly #tracingManager: TracingManager;\n constructor(tracingManager: TracingManager) {\n this.#tracingManager = tracingManager;\n }\n\n bufferUsage({value, eventCount, percentFull}: Protocol.Tracing.BufferUsageEvent): void {\n this.#tracingManager.bufferUsage(value, eventCount, percentFull);\n }\n\n dataCollected({value}: Protocol.Tracing.DataCollectedEvent): void {\n this.#tracingManager.eventsCollected(value);\n }\n\n tracingComplete(): void {\n this.#tracingManager.tracingComplete();\n }\n}\n\nSDK.SDKModel.SDKModel.register(TracingManager, {capabilities: SDK.Target.Capability.Tracing, autostart: false});\n"]}
1
+ {"version":3,"file":"TracingManager.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/TracingManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2014 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 SDK from '../../core/sdk/sdk.js';\nimport type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';\nimport * as Protocol from '../../generated/protocol.js';\n\nimport type * as Types from './types/types.js';\n\nexport class TracingManager extends SDK.SDKModel.SDKModel<void> {\n readonly #tracingAgent: ProtocolProxyApi.TracingApi;\n #activeClient: TracingManagerClient|null;\n #eventsRetrieved: number;\n #finishing?: boolean;\n constructor(target: SDK.Target.Target) {\n super(target);\n this.#tracingAgent = target.tracingAgent();\n target.registerTracingDispatcher(new TracingDispatcher(this));\n\n this.#activeClient = null;\n this.#eventsRetrieved = 0;\n }\n\n bufferUsage(usage?: number, eventCount?: number, percentFull?: number): void {\n if (this.#activeClient) {\n this.#activeClient.tracingBufferUsage(usage || percentFull || 0);\n }\n }\n\n eventsCollected(events: Types.Events.Event[]): void {\n if (!this.#activeClient) {\n return;\n }\n this.#activeClient.traceEventsCollected(events);\n this.#eventsRetrieved += events.length;\n\n // CDP no longer provides an approximate_event_count AKA eventCount. It's always 0.\n // To give some idea of progress we'll compare to a large (900k event) trace.\n // And we'll clamp both sides so the user sees some progress, and never maxed at 99%\n const progress = Math.min((this.#eventsRetrieved / 900_000) + 0.15, 0.90);\n this.#activeClient.eventsRetrievalProgress(progress);\n }\n\n tracingComplete(): void {\n this.#eventsRetrieved = 0;\n if (this.#activeClient) {\n this.#activeClient.tracingComplete();\n this.#activeClient = null;\n }\n this.#finishing = false;\n }\n\n async reset(): Promise<void> {\n // If we have an active client, we should try to stop\n // it before resetting it, else we will leave the\n // backend in a broken state where it thinks we are in\n // the middle of tracing, but we think we are not.\n // Then, any subsequent attempts to record will fail\n // because the backend will not let us start a second\n // tracing session.\n if (this.#activeClient) {\n await this.#tracingAgent.invoke_end();\n }\n this.#eventsRetrieved = 0;\n this.#activeClient = null;\n this.#finishing = false;\n }\n\n // TODO(petermarshall): Use the traceConfig argument instead of deprecated\n // categories + options.\n async start(client: TracingManagerClient, categoryFilter: string, options: string):\n Promise<Protocol.ProtocolResponseWithError> {\n if (this.#activeClient) {\n throw new Error('Tracing is already started');\n }\n const bufferUsageReportingIntervalMs = 500;\n this.#activeClient = client;\n const args = {\n bufferUsageReportingInterval: bufferUsageReportingIntervalMs,\n categories: categoryFilter,\n options,\n transferMode: Protocol.Tracing.StartRequestTransferMode.ReportEvents,\n };\n const response = await this.#tracingAgent.invoke_start(args);\n if (response.getError()) {\n this.#activeClient = null;\n }\n return response;\n }\n\n stop(): void {\n if (!this.#activeClient) {\n throw new Error('Tracing is not started');\n }\n if (this.#finishing) {\n throw new Error('Tracing is already being stopped');\n }\n this.#finishing = true;\n void this.#tracingAgent.invoke_end();\n }\n}\n\nexport interface TracingManagerClient {\n traceEventsCollected(events: Types.Events.Event[]): void;\n\n tracingComplete(): void;\n tracingBufferUsage(usage: number): void;\n eventsRetrievalProgress(progress: number): void;\n}\n\nclass TracingDispatcher implements ProtocolProxyApi.TracingDispatcher {\n readonly #tracingManager: TracingManager;\n constructor(tracingManager: TracingManager) {\n this.#tracingManager = tracingManager;\n }\n\n // `eventCount` will always be 0 as perfetto no longer calculates `approximate_event_count`\n bufferUsage({value, eventCount, percentFull}: Protocol.Tracing.BufferUsageEvent): void {\n this.#tracingManager.bufferUsage(value, eventCount, percentFull);\n }\n\n dataCollected({value}: Protocol.Tracing.DataCollectedEvent): void {\n this.#tracingManager.eventsCollected(value);\n }\n\n tracingComplete(): void {\n this.#tracingManager.tracingComplete();\n }\n}\n\nSDK.SDKModel.SDKModel.register(TracingManager, {capabilities: SDK.Target.Capability.TRACING, autostart: false});\n"]}
@@ -5,10 +5,10 @@ import * as Types from '../types/types.js';
5
5
  export declare function clearCacheForTesting(): void;
6
6
  /**
7
7
  * Looks up the DOM Node on the page for the given BackendNodeId. Uses the
8
- * provided TraceParseData as the cache and will cache the result after the
8
+ * provided ParsedTrace as the cache and will cache the result after the
9
9
  * first lookup.
10
10
  */
11
- export declare function domNodeForBackendNodeID(modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode | null>;
11
+ export declare function domNodeForBackendNodeID(modelData: Handlers.Types.ParsedTrace, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode | null>;
12
12
  /**
13
13
  * Extracts a set of NodeIds for a given event.
14
14
  * NOTE: you probably don't want to call this and instead use
@@ -16,19 +16,19 @@ export declare function domNodeForBackendNodeID(modelData: Handlers.Types.TraceP
16
16
  * This method is primarily exported so we can test the logic more easily
17
17
  * without having to mock the CDP layer.
18
18
  **/
19
- export declare function nodeIdsForEvent(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventData): Set<Protocol.DOM.BackendNodeId>;
19
+ export declare function nodeIdsForEvent(modelData: Handlers.Types.ParsedTrace, event: Types.Events.Event): Set<Protocol.DOM.BackendNodeId>;
20
20
  /**
21
21
  * Looks up for backend node ids in different types of trace events
22
22
  * and resolves them into related DOM nodes.
23
23
  * This method should be progressively updated to support more events
24
24
  * containing node ids which we want to resolve.
25
25
  */
26
- export declare function extractRelatedDOMNodesFromEvent(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventData): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null> | null>;
26
+ export declare function extractRelatedDOMNodesFromEvent(modelData: Handlers.Types.ParsedTrace, event: Types.Events.Event): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null> | null>;
27
27
  /**
28
28
  * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.
29
- * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.
29
+ * Results are cached based on 1) the provided ParsedTrace and 2) the provided set of IDs.
30
30
  */
31
- export declare function domNodesForMultipleBackendNodeIds(modelData: Handlers.Types.TraceParseData, nodeIds: Array<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null>>;
31
+ export declare function domNodesForMultipleBackendNodeIds(modelData: Handlers.Types.ParsedTrace, nodeIds: Array<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null>>;
32
32
  export interface LayoutShiftSource {
33
33
  previousRect: DOMRect;
34
34
  currentRect: DOMRect;
@@ -45,7 +45,7 @@ export interface LayoutShiftSource {
45
45
  * This data is cached based on the provided model data and the given layout
46
46
  * shift, so it is is safe to call multiple times with the same input.
47
47
  */
48
- export declare function sourcesForLayoutShift(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]>;
48
+ export declare function sourcesForLayoutShift(modelData: Handlers.Types.ParsedTrace, event: Types.Events.LayoutShift): Promise<readonly LayoutShiftSource[]>;
49
49
  /**
50
50
  * Takes a LayoutShift and normalizes its node dimensions based on the device
51
51
  * pixel ratio (DPR) of the user's display.
@@ -58,4 +58,4 @@ export declare function sourcesForLayoutShift(modelData: Handlers.Types.TracePar
58
58
  * the provided model data.
59
59
  * See https://crbug.com/1300309 for details.
60
60
  */
61
- export declare function normalizedImpactedNodesForLayoutShift(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]>;
61
+ export declare function normalizedImpactedNodesForLayoutShift(modelData: Handlers.Types.ParsedTrace, event: Types.Events.LayoutShift): Promise<readonly Types.Events.TraceImpactedNode[]>;