@paulirish/trace_engine 0.0.56 → 0.0.58

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 (305) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/README.md +2 -2
  3. package/core/platform/Brand.d.ts +8 -1
  4. package/core/platform/Brand.js.map +1 -1
  5. package/core/platform/DevToolsPath.d.ts +1 -1
  6. package/core/platform/DevToolsPath.js +1 -1
  7. package/core/platform/DevToolsPath.js.map +1 -1
  8. package/core/platform/StringUtilities.d.ts +12 -2
  9. package/core/platform/StringUtilities.js +31 -7
  10. package/core/platform/StringUtilities.js.map +1 -1
  11. package/generated/protocol.d.ts +8290 -7994
  12. package/locales/af.json +82 -67
  13. package/locales/am.json +82 -67
  14. package/locales/ar.json +93 -78
  15. package/locales/as.json +82 -67
  16. package/locales/az.json +82 -67
  17. package/locales/be.json +81 -66
  18. package/locales/bg.json +82 -67
  19. package/locales/bn.json +82 -67
  20. package/locales/bs.json +82 -67
  21. package/locales/ca.json +82 -67
  22. package/locales/cs.json +82 -67
  23. package/locales/cy.json +82 -67
  24. package/locales/da.json +82 -67
  25. package/locales/de.json +82 -67
  26. package/locales/el.json +82 -67
  27. package/locales/en-GB.json +82 -67
  28. package/locales/en-US.json +13 -10
  29. package/locales/en-XL.json +13 -10
  30. package/locales/es-419.json +82 -67
  31. package/locales/es.json +82 -67
  32. package/locales/et.json +82 -67
  33. package/locales/eu.json +82 -67
  34. package/locales/fa.json +86 -71
  35. package/locales/fi.json +82 -67
  36. package/locales/fil.json +82 -67
  37. package/locales/fr-CA.json +82 -67
  38. package/locales/fr.json +82 -67
  39. package/locales/gl.json +82 -67
  40. package/locales/gu.json +82 -67
  41. package/locales/he.json +104 -89
  42. package/locales/hi.json +82 -67
  43. package/locales/hr.json +82 -67
  44. package/locales/hu.json +82 -67
  45. package/locales/hy.json +82 -67
  46. package/locales/id.json +82 -67
  47. package/locales/is.json +82 -67
  48. package/locales/it.json +82 -67
  49. package/locales/ja.json +82 -67
  50. package/locales/ka.json +82 -67
  51. package/locales/kk.json +82 -67
  52. package/locales/km.json +82 -67
  53. package/locales/kn.json +81 -66
  54. package/locales/ko.json +82 -67
  55. package/locales/ky.json +81 -66
  56. package/locales/lo.json +82 -67
  57. package/locales/lt.json +82 -67
  58. package/locales/lv.json +82 -67
  59. package/locales/mk.json +82 -67
  60. package/locales/ml.json +82 -67
  61. package/locales/mn.json +82 -67
  62. package/locales/mr.json +81 -66
  63. package/locales/ms.json +81 -66
  64. package/locales/my.json +83 -68
  65. package/locales/ne.json +83 -68
  66. package/locales/nl.json +82 -67
  67. package/locales/no.json +82 -67
  68. package/locales/or.json +82 -67
  69. package/locales/pa.json +81 -66
  70. package/locales/pl.json +82 -67
  71. package/locales/pt-PT.json +82 -67
  72. package/locales/pt.json +82 -67
  73. package/locales/ro.json +82 -67
  74. package/locales/ru.json +82 -67
  75. package/locales/si.json +82 -67
  76. package/locales/sk.json +82 -67
  77. package/locales/sl.json +82 -67
  78. package/locales/sq.json +82 -67
  79. package/locales/sr-Latn.json +82 -67
  80. package/locales/sr.json +82 -67
  81. package/locales/sv.json +82 -67
  82. package/locales/sw.json +81 -66
  83. package/locales/ta.json +82 -67
  84. package/locales/te.json +82 -67
  85. package/locales/th.json +84 -69
  86. package/locales/tr.json +81 -66
  87. package/locales/uk.json +81 -66
  88. package/locales/ur.json +82 -67
  89. package/locales/uz.json +81 -66
  90. package/locales/vi.json +82 -67
  91. package/locales/zh-HK.json +82 -67
  92. package/locales/zh-TW.json +82 -67
  93. package/locales/zh.json +82 -67
  94. package/locales/zu.json +82 -67
  95. package/models/trace/ModelImpl.d.ts +1 -1
  96. package/models/trace/ModelImpl.js +17 -7
  97. package/models/trace/ModelImpl.js.map +1 -1
  98. package/models/trace/Processor.js +26 -16
  99. package/models/trace/Processor.js.map +1 -1
  100. package/models/trace/extras/ThirdParties.js +1 -2
  101. package/models/trace/extras/ThirdParties.js.map +1 -1
  102. package/models/trace/extras/TraceTree.d.ts +4 -2
  103. package/models/trace/extras/TraceTree.js +7 -5
  104. package/models/trace/extras/TraceTree.js.map +1 -1
  105. package/models/trace/handlers/AnimationFramesHandler.d.ts +1 -0
  106. package/models/trace/handlers/AnimationFramesHandler.js +8 -0
  107. package/models/trace/handlers/AnimationFramesHandler.js.map +1 -1
  108. package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +1 -1
  109. package/models/trace/handlers/ExtensionTraceDataHandler.js +29 -15
  110. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  111. package/models/trace/handlers/FramesHandler.js +38 -28
  112. package/models/trace/handlers/FramesHandler.js.map +1 -1
  113. package/models/trace/handlers/ImagePaintingHandler.d.ts +2 -1
  114. package/models/trace/handlers/ImagePaintingHandler.js.map +1 -1
  115. package/models/trace/handlers/InitiatorsHandler.js +27 -0
  116. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  117. package/models/trace/handlers/NetworkRequestsHandler.js +12 -2
  118. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  119. package/models/trace/handlers/RendererHandler.d.ts +0 -5
  120. package/models/trace/handlers/RendererHandler.js +9 -12
  121. package/models/trace/handlers/RendererHandler.js.map +1 -1
  122. package/models/trace/handlers/SamplesHandler.js +6 -12
  123. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  124. package/models/trace/handlers/ScriptsHandler.d.ts +4 -3
  125. package/models/trace/handlers/ScriptsHandler.js +3 -0
  126. package/models/trace/handlers/ScriptsHandler.js.map +1 -1
  127. package/models/trace/handlers/SelectorStatsHandler.d.ts +17 -0
  128. package/models/trace/handlers/SelectorStatsHandler.js +42 -0
  129. package/models/trace/handlers/SelectorStatsHandler.js.map +1 -1
  130. package/models/trace/handlers/UserInteractionsHandler.d.ts +4 -2
  131. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  132. package/models/trace/handlers/helpers.d.ts +3 -6
  133. package/models/trace/handlers/helpers.js +17 -9
  134. package/models/trace/handlers/helpers.js.map +1 -1
  135. package/models/trace/handlers/types.d.ts +4 -1
  136. package/models/trace/handlers/types.js.map +1 -1
  137. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -0
  138. package/models/trace/helpers/SamplesIntegrator.js +21 -21
  139. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  140. package/models/trace/helpers/SyntheticEvents.d.ts +0 -6
  141. package/models/trace/helpers/SyntheticEvents.js +2 -2
  142. package/models/trace/helpers/SyntheticEvents.js.map +1 -1
  143. package/models/trace/helpers/Timing.d.ts +5 -0
  144. package/models/trace/helpers/Timing.js +55 -3
  145. package/models/trace/helpers/Timing.js.map +1 -1
  146. package/models/trace/helpers/Trace.d.ts +1 -1
  147. package/models/trace/helpers/Trace.js +1 -1
  148. package/models/trace/helpers/Trace.js.map +1 -1
  149. package/models/trace/helpers/TreeHelpers.d.ts +1 -1
  150. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  151. package/models/trace/insights/CLSCulprits.d.ts +3 -2
  152. package/models/trace/insights/CLSCulprits.js +24 -2
  153. package/models/trace/insights/CLSCulprits.js.map +1 -1
  154. package/models/trace/insights/Cache.d.ts +2 -0
  155. package/models/trace/insights/Cache.js +10 -0
  156. package/models/trace/insights/Cache.js.map +1 -1
  157. package/models/trace/insights/Common.d.ts +6 -5
  158. package/models/trace/insights/Common.js +29 -17
  159. package/models/trace/insights/Common.js.map +1 -1
  160. package/models/trace/insights/DOMSize.d.ts +2 -1
  161. package/models/trace/insights/DOMSize.js +9 -1
  162. package/models/trace/insights/DOMSize.js.map +1 -1
  163. package/models/trace/insights/DocumentLatency.d.ts +3 -2
  164. package/models/trace/insights/DocumentLatency.js +44 -2
  165. package/models/trace/insights/DocumentLatency.js.map +1 -1
  166. package/models/trace/insights/DuplicatedJavaScript.d.ts +3 -0
  167. package/models/trace/insights/DuplicatedJavaScript.js +12 -3
  168. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
  169. package/models/trace/insights/FontDisplay.d.ts +1 -0
  170. package/models/trace/insights/FontDisplay.js +7 -0
  171. package/models/trace/insights/FontDisplay.js.map +1 -1
  172. package/models/trace/insights/ForcedReflow.d.ts +5 -3
  173. package/models/trace/insights/ForcedReflow.js +20 -3
  174. package/models/trace/insights/ForcedReflow.js.map +1 -1
  175. package/models/trace/insights/INPBreakdown.d.ts +11 -5
  176. package/models/trace/insights/INPBreakdown.js +36 -5
  177. package/models/trace/insights/INPBreakdown.js.map +1 -1
  178. package/models/trace/insights/ImageDelivery.d.ts +4 -0
  179. package/models/trace/insights/ImageDelivery.js +13 -0
  180. package/models/trace/insights/ImageDelivery.js.map +1 -1
  181. package/models/trace/insights/LCPBreakdown.d.ts +7 -6
  182. package/models/trace/insights/LCPBreakdown.js +33 -12
  183. package/models/trace/insights/LCPBreakdown.js.map +1 -1
  184. package/models/trace/insights/LCPDiscovery.d.ts +14 -2
  185. package/models/trace/insights/LCPDiscovery.js +60 -2
  186. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  187. package/models/trace/insights/LegacyJavaScript.d.ts +3 -0
  188. package/models/trace/insights/LegacyJavaScript.js +12 -3
  189. package/models/trace/insights/LegacyJavaScript.js.map +1 -1
  190. package/models/trace/insights/ModernHTTP.d.ts +8 -5
  191. package/models/trace/insights/ModernHTTP.js +27 -14
  192. package/models/trace/insights/ModernHTTP.js.map +1 -1
  193. package/models/trace/insights/NetworkDependencyTree.d.ts +1 -0
  194. package/models/trace/insights/NetworkDependencyTree.js +25 -1
  195. package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
  196. package/models/trace/insights/RenderBlocking.d.ts +3 -1
  197. package/models/trace/insights/RenderBlocking.js +11 -1
  198. package/models/trace/insights/RenderBlocking.js.map +1 -1
  199. package/models/trace/insights/SlowCSSSelector.d.ts +17 -8
  200. package/models/trace/insights/SlowCSSSelector.js +39 -20
  201. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  202. package/models/trace/insights/ThirdParties.d.ts +3 -0
  203. package/models/trace/insights/ThirdParties.js +31 -0
  204. package/models/trace/insights/ThirdParties.js.map +1 -1
  205. package/models/trace/insights/Viewport.d.ts +2 -1
  206. package/models/trace/insights/Viewport.js +16 -0
  207. package/models/trace/insights/Viewport.js.map +1 -1
  208. package/models/trace/insights/types.d.ts +4 -1
  209. package/models/trace/insights/types.js +1 -0
  210. package/models/trace/insights/types.js.map +1 -1
  211. package/models/trace/lantern/graph/BaseNode.d.ts +1 -1
  212. package/models/trace/lantern/graph/BaseNode.js +1 -1
  213. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  214. package/models/trace/lantern/simulation/SimulationTimingMap.js +1 -1
  215. package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
  216. package/models/trace/types/Configuration.d.ts +7 -0
  217. package/models/trace/types/Configuration.js +1 -0
  218. package/models/trace/types/Configuration.js.map +1 -1
  219. package/models/trace/types/Extensions.d.ts +14 -2
  220. package/models/trace/types/Extensions.js +5 -1
  221. package/models/trace/types/Extensions.js.map +1 -1
  222. package/models/trace/types/File.d.ts +3 -0
  223. package/models/trace/types/File.js.map +1 -1
  224. package/models/trace/types/Overlays.d.ts +115 -0
  225. package/models/trace/types/Overlays.js +5 -0
  226. package/models/trace/types/Overlays.js.map +1 -0
  227. package/models/trace/types/TraceEvents.d.ts +79 -36
  228. package/models/trace/types/TraceEvents.js +8 -13
  229. package/models/trace/types/TraceEvents.js.map +1 -1
  230. package/models/trace/types/types-tsconfig.json +1 -0
  231. package/models/trace/types/types.d.ts +1 -0
  232. package/models/trace/types/types.js +1 -0
  233. package/models/trace/types/types.js.map +1 -1
  234. package/package.json +1 -1
  235. package/test/test-trace-engine.mjs +1 -2
  236. package/core/platform/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  237. package/core/platform/platform.prebundle.d.ts +0 -18
  238. package/core/platform/platform.prebundle.js +0 -53
  239. package/core/platform/platform.prebundle.js.map +0 -1
  240. package/core/platform/platform.prebundle.ts +0 -71
  241. package/models/cpu_profile/cpu_profile.prebundle.d.ts +0 -3
  242. package/models/cpu_profile/cpu_profile.prebundle.js +0 -7
  243. package/models/cpu_profile/cpu_profile.prebundle.js.map +0 -1
  244. package/models/cpu_profile/cpu_profile.prebundle.ts +0 -11
  245. package/models/cpu_profile/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  246. package/models/trace/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -61
  247. package/models/trace/extras/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  248. package/models/trace/extras/extras.prebundle.d.ts +0 -7
  249. package/models/trace/extras/extras.prebundle.js +0 -11
  250. package/models/trace/extras/extras.prebundle.js.map +0 -1
  251. package/models/trace/extras/extras.prebundle.ts +0 -11
  252. package/models/trace/handlers/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  253. package/models/trace/handlers/handlers.prebundle.d.ts +0 -4
  254. package/models/trace/handlers/handlers.prebundle.js +0 -8
  255. package/models/trace/handlers/handlers.prebundle.js.map +0 -1
  256. package/models/trace/handlers/handlers.prebundle.ts +0 -8
  257. package/models/trace/helpers/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  258. package/models/trace/helpers/helpers.prebundle.d.ts +0 -7
  259. package/models/trace/helpers/helpers.prebundle.js +0 -11
  260. package/models/trace/helpers/helpers.prebundle.js.map +0 -1
  261. package/models/trace/helpers/helpers.prebundle.ts +0 -11
  262. package/models/trace/insights/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  263. package/models/trace/insights/insights.prebundle.d.ts +0 -4
  264. package/models/trace/insights/insights.prebundle.js +0 -8
  265. package/models/trace/insights/insights.prebundle.js.map +0 -1
  266. package/models/trace/insights/insights.prebundle.ts +0 -8
  267. package/models/trace/lantern/core/core.prebundle.d.ts +0 -2
  268. package/models/trace/lantern/core/core.prebundle.js +0 -6
  269. package/models/trace/lantern/core/core.prebundle.js.map +0 -1
  270. package/models/trace/lantern/core/core.prebundle.ts +0 -6
  271. package/models/trace/lantern/core/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  272. package/models/trace/lantern/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  273. package/models/trace/lantern/graph/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  274. package/models/trace/lantern/graph/graph.prebundle.d.ts +0 -4
  275. package/models/trace/lantern/graph/graph.prebundle.js +0 -8
  276. package/models/trace/lantern/graph/graph.prebundle.js.map +0 -1
  277. package/models/trace/lantern/graph/graph.prebundle.ts +0 -8
  278. package/models/trace/lantern/lantern.prebundle.d.ts +0 -6
  279. package/models/trace/lantern/lantern.prebundle.js +0 -10
  280. package/models/trace/lantern/lantern.prebundle.js.map +0 -1
  281. package/models/trace/lantern/lantern.prebundle.ts +0 -17
  282. package/models/trace/lantern/metrics/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  283. package/models/trace/lantern/metrics/metrics.prebundle.d.ts +0 -8
  284. package/models/trace/lantern/metrics/metrics.prebundle.js +0 -12
  285. package/models/trace/lantern/metrics/metrics.prebundle.js.map +0 -1
  286. package/models/trace/lantern/metrics/metrics.prebundle.ts +0 -12
  287. package/models/trace/lantern/simulation/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  288. package/models/trace/lantern/simulation/simulation.prebundle.d.ts +0 -6
  289. package/models/trace/lantern/simulation/simulation.prebundle.js +0 -10
  290. package/models/trace/lantern/simulation/simulation.prebundle.js.map +0 -1
  291. package/models/trace/lantern/simulation/simulation.prebundle.ts +0 -10
  292. package/models/trace/lantern/types/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  293. package/models/trace/lantern/types/types.prebundle.d.ts +0 -1
  294. package/models/trace/lantern/types/types.prebundle.js +0 -5
  295. package/models/trace/lantern/types/types.prebundle.js.map +0 -1
  296. package/models/trace/lantern/types/types.prebundle.ts +0 -5
  297. package/models/trace/trace.prebundle.d.ts +0 -10
  298. package/models/trace/trace.prebundle.js +0 -14
  299. package/models/trace/trace.prebundle.js.map +0 -1
  300. package/models/trace/trace.prebundle.ts +0 -25
  301. package/models/trace/types/devtools_entrypoint-bundle-tsconfig-tsconfig.json +0 -43
  302. package/models/trace/types/types.prebundle.d.ts +0 -5
  303. package/models/trace/types/types.prebundle.js +0 -9
  304. package/models/trace/types/types.prebundle.js.map +0 -1
  305. package/models/trace/types/types.prebundle.ts +0 -9
@@ -16,7 +16,6 @@ import * as Types from './types/types.js';
16
16
  **/
17
17
  export class Model extends EventTarget {
18
18
  #traces = [];
19
- #syntheticEventsManagerByTrace = [];
20
19
  #nextNumberByDomain = new Map();
21
20
  #recordingsAvailable = [];
22
21
  #lastRecordingIndex = 0;
@@ -58,7 +57,6 @@ export class Model extends EventTarget {
58
57
  * // Awaiting the parse method() to block until parsing complete
59
58
  * await this.traceModel.parse(events);
60
59
  * const data = this.traceModel.parsedTrace(0)
61
- *
62
60
  * @example
63
61
  * // Using an event listener to be notified when tracing is complete.
64
62
  * this.traceModel.addEventListener(Trace.ModelUpdateEvent.eventName, (event) => {
@@ -86,22 +84,34 @@ export class Model extends EventTarget {
86
84
  metadata,
87
85
  parsedTrace: null,
88
86
  traceInsights: null,
87
+ syntheticEventsManager: Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(traceEvents),
89
88
  };
90
89
  try {
91
90
  // Wait for all outstanding promises before finishing the async execution,
92
91
  // but perform all tasks in parallel.
93
- const syntheticEventsManager = Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(traceEvents);
94
- await this.#processor.parse(traceEvents, {
92
+ const parseConfig = {
95
93
  isFreshRecording,
96
94
  isCPUProfile,
97
95
  metadata,
98
96
  resolveSourceMap: config?.resolveSourceMap,
99
- });
97
+ };
98
+ // if (window.location.href.includes('devtools/bundled') || window.location.search.includes('debugFrontend')) {
99
+ // // Someone is debugging DevTools, enable the logger.
100
+ // const times: Record<string, number> = {};
101
+ // parseConfig.logger = {
102
+ // start(id) {
103
+ // times[id] = performance.now();
104
+ // },
105
+ // end(id) {
106
+ // performance.measure(id, {start: times[id]});
107
+ // },
108
+ // };
109
+ // }
110
+ await this.#processor.parse(traceEvents, parseConfig);
100
111
  this.#storeParsedFileData(file, this.#processor.parsedTrace, this.#processor.insights);
101
112
  // We only push the file onto this.#traces here once we know it's valid
102
113
  // and there's been no errors in the parsing.
103
114
  this.#traces.push(file);
104
- this.#syntheticEventsManagerByTrace.push(syntheticEventsManager);
105
115
  }
106
116
  catch (e) {
107
117
  throw e;
@@ -154,7 +164,7 @@ export class Model extends EventTarget {
154
164
  return this.#traces.at(index)?.traceEvents ?? null;
155
165
  }
156
166
  syntheticTraceEventsManager(index = this.#traces.length - 1) {
157
- return this.#syntheticEventsManagerByTrace.at(index) ?? null;
167
+ return this.#traces.at(index)?.syntheticEventsManager ?? null;
158
168
  }
159
169
  size() {
160
170
  return this.#traces.length;
@@ -1 +1 @@
1
- {"version":3,"file":"ModelImpl.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/ModelImpl.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../core/platform/platform.js';\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport type * as Insights from './insights/insights.js';\nimport {TraceParseProgressEvent, TraceProcessor} from './Processor.js';\nimport * as Types from './types/types.js';\n\n// Note: this model is implemented in a way that can support multiple trace\n// processors. Currently there is only one implemented, but you will see\n// references to \"processors\" plural because it can easily be extended in the future.\n\nexport interface ParseConfig {\n metadata?: Types.File.MetaData;\n isFreshRecording?: boolean;\n resolveSourceMap?: Types.Configuration.ParseOptions['resolveSourceMap'];\n}\n\n/**\n * The Model is responsible for parsing arrays of raw trace events and storing the\n * resulting data. It can store multiple traces at once, and can return the data for\n * any of them.\n *\n * Most uses of this class should be through `createWithAllHandlers`, but\n * `createWithSubsetOfHandlers` can be used to run just some handlers.\n **/\nexport class Model extends EventTarget {\n readonly #traces: ParsedTraceFile[] = [];\n readonly #syntheticEventsManagerByTrace: Helpers.SyntheticEvents.SyntheticEventsManager[] = [];\n readonly #nextNumberByDomain = new Map<string, number>();\n\n readonly #recordingsAvailable: string[] = [];\n #lastRecordingIndex = 0;\n #processor: TraceProcessor;\n #config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\n static createWithAllHandlers(config?: Types.Configuration.Configuration): Model {\n return new Model(Handlers.ModelHandlers, config);\n }\n\n /**\n * Runs only the provided handlers.\n *\n * Callers must ensure they are providing all dependant handlers (although Meta is included automatically),\n * and must know that the result of `.parsedTrace` will be limited to the handlers provided, even though\n * the type won't reflect that.\n */\n static createWithSubsetOfHandlers(\n traceHandlers: Partial<Handlers.Types.Handlers>, config?: Types.Configuration.Configuration): Model {\n return new Model(traceHandlers as Handlers.Types.Handlers, config);\n }\n\n constructor(handlers: Handlers.Types.Handlers, config?: Types.Configuration.Configuration) {\n super();\n if (config) {\n this.#config = config;\n }\n this.#processor = new TraceProcessor(handlers, this.#config);\n }\n\n /**\n * Parses an array of trace events into a structured object containing all the\n * information parsed by the trace handlers.\n * You can `await` this function to pause execution until parsing is complete,\n * or instead rely on the `ModuleUpdateEvent` that is dispatched when the\n * parsing is finished.\n *\n * Once parsed, you then have to call the `parsedTrace` method, providing an\n * index of the trace you want to have the data for. This is because any model\n * can store a number of traces. Each trace is given an index, which starts at 0\n * and increments by one as a new trace is parsed.\n *\n * @example\n * // Awaiting the parse method() to block until parsing complete\n * await this.traceModel.parse(events);\n * const data = this.traceModel.parsedTrace(0)\n *\n * @example\n * // Using an event listener to be notified when tracing is complete.\n * this.traceModel.addEventListener(Trace.ModelUpdateEvent.eventName, (event) => {\n * if(event.data.data === 'done') {\n * // trace complete\n * const data = this.traceModel.parsedTrace(0);\n * }\n * });\n * void this.traceModel.parse(events);\n **/\n async parse(traceEvents: readonly Types.Events.Event[], config?: ParseConfig): Promise<void> {\n const metadata = config?.metadata || {};\n const isFreshRecording = config?.isFreshRecording || false;\n const isCPUProfile = metadata?.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;\n // During parsing, periodically update any listeners on each processors'\n // progress (if they have any updates).\n const onTraceUpdate = (event: Event): void => {\n const {data} = event as TraceParseProgressEvent;\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.PROGRESS_UPDATE, data}));\n };\n\n this.#processor.addEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n\n // Create a parsed trace file. It will be populated with data from the processor.\n const file: ParsedTraceFile = {\n traceEvents,\n metadata,\n parsedTrace: null,\n traceInsights: null,\n };\n\n try {\n // Wait for all outstanding promises before finishing the async execution,\n // but perform all tasks in parallel.\n const syntheticEventsManager = Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(traceEvents);\n await this.#processor.parse(traceEvents, {\n isFreshRecording,\n isCPUProfile,\n metadata,\n resolveSourceMap: config?.resolveSourceMap,\n });\n this.#storeParsedFileData(file, this.#processor.parsedTrace, this.#processor.insights);\n // We only push the file onto this.#traces here once we know it's valid\n // and there's been no errors in the parsing.\n this.#traces.push(file);\n this.#syntheticEventsManagerByTrace.push(syntheticEventsManager);\n } catch (e) {\n throw e;\n } finally {\n // All processors have finished parsing, no more updates are expected.\n this.#processor.removeEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n // Finally, update any listeners that all processors are 'done'.\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.COMPLETE, data: 'done'}));\n }\n }\n\n #storeParsedFileData(\n file: ParsedTraceFile, data: Handlers.Types.ParsedTrace|null,\n insights: Insights.Types.TraceInsightSets|null): void {\n file.parsedTrace = data;\n file.traceInsights = insights;\n this.#lastRecordingIndex++;\n let recordingName = `Trace ${this.#lastRecordingIndex}`;\n let origin: string|null = null;\n if (file.parsedTrace) {\n origin = Helpers.Trace.extractOriginFromTrace(file.parsedTrace.Meta.mainFrameURL);\n if (origin) {\n const nextSequenceForDomain = Platform.MapUtilities.getWithDefault(this.#nextNumberByDomain, origin, () => 1);\n recordingName = `${origin} (${nextSequenceForDomain})`;\n this.#nextNumberByDomain.set(origin, nextSequenceForDomain + 1);\n }\n }\n this.#recordingsAvailable.push(recordingName);\n }\n\n lastTraceIndex(): number {\n return this.size() - 1;\n }\n\n /**\n * Returns the parsed trace data indexed by the order in which it was stored.\n * If no index is given, the last stored parsed data is returned.\n */\n parsedTrace(index: number = this.#traces.length - 1): Handlers.Types.ParsedTrace|null {\n return this.#traces.at(index)?.parsedTrace ?? null;\n }\n\n traceInsights(index: number = this.#traces.length - 1): Insights.Types.TraceInsightSets|null {\n return this.#traces.at(index)?.traceInsights ?? null;\n }\n\n metadata(index: number = this.#traces.length - 1): Types.File.MetaData|null {\n return this.#traces.at(index)?.metadata ?? null;\n }\n\n overrideModifications(index: number, newModifications: Types.File.Modifications): void {\n if (this.#traces[index]) {\n this.#traces[index].metadata.modifications = newModifications;\n }\n }\n\n rawTraceEvents(index: number = this.#traces.length - 1): readonly Types.Events.Event[]|null {\n return this.#traces.at(index)?.traceEvents ?? null;\n }\n\n syntheticTraceEventsManager(index: number = this.#traces.length - 1): Helpers.SyntheticEvents.SyntheticEventsManager\n |null {\n return this.#syntheticEventsManagerByTrace.at(index) ?? null;\n }\n\n size(): number {\n return this.#traces.length;\n }\n\n deleteTraceByIndex(recordingIndex: number): void {\n this.#traces.splice(recordingIndex, 1);\n this.#recordingsAvailable.splice(recordingIndex, 1);\n }\n\n getRecordingsAvailable(): string[] {\n return this.#recordingsAvailable;\n }\n\n resetProcessor(): void {\n this.#processor.reset();\n }\n}\n\n/**\n * This parsed trace file is used by the Model. It keeps multiple instances\n * of these so that the user can swap between them. The key is that it is\n * essentially the TraceFile plus whatever the model has parsed from it.\n */\nexport type ParsedTraceFile = Types.File.TraceFile&{\n parsedTrace: Handlers.Types.ParsedTrace | null,\n traceInsights: Insights.Types.TraceInsightSets | null,\n};\n\nexport const enum ModelUpdateType {\n COMPLETE = 'COMPLETE',\n PROGRESS_UPDATE = 'PROGRESS_UPDATE',\n}\n\nexport type ModelUpdateEventData = ModelUpdateEventComplete|ModelUpdateEventProgress;\n\nexport interface ModelUpdateEventComplete {\n type: ModelUpdateType.COMPLETE;\n data: 'done';\n}\nexport interface ModelUpdateEventProgress {\n type: ModelUpdateType.PROGRESS_UPDATE;\n data: TraceParseEventProgressData;\n}\n\nexport interface TraceParseEventProgressData {\n percent: number;\n}\n\nexport class ModelUpdateEvent extends Event {\n static readonly eventName = 'modelupdate';\n constructor(public data: ModelUpdateEventData) {\n super(ModelUpdateEvent.eventName);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [ModelUpdateEvent.eventName]: ModelUpdateEvent;\n }\n}\n\nexport function isModelUpdateDataComplete(eventData: ModelUpdateEventData): eventData is ModelUpdateEventComplete {\n return eventData.type === ModelUpdateType.COMPLETE;\n}\n"]}
1
+ {"version":3,"file":"ModelImpl.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/ModelImpl.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../core/platform/platform.js';\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport type * as Insights from './insights/insights.js';\nimport {TraceParseProgressEvent, TraceProcessor} from './Processor.js';\nimport * as Types from './types/types.js';\n\n// Note: this model is implemented in a way that can support multiple trace\n// processors. Currently there is only one implemented, but you will see\n// references to \"processors\" plural because it can easily be extended in the future.\n\nexport interface ParseConfig {\n metadata?: Types.File.MetaData;\n isFreshRecording?: boolean;\n resolveSourceMap?: Types.Configuration.ParseOptions['resolveSourceMap'];\n}\n\n/**\n * The Model is responsible for parsing arrays of raw trace events and storing the\n * resulting data. It can store multiple traces at once, and can return the data for\n * any of them.\n *\n * Most uses of this class should be through `createWithAllHandlers`, but\n * `createWithSubsetOfHandlers` can be used to run just some handlers.\n **/\nexport class Model extends EventTarget {\n readonly #traces: ParsedTraceFile[] = [];\n readonly #nextNumberByDomain = new Map<string, number>();\n\n readonly #recordingsAvailable: string[] = [];\n #lastRecordingIndex = 0;\n #processor: TraceProcessor;\n #config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\n static createWithAllHandlers(config?: Types.Configuration.Configuration): Model {\n return new Model(Handlers.ModelHandlers, config);\n }\n\n /**\n * Runs only the provided handlers.\n *\n * Callers must ensure they are providing all dependant handlers (although Meta is included automatically),\n * and must know that the result of `.parsedTrace` will be limited to the handlers provided, even though\n * the type won't reflect that.\n */\n static createWithSubsetOfHandlers(\n traceHandlers: Partial<Handlers.Types.Handlers>, config?: Types.Configuration.Configuration): Model {\n return new Model(traceHandlers as Handlers.Types.Handlers, config);\n }\n\n constructor(handlers: Handlers.Types.Handlers, config?: Types.Configuration.Configuration) {\n super();\n if (config) {\n this.#config = config;\n }\n this.#processor = new TraceProcessor(handlers, this.#config);\n }\n\n /**\n * Parses an array of trace events into a structured object containing all the\n * information parsed by the trace handlers.\n * You can `await` this function to pause execution until parsing is complete,\n * or instead rely on the `ModuleUpdateEvent` that is dispatched when the\n * parsing is finished.\n *\n * Once parsed, you then have to call the `parsedTrace` method, providing an\n * index of the trace you want to have the data for. This is because any model\n * can store a number of traces. Each trace is given an index, which starts at 0\n * and increments by one as a new trace is parsed.\n *\n * @example\n * // Awaiting the parse method() to block until parsing complete\n * await this.traceModel.parse(events);\n * const data = this.traceModel.parsedTrace(0)\n * @example\n * // Using an event listener to be notified when tracing is complete.\n * this.traceModel.addEventListener(Trace.ModelUpdateEvent.eventName, (event) => {\n * if(event.data.data === 'done') {\n * // trace complete\n * const data = this.traceModel.parsedTrace(0);\n * }\n * });\n * void this.traceModel.parse(events);\n **/\n async parse(traceEvents: readonly Types.Events.Event[], config?: ParseConfig): Promise<void> {\n const metadata = config?.metadata || {};\n const isFreshRecording = config?.isFreshRecording || false;\n const isCPUProfile = metadata?.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;\n // During parsing, periodically update any listeners on each processors'\n // progress (if they have any updates).\n const onTraceUpdate = (event: Event): void => {\n const {data} = event as TraceParseProgressEvent;\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.PROGRESS_UPDATE, data}));\n };\n\n this.#processor.addEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n\n // Create a parsed trace file. It will be populated with data from the processor.\n const file: ParsedTraceFile = {\n traceEvents,\n metadata,\n parsedTrace: null,\n traceInsights: null,\n syntheticEventsManager: Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(traceEvents),\n };\n\n try {\n // Wait for all outstanding promises before finishing the async execution,\n // but perform all tasks in parallel.\n const parseConfig: Types.Configuration.ParseOptions = {\n isFreshRecording,\n isCPUProfile,\n metadata,\n resolveSourceMap: config?.resolveSourceMap,\n };\n // if (window.location.href.includes('devtools/bundled') || window.location.search.includes('debugFrontend')) {\n // // Someone is debugging DevTools, enable the logger.\n // const times: Record<string, number> = {};\n // parseConfig.logger = {\n // start(id) {\n // times[id] = performance.now();\n // },\n // end(id) {\n // performance.measure(id, {start: times[id]});\n // },\n // };\n // }\n await this.#processor.parse(traceEvents, parseConfig);\n this.#storeParsedFileData(file, this.#processor.parsedTrace, this.#processor.insights);\n // We only push the file onto this.#traces here once we know it's valid\n // and there's been no errors in the parsing.\n this.#traces.push(file);\n } catch (e) {\n throw e;\n } finally {\n // All processors have finished parsing, no more updates are expected.\n this.#processor.removeEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n // Finally, update any listeners that all processors are 'done'.\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.COMPLETE, data: 'done'}));\n }\n }\n\n #storeParsedFileData(\n file: ParsedTraceFile, data: Handlers.Types.ParsedTrace|null,\n insights: Insights.Types.TraceInsightSets|null): void {\n file.parsedTrace = data;\n file.traceInsights = insights;\n this.#lastRecordingIndex++;\n let recordingName = `Trace ${this.#lastRecordingIndex}`;\n let origin: string|null = null;\n if (file.parsedTrace) {\n origin = Helpers.Trace.extractOriginFromTrace(file.parsedTrace.Meta.mainFrameURL);\n if (origin) {\n const nextSequenceForDomain = Platform.MapUtilities.getWithDefault(this.#nextNumberByDomain, origin, () => 1);\n recordingName = `${origin} (${nextSequenceForDomain})`;\n this.#nextNumberByDomain.set(origin, nextSequenceForDomain + 1);\n }\n }\n this.#recordingsAvailable.push(recordingName);\n }\n\n lastTraceIndex(): number {\n return this.size() - 1;\n }\n\n /**\n * Returns the parsed trace data indexed by the order in which it was stored.\n * If no index is given, the last stored parsed data is returned.\n */\n parsedTrace(index: number = this.#traces.length - 1): Handlers.Types.ParsedTrace|null {\n return this.#traces.at(index)?.parsedTrace ?? null;\n }\n\n traceInsights(index: number = this.#traces.length - 1): Insights.Types.TraceInsightSets|null {\n return this.#traces.at(index)?.traceInsights ?? null;\n }\n\n metadata(index: number = this.#traces.length - 1): Types.File.MetaData|null {\n return this.#traces.at(index)?.metadata ?? null;\n }\n\n overrideModifications(index: number, newModifications: Types.File.Modifications): void {\n if (this.#traces[index]) {\n this.#traces[index].metadata.modifications = newModifications;\n }\n }\n\n rawTraceEvents(index: number = this.#traces.length - 1): readonly Types.Events.Event[]|null {\n return this.#traces.at(index)?.traceEvents ?? null;\n }\n\n syntheticTraceEventsManager(index: number = this.#traces.length - 1): Helpers.SyntheticEvents.SyntheticEventsManager\n |null {\n return this.#traces.at(index)?.syntheticEventsManager ?? null;\n }\n\n size(): number {\n return this.#traces.length;\n }\n\n deleteTraceByIndex(recordingIndex: number): void {\n this.#traces.splice(recordingIndex, 1);\n this.#recordingsAvailable.splice(recordingIndex, 1);\n }\n\n getRecordingsAvailable(): string[] {\n return this.#recordingsAvailable;\n }\n\n resetProcessor(): void {\n this.#processor.reset();\n }\n}\n\n/**\n * This parsed trace file is used by the Model. It keeps multiple instances\n * of these so that the user can swap between them. The key is that it is\n * essentially the TraceFile plus whatever the model has parsed from it.\n */\nexport type ParsedTraceFile = Types.File.TraceFile&{\n parsedTrace: Handlers.Types.ParsedTrace | null,\n traceInsights: Insights.Types.TraceInsightSets | null,\n syntheticEventsManager: Helpers.SyntheticEvents.SyntheticEventsManager,\n};\n\nexport const enum ModelUpdateType {\n COMPLETE = 'COMPLETE',\n PROGRESS_UPDATE = 'PROGRESS_UPDATE',\n}\n\nexport type ModelUpdateEventData = ModelUpdateEventComplete|ModelUpdateEventProgress;\n\nexport interface ModelUpdateEventComplete {\n type: ModelUpdateType.COMPLETE;\n data: 'done';\n}\nexport interface ModelUpdateEventProgress {\n type: ModelUpdateType.PROGRESS_UPDATE;\n data: TraceParseEventProgressData;\n}\n\nexport interface TraceParseEventProgressData {\n percent: number;\n}\n\nexport class ModelUpdateEvent extends Event {\n static readonly eventName = 'modelupdate';\n constructor(public data: ModelUpdateEventData) {\n super(ModelUpdateEvent.eventName);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [ModelUpdateEvent.eventName]: ModelUpdateEvent;\n }\n}\n\nexport function isModelUpdateDataComplete(eventData: ModelUpdateEventData): eventData is ModelUpdateEventComplete {\n return eventData.type === ModelUpdateType.COMPLETE;\n}\n"]}
@@ -170,6 +170,10 @@ export class TraceProcessor extends EventTarget {
170
170
  }
171
171
  options.logger?.end('parse:handleEvent');
172
172
  // Finalize.
173
+ const finalizeOptions = {
174
+ ...options,
175
+ allTraceEvents: traceEvents,
176
+ };
173
177
  for (let i = 0; i < sortedHandlers.length; i++) {
174
178
  const [name, handler] = sortedHandlers[i];
175
179
  if (handler.finalize) {
@@ -177,7 +181,7 @@ export class TraceProcessor extends EventTarget {
177
181
  // Yield to the UI because finalize() calls can be expensive
178
182
  // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`
179
183
  await new Promise(resolve => setTimeout(resolve, 0));
180
- await handler.finalize(options);
184
+ await handler.finalize(finalizeOptions);
181
185
  options.logger?.end(`parse:${name}:finalize`);
182
186
  }
183
187
  const percent = calculateProgress(i / sortedHandlers.length, 0.8 /* ProgressPhase.FINALIZE */);
@@ -310,13 +314,13 @@ export class TraceProcessor extends EventTarget {
310
314
  const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);
311
315
  // Normalize the estimated savings to a single number, weighted by its relative impact
312
316
  // to the page experience based on the same scoring curve that Lighthouse uses.
313
- const observedLcpMicro = Insights.Common.getLCP(this.#insights, insightSet.id)?.value;
317
+ const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;
314
318
  const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);
315
- const observedCls = Insights.Common.getCLS(this.#insights, insightSet.id).value;
319
+ const observedCls = Insights.Common.getCLS(insightSet).value;
316
320
  // INP is special - if users did not interact with the page, we'll have no INP, but we should still
317
321
  // be able to prioritize insights based on this metric. When we observe no interaction, instead use
318
322
  // a default value for the baseline INP.
319
- const observedInpMicro = Insights.Common.getINP(this.#insights, insightSet.id)?.value;
323
+ const observedInpMicro = Insights.Common.getINP(insightSet)?.value;
320
324
  const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);
321
325
  const observedLcpScore = observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;
322
326
  const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);
@@ -379,25 +383,29 @@ export class TraceProcessor extends EventTarget {
379
383
  id = Types.Events.NO_NAVIGATION;
380
384
  urlString = parsedTrace.Meta.finalDisplayUrlByNavigationId.get('') ?? parsedTrace.Meta.mainFrameURL;
381
385
  }
382
- const model = {};
386
+ const insightSetModel = {};
383
387
  for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {
384
- let insightResult;
388
+ let model;
385
389
  try {
386
390
  options.logger?.start(`insights:${name}`);
387
- insightResult = insight.generateInsight(parsedTrace, context);
388
- insightResult.frameId = context.frameId;
391
+ model = insight.generateInsight(parsedTrace, context);
392
+ model.frameId = context.frameId;
389
393
  const navId = context.navigation?.args.data?.navigationId;
390
394
  if (navId) {
391
- insightResult.navigationId = navId;
395
+ model.navigationId = navId;
392
396
  }
397
+ model.createOverlays = () => {
398
+ // @ts-expect-error: model is a union of all possible insight model types.
399
+ return insight.createOverlays(model);
400
+ };
393
401
  }
394
402
  catch (err) {
395
- insightResult = err;
403
+ model = err;
396
404
  }
397
405
  finally {
398
406
  options.logger?.end(`insights:${name}`);
399
407
  }
400
- Object.assign(model, { [name]: insightResult });
408
+ Object.assign(insightSetModel, { [name]: model });
401
409
  }
402
410
  // We may choose to exclude the insightSet if it's trivial. Trivial means:
403
411
  // 1. There's no navigation (it's an initial trace period)
@@ -407,10 +415,12 @@ export class TraceProcessor extends EventTarget {
407
415
  // Generally, these cases are the short time ranges before a page reload starts.
408
416
  const isNavigation = id === Types.Events.NO_NAVIGATION;
409
417
  const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));
410
- const everyInsightPasses = Object.values(model).filter(model => !(model instanceof Error)).every(model => model.state === 'pass');
411
- const noLcp = !model.LCPBreakdown.lcpEvent;
412
- const noInp = !model.INPBreakdown.longestInteractionEvent;
413
- const noLayoutShifts = model.CLSCulprits.shifts?.size === 0;
418
+ const everyInsightPasses = Object.values(insightSetModel)
419
+ .filter(model => !(model instanceof Error))
420
+ .every(model => model.state === 'pass');
421
+ const noLcp = !insightSetModel.LCPBreakdown.lcpEvent;
422
+ const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;
423
+ const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;
414
424
  const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&
415
425
  noInp && noLayoutShifts;
416
426
  if (shouldExclude) {
@@ -431,7 +441,7 @@ export class TraceProcessor extends EventTarget {
431
441
  navigation,
432
442
  frameId: context.frameId,
433
443
  bounds: context.bounds,
434
- model,
444
+ model: insightSetModel,
435
445
  };
436
446
  if (!this.#insights) {
437
447
  this.#insights = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AAEtE,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAS1C,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAE7B;IADnB,MAAM,CAAU,SAAS,GAAG,oBAAoB,CAAC;IACjD,YAAmB,IAAuC,EAAE,OAAkB,EAAC,OAAO,EAAE,IAAI,EAAC;QAC3F,KAAK,CAAC,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAD9B,SAAI,GAAJ,IAAI,CAAmC;IAE1D,CAAC;;AAeH,SAAS,iBAAiB,CAAC,KAAa,EAAE,KAAoB;IAC5D,wCAAwC;IACxC,IAAI,KAAK,qCAA2B,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,GAAG,CAAC,uEAAmD,CAAC,CAAC,uCAA6B,CAAC;IACtG,CAAC;IACD,OAAO,KAAK,GAAG,KAAK,CAAC;AACvB,CAAC;AAQD,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,GAAoC,IAAI,CAAC;IAC9C,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;;OAEG;IACH,MAAM,CAAC,iBAAiB;QACtB,OAAO,EAAC,GAAG,QAAQ,CAAC,MAAM,EAAC,CAAC;IAC9B,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,GAAG,IAAI,GAAG,EAA8B,CAAC;QAClE,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACtE,mBAAmB,CAAC,GAAG,CAAC,WAAyC,CAAC,CAAC;YACnE,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,WAA0C,EAAE,OAAyC;QAC/F,IAAI,IAAI,CAAC,OAAO,6BAAgB,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qEAAqE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvG,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,iCAAiB,CAAC;YAC9B,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC/B,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7B,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAE,iDAAiD;gBAC3F,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;gBAClC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;gBACxD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAClC,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;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CAAC,WAA0C,EAAE,OAAyC;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,OAAO,EAAE,CAAC,CAAC;QAExE,SAAS;QACT,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAE3C,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,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,uCAA6B,CAAC;gBACtF,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,EAAC,CAAC,CAAC,CAAC;gBAC3D,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,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBACtC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAEzC,YAAY;QACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC;gBAChD,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,CAAC,OAAO,CAAC,CAAC;gBAChC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,mCAAyB,CAAC;YACrF,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,EAAC,CAAC,CAAC,CAAC;QAC7D,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,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,EAAE,CAAC;QACvB,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,WAAW,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QAEnC,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,6BAAqB,EAAC,CAAC,CAAC,CAAC;QAEhF,IAAI,CAAC,KAAK,GAAG,WAAyC,CAAC;IACzD,CAAC;IAED,IAAI,WAAW;QACb,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,WAAuC,EAAE,WAA0C,EAAE,OAAe,EACpG,YAAoB,EAAE,OAAyC;QACjE,+BAA+B;QAC/B,IAAI,CAAC,WAAW,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;YACzF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC/C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,oCAAoC,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,aAAa,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC,CAAC;QAC5F,IAAI,CAAC,SAAS,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,iCAAiC,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,aAAa,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAClH,MAAM,kBAAkB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC;QAExF,qEAAqE;QACrE,4GAA4G;QAC5G,MAAM,KAAK,GAAwB;YACjC,WAAW,EAAE,kBAA2D;SACzE,CAAC;QAEF,MAAM,QAAQ,GAAG,sBAAsB,CAAC,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QACtG,MAAM,KAAK,GAAG,sBAAsB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/E,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,yBAAyB,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QAEjH,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAsC;YACzD,+FAA+F;YAC/F,uDAAuD;YACvD,eAAe;YACf,gBAAgB,EAAE,UAAU;YAC5B,GAAG,OAAO,CAAC,eAAe;SAC3B,CAAC;QACF,MAAM,SAAS,GACX,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QAElE,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,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,UAAqC,EAAE,QAAkC;QACtF,2GAA2G;QAC3G,iFAAiF;QACjF,MAAM,aAAa,GAAqD;YACtE,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,IAAI;YACjB,cAAc,EAAE,IAAI;YACpB,qBAAqB,EAAE,IAAI;YAC3B,aAAa,EAAE,IAAI;YACnB,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,IAAI;YAClB,oBAAoB,EAAE,IAAI;YAC1B,eAAe,EAAE,IAAI;YACrB,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,gBAAgB,EAAE,IAAI;SACvB,CAAC;QAEF,oHAAoH;QACpH,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,gCAAgC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEvF,sFAAsF;QACtF,+EAA+E;QAC/E,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;QACtF,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7G,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QAEhF,mGAAmG;QACnG,mGAAmG;QACnG,wCAAwC;QACxC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC;QACtF,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE/G,MAAM,gBAAgB,GAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChG,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC7E,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAE7E,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAE1C,MAAM,cAAc,GAChB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAuB,CAAC,CAAC,CAAC,SAAS,CAAC;YACjG,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAuB,CAAC;YAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;YAEtD,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACzF,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACzD,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACzD,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YAED,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,kCAAkC;QAClC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,EAAE,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC,CAAC;YACZ,CAAC;YACD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC;YACX,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpG,MAAM,QAAQ,GAAG,EAAkC,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,WAAwD,EAAE,CAAC;YAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpC,oFAAoF;YACpF,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;QACD,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED,kBAAkB,CACd,WAAuC,EAAE,OAAyC,EAClF,OAAyC;QAC3C,IAAI,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC;QAC9B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;YAC1B,SAAS;gBACL,WAAW,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;YAC9G,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;YAChC,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;QACtG,CAAC;QAED,MAAM,KAAK,GAAG,EAAwC,CAAC;QAEvD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;YACjF,IAAI,aAAa,CAAC;YAClB,IAAI,CAAC;gBACH,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;gBAC1C,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAC9D,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;gBACxC,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;gBAC1D,IAAI,KAAK,EAAE,CAAC;oBACV,aAAa,CAAC,YAAY,GAAG,KAAK,CAAC;gBACrC,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,aAAa,GAAG,GAAG,CAAC;YACtB,CAAC;oBAAS,CAAC;gBACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YAC1C,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAC,CAAC,CAAC;QAChD,CAAC;QAED,0EAA0E;QAC1E,4DAA4D;QAC5D,8BAA8B;QAC9B,uEAAuE;QACvE,6EAA6E;QAC7E,gFAAgF;QAChF,MAAM,YAAY,GAAG,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACvD,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,MAAM,kBAAkB,GACpB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;QAE3G,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,uBAAuB,CAAC;QAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC;QAC5D,MAAM,aAAa,GAAG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,gBAAgB,IAAI,kBAAkB,IAAI,KAAK;YACxG,KAAK,IAAI,cAAc,CAAC;QAC5B,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC;QACR,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,2FAA2F;YAC3F,0BAA0B;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAA8B;YAC5C,EAAE;YACF,GAAG;YACH,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK;SACN,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,gBAAgB,CACZ,WAAuC,EAAE,WAA0C,EACnF,OAAyC;QAC3C,6DAA6D;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QAE3B,kGAAkG;QAClG,uJAAuJ;QACvJ,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAC5D,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAE/E,IAAI,CAAC,qCAAqC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAE9E,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,CAAC;YAC1B,yFAAyF;YACzF,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;YAC1G,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACpE,IAAI,CAAC,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED;;OAEG;IACH,qCAAqC,CACjC,WAAuC,EAAE,WAAoD,EAC7F,OAAyC;QAC3C,4HAA4H;QAC5H,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACjG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;QAEjC,MAAM,OAAO,GAAqC;YAChD,MAAM;YACN,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;YACrC,iFAAiF;SAClF,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,6BAA6B,CACzB,UAAwC,EAAE,MAAqC,EAC/E,WAAuC,EAAE,WAA0C,EACnF,OAAyC;QAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,+CAA+C;QAC/C,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAsB,CAAC;QAElE,qFAAqF;QACrF,2GAA2G;QAC3G,4EAA4E;QAC5E,IAAI,OAAgD,CAAC;QACrD,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACvD,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QACjG,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,mCAAmC;YACnC,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,CAAC;YACnB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,+BAA+B,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAqC;YAChD,MAAM;YACN,OAAO;YACP,UAAU;YACV,YAAY;YACZ,OAAO;SACR,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,aAAkF;IAE7G,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsD,CAAC;IAChF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA8B,CAAC;IACtD,MAAM,YAAY,GAAG,CAAC,WAAuC,EAAQ,EAAE;QACrE,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,WAAyC,CAAC,CAAC;IAC1D,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.\n\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 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 /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\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 = new Set<Handlers.Types.HandlerName>();\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: Types.Configuration.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\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\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).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\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 const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}: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(options);\n options.logger?.end(`parse:${name}: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 options.logger?.start('parse:clone');\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 options.logger?.end('parse:clone');\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, options: Types.Configuration.ParseOptions): 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 if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\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 ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\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 {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(this.#insights, insightSet.id)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(this.#insights, insightSet.id).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(this.#insights, insightSet.id)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, model] of Object.entries(insightSet.model)) {\n const lcp = model.metricSavings?.LCP ?? 0;\n const inp = model.metricSavings?.INP ?? 0;\n const cls = model.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(\n parsedTrace: Handlers.Types.ParsedTrace, context: Insights.Types.InsightSetContext,\n options: Types.Configuration.ParseOptions): void {\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString =\n parsedTrace.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? parsedTrace.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = parsedTrace.Meta.finalDisplayUrlByNavigationId.get('') ?? parsedTrace.Meta.mainFrameURL;\n }\n\n const model = {} as Insights.Types.InsightSet['model'];\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n let insightResult;\n try {\n options.logger?.start(`insights:${name}`);\n insightResult = insight.generateInsight(parsedTrace, context);\n insightResult.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n insightResult.navigationId = navId;\n }\n } catch (err) {\n insightResult = err;\n } finally {\n options.logger?.end(`insights:${name}`);\n }\n Object.assign(model, {[name]: insightResult});\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses =\n Object.values(model).filter(model => !(model instanceof Error)).every(model => model.state === 'pass');\n\n const noLcp = !model.LCPBreakdown.lcpEvent;\n const noInp = !model.INPBreakdown.longestInteractionEvent;\n const noLayoutShifts = model.CLSCulprits.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\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 insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model,\n };\n if (!this.#insights) {\n this.#insights = new Map();\n }\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = parsedTrace.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(parsedTrace, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : parsedTrace.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, parsedTrace, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n parsedTrace: Handlers.Types.ParsedTrace, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(parsedTrace.Meta.traceBounds.min, navigations[0].ts) :\n parsedTrace.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId: parsedTrace.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(parsedTrace, context, options);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro,\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\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: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(parsedTrace, traceEvents, frameId, navigationId, options);\n } catch (e) {\n // Handle Lantern errors gracefully\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);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(parsedTrace, context, options);\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 handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<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
+ {"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.\n\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 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 /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\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 = new Set<Handlers.Types.HandlerName>();\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: Types.Configuration.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\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\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).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\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 const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n const finalizeOptions: Handlers.Types.FinalizeOptions = {\n ...options,\n allTraceEvents: traceEvents,\n };\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}: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(finalizeOptions);\n options.logger?.end(`parse:${name}: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 options.logger?.start('parse:clone');\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 options.logger?.end('parse:clone');\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, options: Types.Configuration.ParseOptions): 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 if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\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 ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\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 {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(insightSet).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(insightSet)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, model] of Object.entries(insightSet.model)) {\n const lcp = model.metricSavings?.LCP ?? 0;\n const inp = model.metricSavings?.INP ?? 0;\n const cls = model.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(\n parsedTrace: Handlers.Types.ParsedTrace, context: Insights.Types.InsightSetContext,\n options: Types.Configuration.ParseOptions): void {\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString =\n parsedTrace.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? parsedTrace.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = parsedTrace.Meta.finalDisplayUrlByNavigationId.get('') ?? parsedTrace.Meta.mainFrameURL;\n }\n\n const insightSetModel = {} as Insights.Types.InsightSet['model'];\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n let model: Insights.Types.InsightModel|Error;\n try {\n options.logger?.start(`insights:${name}`);\n model = insight.generateInsight(parsedTrace, context);\n model.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n model.navigationId = navId;\n }\n model.createOverlays = () => {\n // @ts-expect-error: model is a union of all possible insight model types.\n return insight.createOverlays(model);\n };\n } catch (err) {\n model = err;\n } finally {\n options.logger?.end(`insights:${name}`);\n }\n Object.assign(insightSetModel, {[name]: model});\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses = Object.values(insightSetModel)\n .filter(model => !(model instanceof Error))\n .every(model => model.state === 'pass');\n\n const noLcp = !insightSetModel.LCPBreakdown.lcpEvent;\n const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;\n const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\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 insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model: insightSetModel,\n };\n if (!this.#insights) {\n this.#insights = new Map();\n }\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = parsedTrace.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(parsedTrace, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : parsedTrace.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, parsedTrace, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n parsedTrace: Handlers.Types.ParsedTrace, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(parsedTrace.Meta.traceBounds.min, navigations[0].ts) :\n parsedTrace.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId: parsedTrace.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(parsedTrace, context, options);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro,\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\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: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(parsedTrace, traceEvents, frameId, navigationId, options);\n } catch (e) {\n // Handle Lantern errors gracefully\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);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(parsedTrace, context, options);\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 handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<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"]}
@@ -105,7 +105,7 @@ function getBottomUpTree(mainThreadEvents, tracebounds, groupingFunction) {
105
105
  // The bottom up root node handles all the "in Tracebounds" checks we need for the insight.
106
106
  const startTime = Helpers.Timing.microToMilli(tracebounds.min);
107
107
  const endTime = Helpers.Timing.microToMilli(tracebounds.max);
108
- const node = new TraceTree.BottomUpRootNode(mainThreadEvents, {
108
+ return new TraceTree.BottomUpRootNode(mainThreadEvents, {
109
109
  textFilter: new TraceFilter.ExclusiveNameFilter([]),
110
110
  filters: [filter],
111
111
  startTime,
@@ -115,6 +115,5 @@ function getBottomUpTree(mainThreadEvents, tracebounds, groupingFunction) {
115
115
  // Ensure we group by 3P alongside eventID for correct 3P grouping.
116
116
  forceGroupIdCallback: true,
117
117
  });
118
- return node;
119
118
  }
120
119
  //# sourceMappingURL=ThirdParties.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/ThirdParties.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAmB5C;;;;GAIG;AACH,SAAS,yBAAyB,CAAC,WAAuC;IACxE,iDAAiD;IACjD,MAAM,mBAAmB,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE;SAClC,IAAI,CAAC,CAAC,CAAC,EAAE;QACR,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;QACxB,2EAA2E;QAC3E,OAAO,CAAC,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACpF,CAAC,CAAC;QACF,EAAE,OAAO,CAAC,MAAM,EAAE;SACjB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;IAExE,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,mBAAmB,CAAC,OAAO,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,qBAAqB,CACjC,WAAuC,EAAE,WAA0C;IACrF,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxG,MAAM,gBAAgB,GAAG,CAAC,KAAyB,EAAU,EAAE;QAC7D,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;IAC5B,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,eAAe,CAAC,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,yBAAyB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE/D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC1B,WAAuC,EAAE,WAA0C;IACrF,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxG,MAAM,gBAAgB,GAAG,CAAC,KAAyB,EAAU,EAAE;QAC7D,OAAO,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;IACtE,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,eAAe,CAAC,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAE5D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,yBAAyB,CAC9B,IAAgC,EAAE,WAAuC;IAC3E,MAAM,SAAS,GAAoB,EAAE,CAAC;IAEtC,iCAAiC;IACjC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YACnB,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QAED,gGAAgG;QAChG,kEAAkE;QAClE,MAAM,OAAO,GAAkB;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YACjD,MAAM;YACN,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;SACpF,CAAC;QACF,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,sBAAsB,CAC3B,IAAgC,EAAE,WAAuC;IAC3E,MAAM,SAAS,GAAiB,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC;IAEvD,sBAAsB;IACtB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAClD,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAE/D,MAAM,OAAO,GAAe;YAC1B,OAAO;YACP,GAAG;YACH,MAAM;YACN,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;SAClD,CAAC;QACF,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CACpB,gBAAsC,EAAE,WAA0C,EAClF,gBAA6D;IAC/D,2EAA2E;IAC3E,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;IACjF,MAAM,MAAM,GACR,IAAI,WAAW,CAAC,mBAAmB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;IAE7G,2FAA2F;IAC3F,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,gBAAgB,CAAC,gBAAgB,EAAE;QAC5D,UAAU,EAAE,IAAI,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,SAAS;QACT,OAAO;QACP,oBAAoB,EAAE,gBAAgB;QACtC,qBAAqB,EAAE,IAAI;QAC3B,mEAAmE;QACnE,oBAAoB,EAAE,IAAI;KAC3B,CAA+B,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport * as TraceFilter from './TraceFilter.js';\nimport * as TraceTree from './TraceTree.js';\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\ninterface BaseSummary {\n entity: Entity;\n transferSize: number;\n mainThreadTime: Types.Timing.Milli;\n}\n\nexport interface EntitySummary extends BaseSummary {\n relatedEvents: Types.Events.Event[];\n}\n\nexport interface URLSummary extends BaseSummary {\n url: string;\n request?: Types.Events.SyntheticNetworkRequest;\n}\n\n/**\n *\n * Returns Main frame main thread events.\n * These events are inline with the ones used by selectedEvents() of TimelineTreeViews\n */\nfunction collectMainThreadActivity(parsedTrace: Handlers.Types.ParsedTrace): Types.Events.Event[] {\n // TODO: Note b/402658800 could be an issue here.\n const mainFrameMainThread = parsedTrace.Renderer.processes.values()\n .find(p => {\n const url = p.url ?? '';\n // Frame url checked a la CompatibilityTracksAppenders's addThreadAppenders\n return p.isOnMainFrame && !url.startsWith('about:') && !url.startsWith('chrome:');\n })\n ?.threads.values()\n .find(t => t.name === 'CrRendererMain');\n\n if (!mainFrameMainThread) {\n return [];\n }\n\n return mainFrameMainThread.entries;\n}\n\nexport function summarizeByThirdParty(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): EntitySummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(event);\n return entity?.name ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByEntity(node, parsedTrace);\n\n return summaries;\n}\n\n/**\n * Used only by Lighthouse.\n */\nexport function summarizeByURL(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): URLSummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n return Handlers.Helpers.getNonResolvedURL(event, parsedTrace) ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByURL(node, parsedTrace);\n\n return summaries;\n}\n\nfunction summarizeBottomUpByEntity(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): EntitySummary[] {\n const summaries: EntitySummary[] = [];\n\n // Top nodes are the 3P entities.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n // Lets use the mapper events as our source of events, since we use the main thread to construct\n // the bottom up tree. The mapper will give us all related events.\n const summary: EntitySummary = {\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n entity,\n relatedEvents: parsedTrace.Renderer.entityMappings.eventsByEntity.get(entity) ?? [],\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction summarizeBottomUpByURL(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): URLSummary[] {\n const summaries: URLSummary[] = [];\n const allRequests = parsedTrace.NetworkRequests.byTime;\n\n // Top nodes are URLs.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '' || typeof node.id !== 'string') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n const url = node.id;\n const request = allRequests.find(r => r.args.data.url === url);\n\n const summary: URLSummary = {\n request,\n url,\n entity,\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction getBottomUpTree(\n mainThreadEvents: Types.Events.Event[], tracebounds: Types.Timing.TraceWindowMicro,\n groupingFunction: ((arg0: Types.Events.Event) => string)|null): TraceTree.BottomUpRootNode {\n // Use the same filtering as front_end/panels/timeline/TimelineTreeView.ts.\n const visibleEvents = Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();\n const filter =\n new TraceFilter.VisibleEventsFilter(visibleEvents.concat([Types.Events.Name.SYNTHETIC_NETWORK_REQUEST]));\n\n // The bottom up root node handles all the \"in Tracebounds\" checks we need for the insight.\n const startTime = Helpers.Timing.microToMilli(tracebounds.min);\n const endTime = Helpers.Timing.microToMilli(tracebounds.max);\n const node = new TraceTree.BottomUpRootNode(mainThreadEvents, {\n textFilter: new TraceFilter.ExclusiveNameFilter([]),\n filters: [filter],\n startTime,\n endTime,\n eventGroupIdCallback: groupingFunction,\n calculateTransferSize: true,\n // Ensure we group by 3P alongside eventID for correct 3P grouping.\n forceGroupIdCallback: true,\n }) as TraceTree.BottomUpRootNode;\n return node;\n}\n"]}
1
+ {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport * as TraceFilter from './TraceFilter.js';\nimport * as TraceTree from './TraceTree.js';\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\ninterface BaseSummary {\n entity: Entity;\n transferSize: number;\n mainThreadTime: Types.Timing.Milli;\n}\n\nexport interface EntitySummary extends BaseSummary {\n relatedEvents: Types.Events.Event[];\n}\n\nexport interface URLSummary extends BaseSummary {\n url: string;\n request?: Types.Events.SyntheticNetworkRequest;\n}\n\n/**\n *\n * Returns Main frame main thread events.\n * These events are inline with the ones used by selectedEvents() of TimelineTreeViews\n */\nfunction collectMainThreadActivity(parsedTrace: Handlers.Types.ParsedTrace): Types.Events.Event[] {\n // TODO: Note b/402658800 could be an issue here.\n const mainFrameMainThread = parsedTrace.Renderer.processes.values()\n .find(p => {\n const url = p.url ?? '';\n // Frame url checked a la CompatibilityTracksAppenders's addThreadAppenders\n return p.isOnMainFrame && !url.startsWith('about:') && !url.startsWith('chrome:');\n })\n ?.threads.values()\n .find(t => t.name === 'CrRendererMain');\n\n if (!mainFrameMainThread) {\n return [];\n }\n\n return mainFrameMainThread.entries;\n}\n\nexport function summarizeByThirdParty(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): EntitySummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(event);\n return entity?.name ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByEntity(node, parsedTrace);\n\n return summaries;\n}\n\n/**\n * Used only by Lighthouse.\n */\nexport function summarizeByURL(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): URLSummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n return Handlers.Helpers.getNonResolvedURL(event, parsedTrace) ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByURL(node, parsedTrace);\n\n return summaries;\n}\n\nfunction summarizeBottomUpByEntity(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): EntitySummary[] {\n const summaries: EntitySummary[] = [];\n\n // Top nodes are the 3P entities.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n // Lets use the mapper events as our source of events, since we use the main thread to construct\n // the bottom up tree. The mapper will give us all related events.\n const summary: EntitySummary = {\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n entity,\n relatedEvents: parsedTrace.Renderer.entityMappings.eventsByEntity.get(entity) ?? [],\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction summarizeBottomUpByURL(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): URLSummary[] {\n const summaries: URLSummary[] = [];\n const allRequests = parsedTrace.NetworkRequests.byTime;\n\n // Top nodes are URLs.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '' || typeof node.id !== 'string') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n const url = node.id;\n const request = allRequests.find(r => r.args.data.url === url);\n\n const summary: URLSummary = {\n request,\n url,\n entity,\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction getBottomUpTree(\n mainThreadEvents: Types.Events.Event[], tracebounds: Types.Timing.TraceWindowMicro,\n groupingFunction: ((arg0: Types.Events.Event) => string)|null): TraceTree.BottomUpRootNode {\n // Use the same filtering as front_end/panels/timeline/TimelineTreeView.ts.\n const visibleEvents = Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();\n const filter =\n new TraceFilter.VisibleEventsFilter(visibleEvents.concat([Types.Events.Name.SYNTHETIC_NETWORK_REQUEST]));\n\n // The bottom up root node handles all the \"in Tracebounds\" checks we need for the insight.\n const startTime = Helpers.Timing.microToMilli(tracebounds.min);\n const endTime = Helpers.Timing.microToMilli(tracebounds.max);\n return new TraceTree.BottomUpRootNode(mainThreadEvents, {\n textFilter: new TraceFilter.ExclusiveNameFilter([]),\n filters: [filter],\n startTime,\n endTime,\n eventGroupIdCallback: groupingFunction,\n calculateTransferSize: true,\n // Ensure we group by 3P alongside eventID for correct 3P grouping.\n forceGroupIdCallback: true,\n });\n}\n"]}
@@ -2,13 +2,16 @@ import type * as Protocol from '../../../generated/protocol.js';
2
2
  import * as Types from '../types/types.js';
3
3
  import type { TraceFilter } from './TraceFilter.js';
4
4
  export declare class Node {
5
+ /** ms */
5
6
  totalTime: number;
7
+ /** ms */
6
8
  selfTime: number;
7
9
  transferSize: number;
8
10
  id: string | symbol;
9
11
  /** The first trace event encountered that necessitated the creation of this tree node. */
10
12
  event: Types.Events.Event;
11
- /** All of the trace events associated with this aggregate node.
13
+ /**
14
+ * All of the trace events associated with this aggregate node.
12
15
  * Minor: In the case of Event Log (EventsTimelineTreeView), the node is not aggregate and this will only hold 1 event, the same that's in this.event
13
16
  */
14
17
  events: Types.Events.Event[];
@@ -37,7 +40,6 @@ export declare class TopDownNode extends Node {
37
40
  setHasChildren(value: boolean): void;
38
41
  children(): ChildrenCache;
39
42
  private buildChildren;
40
- getRoot(): TopDownRootNode | null;
41
43
  }
42
44
  export declare class TopDownRootNode extends TopDownNode {
43
45
  readonly filter: (e: Types.Events.Event) => boolean;
@@ -5,13 +5,16 @@ import * as Helpers from '../helpers/helpers.js';
5
5
  import { SamplesIntegrator } from '../helpers/SamplesIntegrator.js';
6
6
  import * as Types from '../types/types.js';
7
7
  export class Node {
8
+ /** ms */
8
9
  totalTime;
10
+ /** ms */
9
11
  selfTime;
10
12
  transferSize;
11
13
  id;
12
14
  /** The first trace event encountered that necessitated the creation of this tree node. */
13
15
  event;
14
- /** All of the trace events associated with this aggregate node.
16
+ /**
17
+ * All of the trace events associated with this aggregate node.
15
18
  * Minor: In the case of Event Log (EventsTimelineTreeView), the node is not aggregate and this will only hold 1 event, the same that's in this.event
16
19
  */
17
20
  events;
@@ -217,9 +220,6 @@ export class TopDownNode extends Node {
217
220
  this.childrenInternal = children;
218
221
  return children;
219
222
  }
220
- getRoot() {
221
- return this.root;
222
- }
223
223
  }
224
224
  export class TopDownRootNode extends TopDownNode {
225
225
  filter;
@@ -434,7 +434,9 @@ export class BottomUpRootNode extends Node {
434
434
  groupNodes.set(groupId, groupNode);
435
435
  }
436
436
  else {
437
- groupNode.events.push(...node.events);
437
+ for (const e of node.events) {
438
+ groupNode.events.push(e);
439
+ }
438
440
  }
439
441
  groupNode.addChild(node, node.selfTime, node.selfTime, node.transferSize);
440
442
  }