@paulirish/trace_engine 0.0.32 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +6 -10
  2. package/analyze-trace.mjs +9 -10
  3. package/core/platform/ArrayUtilities.js +1 -0
  4. package/core/platform/ArrayUtilities.js.map +1 -1
  5. package/core/platform/DevToolsPath.d.ts +1 -1
  6. package/core/platform/DevToolsPath.js.map +1 -1
  7. package/core/platform/MimeType.js +4 -2
  8. package/core/platform/MimeType.js.map +1 -1
  9. package/core/platform/NumberUtilities.js +8 -0
  10. package/core/platform/NumberUtilities.js.map +1 -1
  11. package/core/platform/ServerTiming.d.ts +31 -0
  12. package/core/platform/ServerTiming.js +212 -0
  13. package/core/platform/ServerTiming.js.map +1 -0
  14. package/core/platform/Timing.d.ts +1 -1
  15. package/core/platform/Timing.js.map +1 -1
  16. package/core/platform/TypescriptUtilities.d.ts +3 -0
  17. package/core/platform/TypescriptUtilities.js.map +1 -1
  18. package/core/platform/UIString.d.ts +1 -1
  19. package/core/platform/UIString.js.map +1 -1
  20. package/core/platform/UserVisibleError.d.ts +1 -1
  21. package/core/platform/UserVisibleError.js.map +1 -1
  22. package/core/platform/platform-tsconfig.json +1 -1
  23. package/core/platform/platform.d.ts +2 -2
  24. package/core/platform/platform.js +2 -2
  25. package/core/platform/platform.js.map +1 -1
  26. package/generated/protocol.d.ts +258 -14
  27. package/models/trace/LanternComputationData.d.ts +4 -4
  28. package/models/trace/LanternComputationData.js +22 -23
  29. package/models/trace/LanternComputationData.js.map +1 -1
  30. package/models/trace/ModelImpl.d.ts +11 -12
  31. package/models/trace/ModelImpl.js +22 -33
  32. package/models/trace/ModelImpl.js.map +1 -1
  33. package/models/trace/Processor.d.ts +21 -12
  34. package/models/trace/Processor.js +148 -67
  35. package/models/trace/Processor.js.map +1 -1
  36. package/models/trace/TracingManager.js.map +1 -1
  37. package/models/trace/extras/FetchNodes.d.ts +8 -8
  38. package/models/trace/extras/FetchNodes.js +16 -11
  39. package/models/trace/extras/FetchNodes.js.map +1 -1
  40. package/models/trace/extras/FilmStrip.d.ts +2 -2
  41. package/models/trace/extras/FilmStrip.js +8 -8
  42. package/models/trace/extras/FilmStrip.js.map +1 -1
  43. package/models/trace/extras/MainThreadActivity.d.ts +1 -1
  44. package/models/trace/extras/MainThreadActivity.js +1 -1
  45. package/models/trace/extras/MainThreadActivity.js.map +1 -1
  46. package/models/trace/extras/Metadata.js +2 -2
  47. package/models/trace/extras/Metadata.js.map +1 -1
  48. package/models/trace/extras/URLForEntry.d.ts +9 -1
  49. package/models/trace/extras/URLForEntry.js +18 -10
  50. package/models/trace/extras/URLForEntry.js.map +1 -1
  51. package/models/trace/extras/extras.js +1 -1
  52. package/models/trace/handlers/AnimationHandler.d.ts +2 -2
  53. package/models/trace/handlers/AnimationHandler.js +1 -1
  54. package/models/trace/handlers/AnimationHandler.js.map +1 -1
  55. package/models/trace/handlers/AuctionWorkletsHandler.d.ts +2 -2
  56. package/models/trace/handlers/AuctionWorkletsHandler.js +11 -11
  57. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
  58. package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +6 -6
  59. package/models/trace/handlers/ExtensionTraceDataHandler.js +12 -8
  60. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  61. package/models/trace/handlers/FramesHandler.d.ts +24 -19
  62. package/models/trace/handlers/FramesHandler.js +46 -25
  63. package/models/trace/handlers/FramesHandler.js.map +1 -1
  64. package/models/trace/handlers/GPUHandler.d.ts +4 -4
  65. package/models/trace/handlers/GPUHandler.js +3 -3
  66. package/models/trace/handlers/GPUHandler.js.map +1 -1
  67. package/models/trace/handlers/ImagePaintingHandler.d.ts +3 -3
  68. package/models/trace/handlers/ImagePaintingHandler.js +6 -8
  69. package/models/trace/handlers/ImagePaintingHandler.js.map +1 -1
  70. package/models/trace/handlers/InitiatorsHandler.d.ts +3 -3
  71. package/models/trace/handlers/InitiatorsHandler.js +14 -14
  72. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  73. package/models/trace/handlers/InvalidationsHandler.d.ts +4 -2
  74. package/models/trace/handlers/InvalidationsHandler.js +29 -11
  75. package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
  76. package/models/trace/handlers/LargestImagePaintHandler.d.ts +2 -2
  77. package/models/trace/handlers/LargestImagePaintHandler.js +1 -1
  78. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
  79. package/models/trace/handlers/LargestTextPaintHandler.d.ts +2 -2
  80. package/models/trace/handlers/LargestTextPaintHandler.js +1 -1
  81. package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -1
  82. package/models/trace/handlers/LayerTreeHandler.d.ts +6 -6
  83. package/models/trace/handlers/LayerTreeHandler.js +6 -6
  84. package/models/trace/handlers/LayerTreeHandler.js.map +1 -1
  85. package/models/trace/handlers/LayoutShiftsHandler.d.ts +12 -20
  86. package/models/trace/handlers/LayoutShiftsHandler.js +73 -12
  87. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  88. package/models/trace/handlers/MemoryHandler.d.ts +2 -2
  89. package/models/trace/handlers/MemoryHandler.js +1 -1
  90. package/models/trace/handlers/MemoryHandler.js.map +1 -1
  91. package/models/trace/handlers/MetaHandler.d.ts +15 -14
  92. package/models/trace/handlers/MetaHandler.js +32 -30
  93. package/models/trace/handlers/MetaHandler.js.map +1 -1
  94. package/models/trace/handlers/ModelHandlers.d.ts +1 -1
  95. package/models/trace/handlers/ModelHandlers.js +1 -1
  96. package/models/trace/handlers/ModelHandlers.js.map +1 -1
  97. package/models/trace/handlers/NetworkRequestsHandler.d.ts +13 -12
  98. package/models/trace/handlers/NetworkRequestsHandler.js +68 -66
  99. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  100. package/models/trace/handlers/PageFramesHandler.d.ts +2 -2
  101. package/models/trace/handlers/PageFramesHandler.js +2 -2
  102. package/models/trace/handlers/PageFramesHandler.js.map +1 -1
  103. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +7 -7
  104. package/models/trace/handlers/PageLoadMetricsHandler.js +21 -24
  105. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  106. package/models/trace/handlers/RendererHandler.d.ts +19 -19
  107. package/models/trace/handlers/RendererHandler.js +5 -5
  108. package/models/trace/handlers/RendererHandler.js.map +1 -1
  109. package/models/trace/handlers/SamplesHandler.d.ts +6 -6
  110. package/models/trace/handlers/SamplesHandler.js +3 -3
  111. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  112. package/models/trace/handlers/ScreenshotsHandler.d.ts +6 -4
  113. package/models/trace/handlers/ScreenshotsHandler.js +11 -9
  114. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  115. package/models/trace/handlers/SelectorStatsHandler.d.ts +3 -3
  116. package/models/trace/handlers/SelectorStatsHandler.js +2 -2
  117. package/models/trace/handlers/SelectorStatsHandler.js.map +1 -1
  118. package/models/trace/handlers/ServerTimingsHandler.d.ts +10 -0
  119. package/models/trace/handlers/ServerTimingsHandler.js +118 -0
  120. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -0
  121. package/models/trace/handlers/Threads.d.ts +7 -7
  122. package/models/trace/handlers/Threads.js +5 -5
  123. package/models/trace/handlers/Threads.js.map +1 -1
  124. package/models/trace/handlers/UserInteractionsHandler.d.ts +13 -11
  125. package/models/trace/handlers/UserInteractionsHandler.js +13 -7
  126. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  127. package/models/trace/handlers/UserTimingsHandler.d.ts +5 -5
  128. package/models/trace/handlers/UserTimingsHandler.js +52 -9
  129. package/models/trace/handlers/UserTimingsHandler.js.map +1 -1
  130. package/models/trace/handlers/WarningsHandler.d.ts +5 -5
  131. package/models/trace/handlers/WarningsHandler.js +4 -5
  132. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  133. package/models/trace/handlers/WorkersHandler.d.ts +4 -4
  134. package/models/trace/handlers/WorkersHandler.js +1 -1
  135. package/models/trace/handlers/WorkersHandler.js.map +1 -1
  136. package/models/trace/handlers/handlers-tsconfig.json +1 -1
  137. package/models/trace/handlers/types.d.ts +7 -7
  138. package/models/trace/handlers/types.js.map +1 -1
  139. package/models/trace/helpers/Extensions.d.ts +2 -2
  140. package/models/trace/helpers/Extensions.js.map +1 -1
  141. package/models/trace/helpers/Network.d.ts +2 -2
  142. package/models/trace/helpers/Network.js +19 -2
  143. package/models/trace/helpers/Network.js.map +1 -1
  144. package/models/trace/helpers/SamplesIntegrator.d.ts +5 -5
  145. package/models/trace/helpers/SamplesIntegrator.js +10 -11
  146. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  147. package/models/trace/helpers/SyntheticEvents.d.ts +8 -14
  148. package/models/trace/helpers/SyntheticEvents.js +20 -31
  149. package/models/trace/helpers/SyntheticEvents.js.map +1 -1
  150. package/models/trace/helpers/Timing.d.ts +16 -4
  151. package/models/trace/helpers/Timing.js +33 -1
  152. package/models/trace/helpers/Timing.js.map +1 -1
  153. package/models/trace/helpers/Trace.d.ts +46 -32
  154. package/models/trace/helpers/Trace.js +53 -24
  155. package/models/trace/helpers/Trace.js.map +1 -1
  156. package/models/trace/helpers/TreeHelpers.d.ts +29 -8
  157. package/models/trace/helpers/TreeHelpers.js +87 -19
  158. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  159. package/models/trace/insights/Common.d.ts +4 -3
  160. package/models/trace/insights/Common.js +22 -7
  161. package/models/trace/insights/Common.js.map +1 -1
  162. package/models/trace/insights/CumulativeLayoutShift.d.ts +34 -13
  163. package/models/trace/insights/CumulativeLayoutShift.js +151 -59
  164. package/models/trace/insights/CumulativeLayoutShift.js.map +1 -1
  165. package/models/trace/insights/DocumentLatency.d.ts +9 -4
  166. package/models/trace/insights/DocumentLatency.js +82 -7
  167. package/models/trace/insights/DocumentLatency.js.map +1 -1
  168. package/models/trace/insights/FontDisplay.d.ts +11 -0
  169. package/models/trace/insights/FontDisplay.js +44 -0
  170. package/models/trace/insights/FontDisplay.js.map +1 -0
  171. package/models/trace/insights/InsightRunners.d.ts +3 -0
  172. package/models/trace/insights/InsightRunners.js +3 -0
  173. package/models/trace/insights/InsightRunners.js.map +1 -1
  174. package/models/trace/insights/InteractionToNextPaint.d.ts +4 -5
  175. package/models/trace/insights/InteractionToNextPaint.js +5 -3
  176. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  177. package/models/trace/insights/LargestContentfulPaint.d.ts +20 -7
  178. package/models/trace/insights/LargestContentfulPaint.js +57 -37
  179. package/models/trace/insights/LargestContentfulPaint.js.map +1 -1
  180. package/models/trace/insights/RenderBlocking.d.ts +3 -3
  181. package/models/trace/insights/RenderBlocking.js +29 -24
  182. package/models/trace/insights/RenderBlocking.js.map +1 -1
  183. package/models/trace/insights/SlowCSSSelector.d.ts +11 -0
  184. package/models/trace/insights/SlowCSSSelector.js +67 -0
  185. package/models/trace/insights/SlowCSSSelector.js.map +1 -0
  186. package/models/trace/insights/ThirdPartyWeb.d.ts +18 -0
  187. package/models/trace/insights/ThirdPartyWeb.js +174 -0
  188. package/models/trace/insights/ThirdPartyWeb.js.map +1 -0
  189. package/models/trace/insights/Viewport.d.ts +5 -2
  190. package/models/trace/insights/Viewport.js +14 -9
  191. package/models/trace/insights/Viewport.js.map +1 -1
  192. package/models/trace/insights/insights-tsconfig.json +9 -0
  193. package/models/trace/insights/insights.d.ts +1 -0
  194. package/models/trace/insights/insights.js +1 -0
  195. package/models/trace/insights/insights.js.map +1 -1
  196. package/models/trace/insights/types.d.ts +43 -25
  197. package/models/trace/insights/types.js.map +1 -1
  198. package/models/trace/lantern/core/NetworkAnalyzer.d.ts +6 -6
  199. package/models/trace/lantern/core/NetworkAnalyzer.js +12 -12
  200. package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
  201. package/models/trace/lantern/graph/BaseNode.d.ts +4 -4
  202. package/models/trace/lantern/graph/BaseNode.js +21 -21
  203. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  204. package/models/trace/lantern/graph/CPUNode.d.ts +1 -1
  205. package/models/trace/lantern/graph/CPUNode.js +5 -5
  206. package/models/trace/lantern/graph/CPUNode.js.map +1 -1
  207. package/models/trace/lantern/graph/PageDependencyGraph.d.ts +4 -4
  208. package/models/trace/lantern/graph/PageDependencyGraph.js +5 -5
  209. package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
  210. package/models/trace/lantern/simulation/ConnectionPool.d.ts +7 -7
  211. package/models/trace/lantern/simulation/ConnectionPool.js +26 -26
  212. package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
  213. package/models/trace/lantern/simulation/DNSCache.d.ts +3 -3
  214. package/models/trace/lantern/simulation/DNSCache.js +11 -11
  215. package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
  216. package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +1 -1
  217. package/models/trace/lantern/simulation/SimulationTimingMap.js +15 -15
  218. package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
  219. package/models/trace/lantern/simulation/Simulator.d.ts +28 -28
  220. package/models/trace/lantern/simulation/Simulator.js +113 -113
  221. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  222. package/models/trace/lantern/simulation/TCPConnection.d.ts +9 -9
  223. package/models/trace/lantern/simulation/TCPConnection.js +36 -36
  224. package/models/trace/lantern/simulation/TCPConnection.js.map +1 -1
  225. package/models/trace/root-causes/LayoutShift.d.ts +13 -13
  226. package/models/trace/root-causes/LayoutShift.js +7 -25
  227. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  228. package/models/trace/types/Configuration.d.ts +16 -0
  229. package/models/trace/types/Configuration.js +1 -0
  230. package/models/trace/types/Configuration.js.map +1 -1
  231. package/models/trace/types/Extensions.d.ts +9 -12
  232. package/models/trace/types/Extensions.js +2 -1
  233. package/models/trace/types/Extensions.js.map +1 -1
  234. package/models/trace/types/File.d.ts +55 -23
  235. package/models/trace/types/File.js +15 -3
  236. package/models/trace/types/File.js.map +1 -1
  237. package/models/trace/types/TraceEvents.d.ts +818 -713
  238. package/models/trace/types/TraceEvents.js +270 -277
  239. package/models/trace/types/TraceEvents.js.map +1 -1
  240. package/models/trace/types/types.d.ts +1 -1
  241. package/models/trace/types/types.js +1 -1
  242. package/models/trace/types/types.js.map +1 -1
  243. package/package.json +4 -2
  244. package/test/test-trace-engine.mjs +47 -2
  245. package/third_party/third-party-web/third-party-web.js +1 -0
  246. package/core/platform/PromiseUtilities.d.ts +0 -10
  247. package/core/platform/PromiseUtilities.js +0 -18
  248. package/core/platform/PromiseUtilities.js.map +0 -1
  249. package/core/platform/SetUtilities.d.ts +0 -2
  250. package/core/platform/SetUtilities.js +0 -23
  251. package/core/platform/SetUtilities.js.map +0 -1
  252. package/models/trace/EntriesFilter.d.ts +0 -72
  253. package/models/trace/EntriesFilter.js +0 -296
  254. package/models/trace/EntriesFilter.js.map +0 -1
  255. package/models/trace/LegacyTracingModel.js.map +0 -1
  256. package/models/trace/handlers/EnhancedTracesHandler.d.ts +0 -48
  257. package/models/trace/handlers/EnhancedTracesHandler.js +0 -165
  258. package/models/trace/handlers/EnhancedTracesHandler.js.map +0 -1
  259. package/models/trace/lantern/BaseNode.d.ts +0 -91
  260. package/models/trace/lantern/BaseNode.js +0 -268
  261. package/models/trace/lantern/BaseNode.js.map +0 -1
  262. package/models/trace/lantern/CPUNode.d.ts +0 -24
  263. package/models/trace/lantern/CPUNode.js +0 -64
  264. package/models/trace/lantern/CPUNode.js.map +0 -1
  265. package/models/trace/lantern/LanternError.d.ts +0 -3
  266. package/models/trace/lantern/LanternError.js +0 -7
  267. package/models/trace/lantern/LanternError.js.map +0 -1
  268. package/models/trace/lantern/MetricsModule.d.ts +0 -11
  269. package/models/trace/lantern/MetricsModule.js +0 -14
  270. package/models/trace/lantern/MetricsModule.js.map +0 -1
  271. package/models/trace/lantern/NetworkNode.d.ts +0 -22
  272. package/models/trace/lantern/NetworkNode.js +0 -83
  273. package/models/trace/lantern/NetworkNode.js.map +0 -1
  274. package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
  275. package/models/trace/lantern/PageDependencyGraph.js +0 -509
  276. package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
  277. package/models/trace/lantern/SimulationModule.d.ts +0 -17
  278. package/models/trace/lantern/SimulationModule.js +0 -13
  279. package/models/trace/lantern/SimulationModule.js.map +0 -1
  280. package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
  281. package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
  282. package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
@@ -106,7 +106,7 @@ export function handleEvent(event) {
106
106
  * A fake trace event created to support CDP.Profiler.Profiles in the
107
107
  * trace engine.
108
108
  */
109
- if (Types.TraceEvents.isSyntheticCpuProfile(event)) {
109
+ if (Types.Events.isSyntheticCpuProfile(event)) {
110
110
  // At the moment we are attaching to a single node target so we
111
111
  // should only get a single CPU profile. The values of the process
112
112
  // id and thread id are not really important, so we use the data
@@ -121,7 +121,7 @@ export function handleEvent(event) {
121
121
  profileData.threadId = tid;
122
122
  return;
123
123
  }
124
- if (Types.TraceEvents.isTraceEventProfile(event)) {
124
+ if (Types.Events.isProfile(event)) {
125
125
  // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain,
126
126
  // but use profileEvent.ts which has been translated to Perfetto's clock
127
127
  // domain. Also convert from ms to us.
@@ -132,7 +132,7 @@ export function handleEvent(event) {
132
132
  profileData.threadId = event.tid;
133
133
  return;
134
134
  }
135
- if (Types.TraceEvents.isTraceEventProfileChunk(event)) {
135
+ if (Types.Events.isProfileChunk(event)) {
136
136
  const profileData = getOrCreatePreProcessedData(event.pid, event.id);
137
137
  const cdpProfile = profileData.rawProfile;
138
138
  const nodesAndSamples = event.args?.data?.cpuProfile || { samples: [] };
@@ -1 +1 @@
1
- {"version":3,"file":"SamplesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.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';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst events =\n new Map<Types.TraceEvents.ProcessID, Map<Types.TraceEvents.ThreadID, Types.TraceEvents.TraceEventComplete[]>>();\n\nconst profilesInProcess = new Map<Types.TraceEvents.ProcessID, Map<Types.TraceEvents.ThreadID, ProfileData>>();\nconst entryToNode = new Map<Types.TraceEvents.TraceEventData, Helpers.TreeHelpers.TraceEntryNode>();\n\n// The profile head, containing its metadata like its start\n// time, comes in a \"Profile\" event. The sample data comes in\n// \"ProfileChunk\" events. We match these ProfileChunks with their head\n// using process and profile ids. However, in order to integrate sample\n// data with trace data, we need the thread id that owns each profile.\n// This thread id is extracted from the head event.\n// For this reason, we have a preprocessed data structure, where events\n// are matched by profile id, which we then finish processing to export\n// events matched by thread id.\nconst preprocessedData = new Map<Types.TraceEvents.ProcessID, Map<Types.TraceEvents.ProfileID, PreprocessedData>>();\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nfunction buildProfileCalls(): void {\n for (const [processId, profiles] of preprocessedData) {\n for (const [profileId, preProcessedData] of profiles) {\n const threadId = preProcessedData.threadId;\n if (!preProcessedData.rawProfile.nodes.length || threadId === undefined) {\n continue;\n }\n const indexStack: number[] = [];\n\n const profileModel = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(preProcessedData.rawProfile);\n const profileTree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n profileTree.maxDepth = profileModel.maxDepth;\n\n const finalizedData: ProfileData = {\n rawProfile: preProcessedData.rawProfile,\n parsedProfile: profileModel,\n profileCalls: [],\n profileTree,\n profileId,\n };\n\n const dataByThread = Platform.MapUtilities.getWithDefault(profilesInProcess, processId, () => new Map());\n profileModel.forEachFrame(openFrameCallback, closeFrameCallback);\n dataByThread.set(threadId, finalizedData);\n\n function openFrameCallback(\n depth: number, node: CPUProfile.ProfileTreeModel.ProfileNode, sampleIndex: number,\n timeStampMilliseconds: number): void {\n if (threadId === undefined) {\n return;\n }\n const ts = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timeStampMilliseconds));\n const nodeId = node.id as Helpers.TreeHelpers.TraceEntryNodeId;\n\n const profileCall = Helpers.Trace.makeProfileCall(node, profileId, sampleIndex, ts, processId, threadId);\n finalizedData.profileCalls.push(profileCall);\n indexStack.push(finalizedData.profileCalls.length - 1);\n const traceEntryNode = Helpers.TreeHelpers.makeEmptyTraceEntryNode(profileCall, nodeId);\n entryToNode.set(profileCall, traceEntryNode);\n traceEntryNode.depth = depth;\n if (indexStack.length === 1) {\n // First call in the stack is a root call.\n finalizedData.profileTree?.roots.add(traceEntryNode);\n }\n }\n function closeFrameCallback(\n _depth: number, _node: CPUProfile.ProfileTreeModel.ProfileNode, _sampleIndex: number,\n _timeStampMillis: number, durMs: number, selfTimeMs: number): void {\n const profileCallIndex = indexStack.pop();\n const profileCall = profileCallIndex !== undefined && finalizedData.profileCalls[profileCallIndex];\n if (!profileCall) {\n return;\n }\n const {callFrame, ts, pid, tid} = profileCall;\n const traceEntryNode = entryToNode.get(profileCall);\n if (callFrame === undefined || ts === undefined || pid === undefined || profileId === undefined ||\n tid === undefined || traceEntryNode === undefined) {\n return;\n }\n const dur = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(durMs));\n const selfTime = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(selfTimeMs));\n profileCall.dur = dur;\n traceEntryNode.selfTime = selfTime;\n\n const parentIndex = indexStack.at(-1);\n const parent = parentIndex !== undefined && finalizedData.profileCalls.at(parentIndex);\n const parentNode = parent && entryToNode.get(parent);\n if (!parentNode) {\n return;\n }\n traceEntryNode.parent = parentNode;\n parentNode.children.push(traceEntryNode);\n }\n }\n }\n}\n\nexport function reset(): void {\n events.clear();\n preprocessedData.clear();\n profilesInProcess.clear();\n entryToNode.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Samples Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n\n /**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\n if (Types.TraceEvents.isSyntheticCpuProfile(event)) {\n // At the moment we are attaching to a single node target so we\n // should only get a single CPU profile. The values of the process\n // id and thread id are not really important, so we use the data\n // in the fake event. Should multi-thread CPU profiling be supported\n // we could use these fields in the event to pass thread info.\n const pid = event.pid;\n const tid = event.tid;\n // Create an arbitrary profile id.\n const profileId = '0x1' as Types.TraceEvents.ProfileID;\n const profileData = getOrCreatePreProcessedData(pid, profileId);\n profileData.rawProfile = event.args.data.cpuProfile;\n profileData.threadId = tid;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventProfile(event)) {\n // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain,\n // but use profileEvent.ts which has been translated to Perfetto's clock\n // domain. Also convert from ms to us.\n // Note: events are collected on a different thread than what's sampled.\n // The correct process and thread ids are specified by the profile.\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n profileData.rawProfile.startTime = event.ts;\n profileData.threadId = event.tid;\n return;\n }\n if (Types.TraceEvents.isTraceEventProfileChunk(event)) {\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n const cdpProfile = profileData.rawProfile;\n const nodesAndSamples: Types.TraceEvents.TraceEventPartialProfile|undefined =\n event.args?.data?.cpuProfile || {samples: []};\n const samples = nodesAndSamples?.samples || [];\n const nodes: CPUProfile.CPUProfileDataModel.ExtendedProfileNode[] = [];\n for (const n of nodesAndSamples?.nodes || []) {\n const lineNumber = typeof n.callFrame.lineNumber === 'undefined' ? -1 : n.callFrame.lineNumber;\n const columnNumber = typeof n.callFrame.columnNumber === 'undefined' ? -1 : n.callFrame.columnNumber;\n\n const scriptId = String(n.callFrame.scriptId) as Protocol.Runtime.ScriptId;\n const url = n.callFrame.url || '';\n const node = {\n ...n,\n callFrame: {\n ...n.callFrame,\n url,\n lineNumber,\n columnNumber,\n scriptId,\n },\n };\n nodes.push(node);\n }\n\n const timeDeltas = event.args.data?.timeDeltas || [];\n const lines = event.args.data?.lines || Array(samples.length).fill(0);\n cdpProfile.nodes.push(...nodes);\n cdpProfile.samples?.push(...samples);\n cdpProfile.timeDeltas?.push(...timeDeltas);\n cdpProfile.lines?.push(...lines);\n if (cdpProfile.samples && cdpProfile.timeDeltas && cdpProfile.samples.length !== cdpProfile.timeDeltas.length) {\n console.error('Failed to parse CPU profile.');\n return;\n }\n if (!cdpProfile.endTime && cdpProfile.timeDeltas) {\n const timeDeltas: number[] = cdpProfile.timeDeltas;\n cdpProfile.endTime = timeDeltas.reduce((x, y) => x + y, cdpProfile.startTime);\n }\n return;\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n buildProfileCalls();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): SamplesHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Samples Handler is not finalized');\n }\n\n return {\n profilesInProcess,\n entryToNode,\n };\n}\n\nfunction getOrCreatePreProcessedData(\n processId: Types.TraceEvents.ProcessID, profileId: Types.TraceEvents.ProfileID): PreprocessedData {\n const profileById = Platform.MapUtilities.getWithDefault(preprocessedData, processId, () => new Map());\n return Platform.MapUtilities.getWithDefault<Types.TraceEvents.ProfileID, PreprocessedData>(\n profileById, profileId, () => ({\n rawProfile: {\n startTime: 0,\n endTime: 0,\n nodes: [],\n samples: [],\n timeDeltas: [],\n lines: [],\n },\n profileId,\n }));\n}\n\nexport interface SamplesHandlerData {\n profilesInProcess: typeof profilesInProcess;\n entryToNode: typeof entryToNode;\n}\n\nexport type ProfileData = {\n profileId: Types.TraceEvents.ProfileID,\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n parsedProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel,\n /**\n * Contains the calls built from the CPU profile samples.\n * Note: This doesn't contain real trace events coming from the\n * browser, only calls synthetically typed as trace events for\n * compatibility, as such it only makes sense to use them in pure CPU\n * profiles.\n *\n * If you need the profile calls from a CPU profile obtained from a\n * web trace, use the data exported by the RendererHandler instead.\n */\n profileCalls: Types.TraceEvents.SyntheticProfileCall[],\n /**\n * Contains the call tree built from the CPU profile samples.\n * Similar to the profileCalls field, this tree does not contain nor\n * take into account trace events, as such it only makes sense to use\n * them in pure CPU profiles.\n */\n profileTree?: Helpers.TreeHelpers.TraceEntryTree,\n};\n\ntype PreprocessedData = {\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n profileId: Types.TraceEvents.ProfileID,\n threadId?: Types.TraceEvents.ThreadID,\n};\n\n/**\n * Returns the name of a function for a given synthetic profile call.\n * We first look to find the ProfileNode representing this call, and use its\n * function name. This is preferred (and should always exist) because if we\n * resolve sourcemaps, we will update this name. If that name is not present,\n * we fall back to the function name that was in the callframe that we got\n * when parsing the profile's trace data.\n */\nexport function getProfileCallFunctionName(\n data: SamplesHandlerData, entry: Types.TraceEvents.SyntheticProfileCall): string {\n const profile = data.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node?.functionName) {\n return node.functionName;\n }\n return entry.callFrame.functionName;\n}\n"]}
1
+ {"version":3,"file":"SamplesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.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';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst events = new Map<Types.Events.ProcessID, Map<Types.Events.ThreadID, Types.Events.Complete[]>>();\n\nconst profilesInProcess = new Map<Types.Events.ProcessID, Map<Types.Events.ThreadID, ProfileData>>();\nconst entryToNode = new Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>();\n\n// The profile head, containing its metadata like its start\n// time, comes in a \"Profile\" event. The sample data comes in\n// \"ProfileChunk\" events. We match these ProfileChunks with their head\n// using process and profile ids. However, in order to integrate sample\n// data with trace data, we need the thread id that owns each profile.\n// This thread id is extracted from the head event.\n// For this reason, we have a preprocessed data structure, where events\n// are matched by profile id, which we then finish processing to export\n// events matched by thread id.\nconst preprocessedData = new Map<Types.Events.ProcessID, Map<Types.Events.ProfileID, PreprocessedData>>();\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nfunction buildProfileCalls(): void {\n for (const [processId, profiles] of preprocessedData) {\n for (const [profileId, preProcessedData] of profiles) {\n const threadId = preProcessedData.threadId;\n if (!preProcessedData.rawProfile.nodes.length || threadId === undefined) {\n continue;\n }\n const indexStack: number[] = [];\n\n const profileModel = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(preProcessedData.rawProfile);\n const profileTree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n profileTree.maxDepth = profileModel.maxDepth;\n\n const finalizedData: ProfileData = {\n rawProfile: preProcessedData.rawProfile,\n parsedProfile: profileModel,\n profileCalls: [],\n profileTree,\n profileId,\n };\n\n const dataByThread = Platform.MapUtilities.getWithDefault(profilesInProcess, processId, () => new Map());\n profileModel.forEachFrame(openFrameCallback, closeFrameCallback);\n dataByThread.set(threadId, finalizedData);\n\n function openFrameCallback(\n depth: number, node: CPUProfile.ProfileTreeModel.ProfileNode, sampleIndex: number,\n timeStampMilliseconds: number): void {\n if (threadId === undefined) {\n return;\n }\n const ts = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timeStampMilliseconds));\n const nodeId = node.id as Helpers.TreeHelpers.TraceEntryNodeId;\n\n const profileCall = Helpers.Trace.makeProfileCall(node, profileId, sampleIndex, ts, processId, threadId);\n finalizedData.profileCalls.push(profileCall);\n indexStack.push(finalizedData.profileCalls.length - 1);\n const traceEntryNode = Helpers.TreeHelpers.makeEmptyTraceEntryNode(profileCall, nodeId);\n entryToNode.set(profileCall, traceEntryNode);\n traceEntryNode.depth = depth;\n if (indexStack.length === 1) {\n // First call in the stack is a root call.\n finalizedData.profileTree?.roots.add(traceEntryNode);\n }\n }\n function closeFrameCallback(\n _depth: number, _node: CPUProfile.ProfileTreeModel.ProfileNode, _sampleIndex: number,\n _timeStampMillis: number, durMs: number, selfTimeMs: number): void {\n const profileCallIndex = indexStack.pop();\n const profileCall = profileCallIndex !== undefined && finalizedData.profileCalls[profileCallIndex];\n if (!profileCall) {\n return;\n }\n const {callFrame, ts, pid, tid} = profileCall;\n const traceEntryNode = entryToNode.get(profileCall);\n if (callFrame === undefined || ts === undefined || pid === undefined || profileId === undefined ||\n tid === undefined || traceEntryNode === undefined) {\n return;\n }\n const dur = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(durMs));\n const selfTime = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(selfTimeMs));\n profileCall.dur = dur;\n traceEntryNode.selfTime = selfTime;\n\n const parentIndex = indexStack.at(-1);\n const parent = parentIndex !== undefined && finalizedData.profileCalls.at(parentIndex);\n const parentNode = parent && entryToNode.get(parent);\n if (!parentNode) {\n return;\n }\n traceEntryNode.parent = parentNode;\n parentNode.children.push(traceEntryNode);\n }\n }\n }\n}\n\nexport function reset(): void {\n events.clear();\n preprocessedData.clear();\n profilesInProcess.clear();\n entryToNode.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Samples Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n\n /**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\n if (Types.Events.isSyntheticCpuProfile(event)) {\n // At the moment we are attaching to a single node target so we\n // should only get a single CPU profile. The values of the process\n // id and thread id are not really important, so we use the data\n // in the fake event. Should multi-thread CPU profiling be supported\n // we could use these fields in the event to pass thread info.\n const pid = event.pid;\n const tid = event.tid;\n // Create an arbitrary profile id.\n const profileId = '0x1' as Types.Events.ProfileID;\n const profileData = getOrCreatePreProcessedData(pid, profileId);\n profileData.rawProfile = event.args.data.cpuProfile;\n profileData.threadId = tid;\n return;\n }\n\n if (Types.Events.isProfile(event)) {\n // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain,\n // but use profileEvent.ts which has been translated to Perfetto's clock\n // domain. Also convert from ms to us.\n // Note: events are collected on a different thread than what's sampled.\n // The correct process and thread ids are specified by the profile.\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n profileData.rawProfile.startTime = event.ts;\n profileData.threadId = event.tid;\n return;\n }\n if (Types.Events.isProfileChunk(event)) {\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n const cdpProfile = profileData.rawProfile;\n const nodesAndSamples: Types.Events.PartialProfile|undefined = event.args?.data?.cpuProfile || {samples: []};\n const samples = nodesAndSamples?.samples || [];\n const nodes: CPUProfile.CPUProfileDataModel.ExtendedProfileNode[] = [];\n for (const n of nodesAndSamples?.nodes || []) {\n const lineNumber = typeof n.callFrame.lineNumber === 'undefined' ? -1 : n.callFrame.lineNumber;\n const columnNumber = typeof n.callFrame.columnNumber === 'undefined' ? -1 : n.callFrame.columnNumber;\n\n const scriptId = String(n.callFrame.scriptId) as Protocol.Runtime.ScriptId;\n const url = n.callFrame.url || '';\n const node = {\n ...n,\n callFrame: {\n ...n.callFrame,\n url,\n lineNumber,\n columnNumber,\n scriptId,\n },\n };\n nodes.push(node);\n }\n\n const timeDeltas = event.args.data?.timeDeltas || [];\n const lines = event.args.data?.lines || Array(samples.length).fill(0);\n cdpProfile.nodes.push(...nodes);\n cdpProfile.samples?.push(...samples);\n cdpProfile.timeDeltas?.push(...timeDeltas);\n cdpProfile.lines?.push(...lines);\n if (cdpProfile.samples && cdpProfile.timeDeltas && cdpProfile.samples.length !== cdpProfile.timeDeltas.length) {\n console.error('Failed to parse CPU profile.');\n return;\n }\n if (!cdpProfile.endTime && cdpProfile.timeDeltas) {\n const timeDeltas: number[] = cdpProfile.timeDeltas;\n cdpProfile.endTime = timeDeltas.reduce((x, y) => x + y, cdpProfile.startTime);\n }\n return;\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n buildProfileCalls();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): SamplesHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Samples Handler is not finalized');\n }\n\n return {\n profilesInProcess,\n entryToNode,\n };\n}\n\nfunction getOrCreatePreProcessedData(\n processId: Types.Events.ProcessID, profileId: Types.Events.ProfileID): PreprocessedData {\n const profileById = Platform.MapUtilities.getWithDefault(preprocessedData, processId, () => new Map());\n return Platform.MapUtilities.getWithDefault<Types.Events.ProfileID, PreprocessedData>(\n profileById, profileId, () => ({\n rawProfile: {\n startTime: 0,\n endTime: 0,\n nodes: [],\n samples: [],\n timeDeltas: [],\n lines: [],\n },\n profileId,\n }));\n}\n\nexport interface SamplesHandlerData {\n profilesInProcess: typeof profilesInProcess;\n entryToNode: typeof entryToNode;\n}\n\nexport type ProfileData = {\n profileId: Types.Events.ProfileID,\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n parsedProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel,\n /**\n * Contains the calls built from the CPU profile samples.\n * Note: This doesn't contain real trace events coming from the\n * browser, only calls synthetically typed as trace events for\n * compatibility, as such it only makes sense to use them in pure CPU\n * profiles.\n *\n * If you need the profile calls from a CPU profile obtained from a\n * web trace, use the data exported by the RendererHandler instead.\n */\n profileCalls: Types.Events.SyntheticProfileCall[],\n /**\n * Contains the call tree built from the CPU profile samples.\n * Similar to the profileCalls field, this tree does not contain nor\n * take into account trace events, as such it only makes sense to use\n * them in pure CPU profiles.\n */\n profileTree?: Helpers.TreeHelpers.TraceEntryTree,\n};\n\ntype PreprocessedData = {\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n profileId: Types.Events.ProfileID,\n threadId?: Types.Events.ThreadID,\n};\n\n/**\n * Returns the name of a function for a given synthetic profile call.\n * We first look to find the ProfileNode representing this call, and use its\n * function name. This is preferred (and should always exist) because if we\n * resolve sourcemaps, we will update this name. If that name is not present,\n * we fall back to the function name that was in the callframe that we got\n * when parsing the profile's trace data.\n */\nexport function getProfileCallFunctionName(data: SamplesHandlerData, entry: Types.Events.SyntheticProfileCall): string {\n const profile = data.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node?.functionName) {\n return node.functionName;\n }\n return entry.callFrame.functionName;\n}\n"]}
@@ -1,7 +1,9 @@
1
1
  import * as Types from '../types/types.js';
2
- import { type TraceEventHandlerName } from './types.js';
2
+ import type { HandlerName } from './types.js';
3
3
  export declare function reset(): void;
4
- export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
4
+ export declare function handleEvent(event: Types.Events.Event): void;
5
5
  export declare function finalize(): Promise<void>;
6
- export declare function data(): Types.TraceEvents.SyntheticScreenshot[];
7
- export declare function deps(): TraceEventHandlerName[];
6
+ export declare function data(): ({
7
+ all: Types.Events.SyntheticScreenshot[];
8
+ });
9
+ export declare function deps(): HandlerName[];
@@ -7,19 +7,19 @@ import * as Types from '../types/types.js';
7
7
  // used to store the event in the correct process thread entry below.
8
8
  const unpairedAsyncEvents = [];
9
9
  const snapshotEvents = [];
10
- const syntheticScreenshotEvents = [];
10
+ const syntheticScreenshots = [];
11
11
  let frameSequenceToTs = {};
12
12
  export function reset() {
13
13
  unpairedAsyncEvents.length = 0;
14
14
  snapshotEvents.length = 0;
15
- syntheticScreenshotEvents.length = 0;
15
+ syntheticScreenshots.length = 0;
16
16
  frameSequenceToTs = {};
17
17
  }
18
18
  export function handleEvent(event) {
19
- if (Types.TraceEvents.isTraceEventScreenshot(event)) {
19
+ if (Types.Events.isScreenshot(event)) {
20
20
  snapshotEvents.push(event);
21
21
  }
22
- else if (Types.TraceEvents.isTraceEventPipelineReporter(event)) {
22
+ else if (Types.Events.isPipelineReporter(event)) {
23
23
  unpairedAsyncEvents.push(event);
24
24
  }
25
25
  }
@@ -32,20 +32,21 @@ export async function finalize() {
32
32
  }));
33
33
  for (const snapshotEvent of snapshotEvents) {
34
34
  const { cat, name, ph, pid, tid } = snapshotEvent;
35
- const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticBasedEvent({
35
+ const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({
36
36
  rawSourceEvent: snapshotEvent,
37
37
  cat,
38
38
  name,
39
39
  ph,
40
40
  pid,
41
41
  tid,
42
- // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot was adjusted to the right/later
43
- ts: getPresentationTimestamp(snapshotEvent),
42
+ // TODO(paulirish, crbug.com/41363012): investigate why getPresentationTimestamp(snapshotEvent) seems less accurate. Resolve screenshot timing innaccuracy.
43
+ // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot should be adjusted to the right/later
44
+ ts: snapshotEvent.ts,
44
45
  args: {
45
46
  dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`,
46
47
  },
47
48
  });
48
- syntheticScreenshotEvents.push(syntheticEvent);
49
+ syntheticScreenshots.push(syntheticEvent);
49
50
  }
50
51
  }
51
52
  /**
@@ -54,6 +55,7 @@ export async function finalize() {
54
55
  * We match that up with the "PipelineReporter" trace events as they terminate at presentation.
55
56
  * Presentation == when the pixels hit the screen. AKA Swap on the GPU
56
57
  */
58
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
59
  function getPresentationTimestamp(screenshotEvent) {
58
60
  const frameSequence = parseInt(screenshotEvent.id, 16);
59
61
  // If it's 1, then it's an old trace (before https://crrev.com/c/4957973) and cannot be corrected.
@@ -73,7 +75,7 @@ function getPresentationTimestamp(screenshotEvent) {
73
75
  }
74
76
  // TODO(crbug/41484172): should be readonly
75
77
  export function data() {
76
- return syntheticScreenshotEvents;
78
+ return { all: syntheticScreenshots };
77
79
  }
78
80
  export function deps() {
79
81
  return ['Meta'];
@@ -1 +1 @@
1
- {"version":3,"file":"ScreenshotsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.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 Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type TraceEventHandlerName} from './types.js';\n\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nconst unpairedAsyncEvents: Types.TraceEvents.TraceEventPipelineReporter[] = [];\n\nconst snapshotEvents: Types.TraceEvents.TraceEventScreenshot[] = [];\nconst syntheticScreenshotEvents: Types.TraceEvents.SyntheticScreenshot[] = [];\nlet frameSequenceToTs: Record<string, Types.Timing.MicroSeconds> = {};\n\nexport function reset(): void {\n unpairedAsyncEvents.length = 0;\n snapshotEvents.length = 0;\n syntheticScreenshotEvents.length = 0;\n frameSequenceToTs = {};\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventScreenshot(event)) {\n snapshotEvents.push(event);\n } else if (Types.TraceEvents.isTraceEventPipelineReporter(event)) {\n unpairedAsyncEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise<void> {\n const pipelineReporterEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(unpairedAsyncEvents);\n\n frameSequenceToTs = Object.fromEntries(pipelineReporterEvents.map(evt => {\n const frameSequenceId = evt.args.data.beginEvent.args.chrome_frame_reporter.frame_sequence;\n const presentationTs = Types.Timing.MicroSeconds(evt.ts + evt.dur);\n return [frameSequenceId, presentationTs];\n }));\n\n for (const snapshotEvent of snapshotEvents) {\n const {cat, name, ph, pid, tid} = snapshotEvent;\n const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticBasedEvent<\n Types.TraceEvents.SyntheticScreenshot>({\n rawSourceEvent: snapshotEvent,\n cat,\n name,\n ph,\n pid,\n tid,\n // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot was adjusted to the right/later\n ts: getPresentationTimestamp(snapshotEvent),\n args: {\n dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`,\n },\n });\n syntheticScreenshotEvents.push(syntheticEvent);\n }\n}\n\n/**\n * Correct the screenshot timestamps\n * The screenshot 'snapshot object' trace event has the \"frame sequence number\" attached as an ID.\n * We match that up with the \"PipelineReporter\" trace events as they terminate at presentation.\n * Presentation == when the pixels hit the screen. AKA Swap on the GPU\n */\nfunction getPresentationTimestamp(screenshotEvent: Types.TraceEvents.TraceEventScreenshot): Types.Timing.MicroSeconds {\n const frameSequence = parseInt(screenshotEvent.id, 16);\n // If it's 1, then it's an old trace (before https://crrev.com/c/4957973) and cannot be corrected.\n if (frameSequence === 1) {\n return screenshotEvent.ts;\n }\n // The screenshot trace event's `ts` reflects the \"expected display time\" which is ESTIMATE.\n // It is set by the compositor frame sink from the `expected_display_time`, which is based on a previously known\n // frame start PLUS the vsync interval (eg 16.6ms)\n const updatedTs = frameSequenceToTs[frameSequence];\n // Do we always find a match? No...\n // We generally don't match the very first screenshot and, sometimes, the last\n // The very first screenshot is requested immediately (even if nothing is painting). As a result there's no compositor\n // instrumentation running alongside.\n // The last one is sometimes missing as because the trace terminates right before the associated PipelineReporter is emitted.\n return updatedTs ?? screenshotEvent.ts;\n}\n\n// TODO(crbug/41484172): should be readonly\nexport function data(): Types.TraceEvents.SyntheticScreenshot[] {\n return syntheticScreenshotEvents;\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta'];\n}\n"]}
1
+ {"version":3,"file":"ScreenshotsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.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 Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {HandlerName} from './types.js';\n\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nconst unpairedAsyncEvents: Types.Events.PipelineReporter[] = [];\n\nconst snapshotEvents: Types.Events.Screenshot[] = [];\nconst syntheticScreenshots: Types.Events.SyntheticScreenshot[] = [];\nlet frameSequenceToTs: Record<string, Types.Timing.MicroSeconds> = {};\n\nexport function reset(): void {\n unpairedAsyncEvents.length = 0;\n snapshotEvents.length = 0;\n syntheticScreenshots.length = 0;\n frameSequenceToTs = {};\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isScreenshot(event)) {\n snapshotEvents.push(event);\n } else if (Types.Events.isPipelineReporter(event)) {\n unpairedAsyncEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise<void> {\n const pipelineReporterEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(unpairedAsyncEvents);\n\n frameSequenceToTs = Object.fromEntries(pipelineReporterEvents.map(evt => {\n const frameSequenceId = evt.args.data.beginEvent.args.chrome_frame_reporter.frame_sequence;\n const presentationTs = Types.Timing.MicroSeconds(evt.ts + evt.dur);\n return [frameSequenceId, presentationTs];\n }));\n\n for (const snapshotEvent of snapshotEvents) {\n const {cat, name, ph, pid, tid} = snapshotEvent;\n const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent<\n Types.Events.SyntheticScreenshot>({\n rawSourceEvent: snapshotEvent,\n cat,\n name,\n ph,\n pid,\n tid,\n // TODO(paulirish, crbug.com/41363012): investigate why getPresentationTimestamp(snapshotEvent) seems less accurate. Resolve screenshot timing innaccuracy.\n // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot should be adjusted to the right/later\n ts: snapshotEvent.ts,\n args: {\n dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`,\n },\n });\n syntheticScreenshots.push(syntheticEvent);\n }\n}\n\n/**\n * Correct the screenshot timestamps\n * The screenshot 'snapshot object' trace event has the \"frame sequence number\" attached as an ID.\n * We match that up with the \"PipelineReporter\" trace events as they terminate at presentation.\n * Presentation == when the pixels hit the screen. AKA Swap on the GPU\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction getPresentationTimestamp(screenshotEvent: Types.Events.Screenshot): Types.Timing.MicroSeconds {\n const frameSequence = parseInt(screenshotEvent.id, 16);\n // If it's 1, then it's an old trace (before https://crrev.com/c/4957973) and cannot be corrected.\n if (frameSequence === 1) {\n return screenshotEvent.ts;\n }\n // The screenshot trace event's `ts` reflects the \"expected display time\" which is ESTIMATE.\n // It is set by the compositor frame sink from the `expected_display_time`, which is based on a previously known\n // frame start PLUS the vsync interval (eg 16.6ms)\n const updatedTs = frameSequenceToTs[frameSequence];\n // Do we always find a match? No...\n // We generally don't match the very first screenshot and, sometimes, the last\n // The very first screenshot is requested immediately (even if nothing is painting). As a result there's no compositor\n // instrumentation running alongside.\n // The last one is sometimes missing as because the trace terminates right before the associated PipelineReporter is emitted.\n return updatedTs ?? screenshotEvent.ts;\n}\n\n// TODO(crbug/41484172): should be readonly\nexport function data(): ({all: Types.Events.SyntheticScreenshot[]}) {\n return {all: syntheticScreenshots};\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta'];\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  import * as Types from '../types/types.js';
2
2
  export declare function reset(): void;
3
- export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
3
+ export declare function handleEvent(event: Types.Events.Event): void;
4
4
  export interface SelectorStatsData {
5
- dataForUpdateLayoutEvent: Map<Types.TraceEvents.TraceEventUpdateLayoutTree, {
6
- timings: Types.TraceEvents.SelectorTiming[];
5
+ dataForUpdateLayoutEvent: Map<Types.Events.UpdateLayoutTree, {
6
+ timings: Types.Events.SelectorTiming[];
7
7
  }>;
8
8
  }
9
9
  export declare function data(): SelectorStatsData;
@@ -9,13 +9,13 @@ export function reset() {
9
9
  selectorDataForUpdateLayoutTree.clear();
10
10
  }
11
11
  export function handleEvent(event) {
12
- if (Types.TraceEvents.isTraceEventSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {
12
+ if (Types.Events.isSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {
13
13
  selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, {
14
14
  timings: event.args.selector_stats.selector_timings,
15
15
  });
16
16
  return;
17
17
  }
18
- if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {
18
+ if (Types.Events.isUpdateLayoutTree(event)) {
19
19
  lastUpdateLayoutTreeEvent = event;
20
20
  return;
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SelectorStatsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,IAAI,yBAAyB,GAAsD,IAAI,CAAC;AAExF,MAAM,+BAA+B,GAAG,IAAI,GAAG,EAE3C,CAAC;AAEL,MAAM,UAAU,KAAK;IACnB,yBAAyB,GAAG,IAAI,CAAC;IACjC,+BAA+B,CAAC,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,KAAK,CAAC,WAAW,CAAC,yBAAyB,CAAC,KAAK,CAAC,IAAI,yBAAyB,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACjH,+BAA+B,CAAC,GAAG,CAAC,yBAAyB,EAAE;YAC7D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB;SACpD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,yBAAyB,GAAG,KAAK,CAAC;QAClC,OAAO;IACT,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,wBAAwB,EAAE,+BAA+B;KAC1D,CAAC;AACJ,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 * as Types from '../types/types.js';\n\nlet lastUpdateLayoutTreeEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\nconst selectorDataForUpdateLayoutTree = new Map<Types.TraceEvents.TraceEventUpdateLayoutTree, {\n timings: Types.TraceEvents.SelectorTiming[],\n}>();\n\nexport function reset(): void {\n lastUpdateLayoutTreeEvent = null;\n selectorDataForUpdateLayoutTree.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {\n selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, {\n timings: event.args.selector_stats.selector_timings,\n });\n return;\n }\n\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastUpdateLayoutTreeEvent = event;\n return;\n }\n}\n\nexport interface SelectorStatsData {\n dataForUpdateLayoutEvent: Map<Types.TraceEvents.TraceEventUpdateLayoutTree, {\n timings: Types.TraceEvents.SelectorTiming[],\n }>;\n}\n\nexport function data(): SelectorStatsData {\n return {\n dataForUpdateLayoutEvent: selectorDataForUpdateLayoutTree,\n };\n}\n"]}
1
+ {"version":3,"file":"SelectorStatsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,IAAI,yBAAyB,GAAuC,IAAI,CAAC;AAEzE,MAAM,+BAA+B,GAAG,IAAI,GAAG,EAE3C,CAAC;AAEL,MAAM,UAAU,KAAK;IACnB,yBAAyB,GAAG,IAAI,CAAC;IACjC,+BAA+B,CAAC,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,yBAAyB,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAClG,+BAA+B,CAAC,GAAG,CAAC,yBAAyB,EAAE;YAC7D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB;SACpD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,yBAAyB,GAAG,KAAK,CAAC;QAClC,OAAO;IACT,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,wBAAwB,EAAE,+BAA+B;KAC1D,CAAC;AACJ,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 * as Types from '../types/types.js';\n\nlet lastUpdateLayoutTreeEvent: Types.Events.UpdateLayoutTree|null = null;\n\nconst selectorDataForUpdateLayoutTree = new Map<Types.Events.UpdateLayoutTree, {\n timings: Types.Events.SelectorTiming[],\n}>();\n\nexport function reset(): void {\n lastUpdateLayoutTreeEvent = null;\n selectorDataForUpdateLayoutTree.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {\n selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, {\n timings: event.args.selector_stats.selector_timings,\n });\n return;\n }\n\n if (Types.Events.isUpdateLayoutTree(event)) {\n lastUpdateLayoutTreeEvent = event;\n return;\n }\n}\n\nexport interface SelectorStatsData {\n dataForUpdateLayoutEvent: Map<Types.Events.UpdateLayoutTree, {\n timings: Types.Events.SelectorTiming[],\n }>;\n}\n\nexport function data(): SelectorStatsData {\n return {\n dataForUpdateLayoutEvent: selectorDataForUpdateLayoutTree,\n };\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import * as Types from '../types/types.js';
2
+ import { type HandlerName } from './types.js';
3
+ export declare function reset(): void;
4
+ export declare function initialize(): void;
5
+ export declare function handleEvent(_event: Types.Events.Event): void;
6
+ export declare function finalize(): Promise<void>;
7
+ export declare function data(): {
8
+ serverTimings: Types.Events.SyntheticServerTiming[];
9
+ };
10
+ export declare function deps(): HandlerName[];
@@ -0,0 +1,118 @@
1
+ // Copyright 2024 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+ import * as Platform from '../../../core/platform/platform.js';
5
+ import * as Helpers from '../helpers/helpers.js';
6
+ import * as Types from '../types/types.js';
7
+ import { data as networkData } from './NetworkRequestsHandler.js';
8
+ const serverTimings = [];
9
+ let handlerState = 1 /* HandlerState.UNINITIALIZED */;
10
+ export function reset() {
11
+ serverTimings.length = 0;
12
+ handlerState = 1 /* HandlerState.UNINITIALIZED */;
13
+ }
14
+ export function initialize() {
15
+ handlerState = 2 /* HandlerState.INITIALIZED */;
16
+ }
17
+ export function handleEvent(_event) {
18
+ // Implementation not needed because data is sourced from NetworkRequestsHandler
19
+ }
20
+ export async function finalize() {
21
+ if (handlerState !== 2 /* HandlerState.INITIALIZED */) {
22
+ throw new Error('Server Timings handler is not initialized');
23
+ }
24
+ extractServerTimings();
25
+ Helpers.Trace.sortTraceEventsInPlace(serverTimings);
26
+ handlerState = 3 /* HandlerState.FINALIZED */;
27
+ }
28
+ const RESPONSE_START_METRIC_NAME = 'response-start';
29
+ const RESPONSE_END_METRIC_NAME = 'response-end';
30
+ /**
31
+ * Creates synthetic trace events based on server timings in the
32
+ * `Server-Timing` response header. A non-standard `start` param is
33
+ * expected on each metric that contains the start time of the timing
34
+ * based on the server clock.
35
+ *
36
+ * In order to estimate the offset between the server and client clocks,
37
+ * we look for the non-standard `response-start` and `response-end`
38
+ * metrics in the response header, which contain the start and end
39
+ * timestamps of the network request processing in the server. We
40
+ * compare these with the times the request was sent and received in the
41
+ * client to estimate the offset between the client and the server
42
+ * clocks.
43
+ *
44
+ * With this offset estimation at hand, we can map timestamps from the
45
+ * server clock to the tracing clock and locate the timings in the
46
+ * performance timeline.
47
+ */
48
+ function extractServerTimings() {
49
+ for (const networkEvent of networkData().byTime) {
50
+ let timingsInRequest = null;
51
+ for (const header of networkEvent.args.data.responseHeaders) {
52
+ const headerName = header.name.toLocaleLowerCase();
53
+ // Some popular hosting providers like vercel or render get rid of
54
+ // Server-Timing headers added by users, so as a workaround we
55
+ // also support server timing headers with the `-test` suffix
56
+ // while this feature is experimental, to enable easier trials.
57
+ if (headerName === 'server-timing' || headerName === 'server-timing-test') {
58
+ header.name = 'server-timing';
59
+ timingsInRequest = Platform.ServerTiming.ServerTiming.parseHeaders([header]);
60
+ continue;
61
+ }
62
+ }
63
+ const serverStart = timingsInRequest?.find(timing => timing.metric === RESPONSE_START_METRIC_NAME)?.start;
64
+ const serverEnd = timingsInRequest?.find(timing => timing.metric === RESPONSE_END_METRIC_NAME)?.start;
65
+ if (!serverStart || !serverEnd || !timingsInRequest) {
66
+ continue;
67
+ }
68
+ const serverStartInMicro = serverStart * 1_000;
69
+ const serverEndInMicro = serverEnd * 1_000;
70
+ serverTimings.push(...createSyntheticServerTiming(networkEvent, serverStartInMicro, serverEndInMicro, timingsInRequest));
71
+ }
72
+ }
73
+ function createSyntheticServerTiming(request, serverStart, serverEnd, timingsInRequest) {
74
+ const clientStart = request.args.data.syntheticData.sendStartTime;
75
+ const clientEndTime = request.args.data.syntheticData.sendStartTime + request.args.data.syntheticData.waiting;
76
+ const offset = Types.Timing.MicroSeconds((serverStart - clientStart + serverEnd - clientEndTime) / 2);
77
+ const convertedServerTimings = [];
78
+ for (const timing of timingsInRequest) {
79
+ if (timing.metric === RESPONSE_START_METRIC_NAME || timing.metric === RESPONSE_END_METRIC_NAME) {
80
+ continue;
81
+ }
82
+ if (timing.start === null) {
83
+ continue;
84
+ }
85
+ const convertedTimestamp = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.start)) - offset;
86
+ const parsedUrl = new URL(request.args.data.url);
87
+ const origin = parsedUrl.origin;
88
+ const serverTiming = Helpers.SyntheticEvents.SyntheticEventsManager.registerServerTiming({
89
+ rawSourceEvent: request.rawSourceEvent,
90
+ name: timing.metric,
91
+ ph: "X" /* Types.Events.Phase.COMPLETE */,
92
+ pid: Types.Events.ProcessID(0),
93
+ tid: Types.Events.ThreadID(0),
94
+ ts: Types.Timing.MicroSeconds(convertedTimestamp),
95
+ dur: Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.value)),
96
+ cat: 'devtools.server-timing',
97
+ args: { data: { desc: timing.description || undefined, origin } },
98
+ });
99
+ if (!request.args.data.syntheticServerTimings) {
100
+ request.args.data.syntheticServerTimings = [];
101
+ }
102
+ request.args.data.syntheticServerTimings.push(serverTiming);
103
+ convertedServerTimings.push(serverTiming);
104
+ }
105
+ return convertedServerTimings;
106
+ }
107
+ export function data() {
108
+ if (handlerState !== 3 /* HandlerState.FINALIZED */) {
109
+ throw new Error('Server Timing handler is not finalized');
110
+ }
111
+ return {
112
+ serverTimings,
113
+ };
114
+ }
115
+ export function deps() {
116
+ return ['NetworkRequests'];
117
+ }
118
+ //# sourceMappingURL=ServerTimingsHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServerTimingsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ServerTimingsHandler.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 * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as networkData} from './NetworkRequestsHandler.js';\nimport {type HandlerName, HandlerState} from './types.js';\n\nconst serverTimings: Types.Events.SyntheticServerTiming[] = [];\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n serverTimings.length = 0;\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(_event: Types.Events.Event): void {\n // Implementation not needed because data is sourced from NetworkRequestsHandler\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Server Timings handler is not initialized');\n }\n extractServerTimings();\n Helpers.Trace.sortTraceEventsInPlace(serverTimings);\n handlerState = HandlerState.FINALIZED;\n}\n\nconst RESPONSE_START_METRIC_NAME = 'response-start';\nconst RESPONSE_END_METRIC_NAME = 'response-end';\n\n/**\n * Creates synthetic trace events based on server timings in the\n * `Server-Timing` response header. A non-standard `start` param is\n * expected on each metric that contains the start time of the timing\n * based on the server clock.\n *\n * In order to estimate the offset between the server and client clocks,\n * we look for the non-standard `response-start` and `response-end`\n * metrics in the response header, which contain the start and end\n * timestamps of the network request processing in the server. We\n * compare these with the times the request was sent and received in the\n * client to estimate the offset between the client and the server\n * clocks.\n *\n * With this offset estimation at hand, we can map timestamps from the\n * server clock to the tracing clock and locate the timings in the\n * performance timeline.\n */\nfunction extractServerTimings(): void {\n for (const networkEvent of networkData().byTime) {\n let timingsInRequest: Platform.ServerTiming.ServerTiming[]|null = null;\n for (const header of networkEvent.args.data.responseHeaders) {\n const headerName = header.name.toLocaleLowerCase();\n // Some popular hosting providers like vercel or render get rid of\n // Server-Timing headers added by users, so as a workaround we\n // also support server timing headers with the `-test` suffix\n // while this feature is experimental, to enable easier trials.\n if (headerName === 'server-timing' || headerName === 'server-timing-test') {\n header.name = 'server-timing';\n timingsInRequest = Platform.ServerTiming.ServerTiming.parseHeaders([header]);\n continue;\n }\n }\n const serverStart = timingsInRequest?.find(timing => timing.metric === RESPONSE_START_METRIC_NAME)?.start;\n const serverEnd = timingsInRequest?.find(timing => timing.metric === RESPONSE_END_METRIC_NAME)?.start;\n if (!serverStart || !serverEnd || !timingsInRequest) {\n continue;\n }\n\n const serverStartInMicro = serverStart * 1_000;\n const serverEndInMicro = serverEnd * 1_000;\n serverTimings.push(\n ...createSyntheticServerTiming(networkEvent, serverStartInMicro, serverEndInMicro, timingsInRequest));\n }\n}\nfunction createSyntheticServerTiming(\n request: Types.Events.SyntheticNetworkRequest, serverStart: number, serverEnd: number,\n timingsInRequest: Platform.ServerTiming.ServerTiming[]): Types.Events.SyntheticServerTiming[] {\n const clientStart = request.args.data.syntheticData.sendStartTime;\n const clientEndTime = request.args.data.syntheticData.sendStartTime + request.args.data.syntheticData.waiting;\n const offset = Types.Timing.MicroSeconds((serverStart - clientStart + serverEnd - clientEndTime) / 2);\n const convertedServerTimings: Types.Events.SyntheticServerTiming[] = [];\n for (const timing of timingsInRequest) {\n if (timing.metric === RESPONSE_START_METRIC_NAME || timing.metric === RESPONSE_END_METRIC_NAME) {\n continue;\n }\n if (timing.start === null) {\n continue;\n }\n const convertedTimestamp =\n Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.start)) - offset;\n const parsedUrl = new URL(request.args.data.url);\n const origin = parsedUrl.origin;\n\n const serverTiming = Helpers.SyntheticEvents.SyntheticEventsManager.registerServerTiming({\n rawSourceEvent: request.rawSourceEvent,\n name: timing.metric,\n ph: Types.Events.Phase.COMPLETE,\n pid: Types.Events.ProcessID(0),\n tid: Types.Events.ThreadID(0),\n ts: Types.Timing.MicroSeconds(convertedTimestamp),\n dur: Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.value)),\n cat: 'devtools.server-timing',\n args: {data: {desc: timing.description || undefined, origin}},\n });\n\n if (!request.args.data.syntheticServerTimings) {\n request.args.data.syntheticServerTimings = [];\n }\n request.args.data.syntheticServerTimings.push(serverTiming);\n convertedServerTimings.push(serverTiming);\n }\n return convertedServerTimings;\n}\n\nexport function data(): {serverTimings: Types.Events.SyntheticServerTiming[]} {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Server Timing handler is not finalized');\n }\n\n return {\n serverTimings,\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['NetworkRequests'];\n}\n"]}
@@ -1,17 +1,17 @@
1
1
  import type * as Helpers from '../helpers/helpers.js';
2
2
  import type * as Types from '../types/types.js';
3
- import { type AuctionWorkletsData } from './AuctionWorkletsHandler.js';
3
+ import type { AuctionWorkletsData } from './AuctionWorkletsHandler.js';
4
4
  import type * as Renderer from './RendererHandler.js';
5
- import { type TraceParseData } from './types.js';
5
+ import type { ParsedTrace } from './types.js';
6
6
  export interface ThreadData {
7
- pid: Types.TraceEvents.ProcessID;
8
- tid: Types.TraceEvents.ThreadID;
9
- entries: readonly Types.TraceEvents.TraceEventData[];
7
+ pid: Types.Events.ProcessID;
8
+ tid: Types.Events.ThreadID;
9
+ entries: readonly Types.Events.Event[];
10
10
  processIsOnMainFrame: boolean;
11
11
  tree: Helpers.TreeHelpers.TraceEntryTree;
12
12
  type: ThreadType;
13
13
  name: string | null;
14
- entryToNode: Map<Types.TraceEvents.TraceEventData, Helpers.TreeHelpers.TraceEntryNode>;
14
+ entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;
15
15
  }
16
16
  export declare const enum ThreadType {
17
17
  MAIN_THREAD = "MAIN_THREAD",
@@ -30,4 +30,4 @@ export declare function threadsInRenderer(rendererData: Renderer.RendererHandler
30
30
  * can use this helper to iterate over threads in confidence that it will work
31
31
  * for both trace types.
32
32
  */
33
- export declare function threadsInTrace(traceParseData: TraceParseData): readonly ThreadData[];
33
+ export declare function threadsInTrace(parsedTrace: ParsedTrace): readonly ThreadData[];
@@ -56,18 +56,18 @@ export function threadsInRenderer(rendererData, auctionWorkletsData) {
56
56
  * can use this helper to iterate over threads in confidence that it will work
57
57
  * for both trace types.
58
58
  */
59
- export function threadsInTrace(traceParseData) {
59
+ export function threadsInTrace(parsedTrace) {
60
60
  // If we have Renderer threads, we prefer to use those. In the event that a
61
61
  // trace is a CPU Profile trace, we will never have Renderer threads, so we
62
62
  // know if there are no Renderer threads that we can fallback to using the
63
63
  // data from the SamplesHandler.
64
- const threadsFromRenderer = threadsInRenderer(traceParseData.Renderer, traceParseData.AuctionWorklets);
64
+ const threadsFromRenderer = threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets);
65
65
  if (threadsFromRenderer.length) {
66
66
  return threadsFromRenderer;
67
67
  }
68
68
  const foundThreads = [];
69
- if (traceParseData.Samples.profilesInProcess.size) {
70
- for (const [pid, process] of traceParseData.Samples.profilesInProcess) {
69
+ if (parsedTrace.Samples.profilesInProcess.size) {
70
+ for (const [pid, process] of parsedTrace.Samples.profilesInProcess) {
71
71
  for (const [tid, thread] of process) {
72
72
  if (!thread.profileTree) {
73
73
  // Drop threads where we could not create the tree; this indicates
@@ -85,7 +85,7 @@ export function threadsInTrace(traceParseData) {
85
85
  processIsOnMainFrame: false,
86
86
  tree: thread.profileTree,
87
87
  type: "CPU_PROFILE" /* ThreadType.CPU_PROFILE */,
88
- entryToNode: traceParseData.Samples.entryToNode,
88
+ entryToNode: parsedTrace.Samples.entryToNode,
89
89
  });
90
90
  }
91
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Threads.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.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 type * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type AuctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport type * as Renderer from './RendererHandler.js';\nimport {type TraceParseData} from './types.js';\n\nexport interface ThreadData {\n pid: Types.TraceEvents.ProcessID;\n tid: Types.TraceEvents.ThreadID;\n entries: readonly Types.TraceEvents.TraceEventData[];\n processIsOnMainFrame: boolean;\n tree: Helpers.TreeHelpers.TraceEntryTree;\n type: ThreadType;\n name: string|null;\n entryToNode: Map<Types.TraceEvents.TraceEventData, Helpers.TreeHelpers.TraceEntryNode>;\n}\n\nexport const enum ThreadType {\n MAIN_THREAD = 'MAIN_THREAD',\n WORKER = 'WORKER',\n RASTERIZER = 'RASTERIZER',\n AUCTION_WORKLET = 'AUCTION_WORKLET',\n OTHER = 'OTHER',\n CPU_PROFILE = 'CPU_PROFILE',\n THREAD_POOL = 'THREAD_POOL',\n}\n\nfunction getThreadTypeForRendererThread(\n pid: Types.TraceEvents.ProcessID, thread: Renderer.RendererThread,\n auctionWorkletsData: AuctionWorkletsData): ThreadType {\n let threadType = ThreadType.OTHER;\n if (thread.name === 'CrRendererMain') {\n threadType = ThreadType.MAIN_THREAD;\n } else if (thread.name === 'DedicatedWorker thread') {\n threadType = ThreadType.WORKER;\n } else if (thread.name?.startsWith('CompositorTileWorker')) {\n threadType = ThreadType.RASTERIZER;\n } else if (auctionWorkletsData.worklets.has(pid)) {\n threadType = ThreadType.AUCTION_WORKLET;\n } else if (thread.name?.startsWith('ThreadPool')) {\n // TODO(paulirish): perhaps exclude ThreadPoolServiceThread entirely\n threadType = ThreadType.THREAD_POOL;\n }\n return threadType;\n}\n\nexport function threadsInRenderer(\n rendererData: Renderer.RendererHandlerData, auctionWorkletsData: AuctionWorkletsData): readonly ThreadData[] {\n const foundThreads: ThreadData[] = [];\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n if (rendererData.processes.size) {\n for (const [pid, process] of rendererData.processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.tree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n const threadType = getThreadTypeForRendererThread(pid, thread, auctionWorkletsData);\n foundThreads.push({\n name: thread.name,\n pid,\n tid,\n processIsOnMainFrame: process.isOnMainFrame,\n entries: thread.entries,\n tree: thread.tree,\n type: threadType,\n entryToNode: rendererData.entryToNode,\n });\n }\n }\n }\n return foundThreads;\n}\n\n/**\n * Given trace parsed data, this helper will return a high level array of\n * ThreadData. This is useful because it allows you to get a list of threads\n * regardless of if the trace is a CPU Profile or a Tracing profile. Thus you\n * can use this helper to iterate over threads in confidence that it will work\n * for both trace types.\n */\nexport function threadsInTrace(traceParseData: TraceParseData): readonly ThreadData[] {\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n const threadsFromRenderer = threadsInRenderer(traceParseData.Renderer, traceParseData.AuctionWorklets);\n if (threadsFromRenderer.length) {\n return threadsFromRenderer;\n }\n\n const foundThreads: ThreadData[] = [];\n if (traceParseData.Samples.profilesInProcess.size) {\n for (const [pid, process] of traceParseData.Samples.profilesInProcess) {\n for (const [tid, thread] of process) {\n if (!thread.profileTree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n\n foundThreads.push({\n pid,\n tid,\n // CPU Profile threads do not have a name.\n name: null,\n entries: thread.profileCalls,\n // There is no concept of a \"Main Frame\" in a CPU profile.\n processIsOnMainFrame: false,\n tree: thread.profileTree,\n type: ThreadType.CPU_PROFILE,\n entryToNode: traceParseData.Samples.entryToNode,\n });\n }\n }\n }\n\n return foundThreads;\n}\n"]}
1
+ {"version":3,"file":"Threads.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.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 type * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport type {AuctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport type * as Renderer from './RendererHandler.js';\nimport type {ParsedTrace} from './types.js';\n\nexport interface ThreadData {\n pid: Types.Events.ProcessID;\n tid: Types.Events.ThreadID;\n entries: readonly Types.Events.Event[];\n processIsOnMainFrame: boolean;\n tree: Helpers.TreeHelpers.TraceEntryTree;\n type: ThreadType;\n name: string|null;\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;\n}\n\nexport const enum ThreadType {\n MAIN_THREAD = 'MAIN_THREAD',\n WORKER = 'WORKER',\n RASTERIZER = 'RASTERIZER',\n AUCTION_WORKLET = 'AUCTION_WORKLET',\n OTHER = 'OTHER',\n CPU_PROFILE = 'CPU_PROFILE',\n THREAD_POOL = 'THREAD_POOL',\n}\n\nfunction getThreadTypeForRendererThread(\n pid: Types.Events.ProcessID, thread: Renderer.RendererThread,\n auctionWorkletsData: AuctionWorkletsData): ThreadType {\n let threadType = ThreadType.OTHER;\n if (thread.name === 'CrRendererMain') {\n threadType = ThreadType.MAIN_THREAD;\n } else if (thread.name === 'DedicatedWorker thread') {\n threadType = ThreadType.WORKER;\n } else if (thread.name?.startsWith('CompositorTileWorker')) {\n threadType = ThreadType.RASTERIZER;\n } else if (auctionWorkletsData.worklets.has(pid)) {\n threadType = ThreadType.AUCTION_WORKLET;\n } else if (thread.name?.startsWith('ThreadPool')) {\n // TODO(paulirish): perhaps exclude ThreadPoolServiceThread entirely\n threadType = ThreadType.THREAD_POOL;\n }\n return threadType;\n}\n\nexport function threadsInRenderer(\n rendererData: Renderer.RendererHandlerData, auctionWorkletsData: AuctionWorkletsData): readonly ThreadData[] {\n const foundThreads: ThreadData[] = [];\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n if (rendererData.processes.size) {\n for (const [pid, process] of rendererData.processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.tree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n const threadType = getThreadTypeForRendererThread(pid, thread, auctionWorkletsData);\n foundThreads.push({\n name: thread.name,\n pid,\n tid,\n processIsOnMainFrame: process.isOnMainFrame,\n entries: thread.entries,\n tree: thread.tree,\n type: threadType,\n entryToNode: rendererData.entryToNode,\n });\n }\n }\n }\n return foundThreads;\n}\n\n/**\n * Given trace parsed data, this helper will return a high level array of\n * ThreadData. This is useful because it allows you to get a list of threads\n * regardless of if the trace is a CPU Profile or a Tracing profile. Thus you\n * can use this helper to iterate over threads in confidence that it will work\n * for both trace types.\n */\nexport function threadsInTrace(parsedTrace: ParsedTrace): readonly ThreadData[] {\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n const threadsFromRenderer = threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets);\n if (threadsFromRenderer.length) {\n return threadsFromRenderer;\n }\n\n const foundThreads: ThreadData[] = [];\n if (parsedTrace.Samples.profilesInProcess.size) {\n for (const [pid, process] of parsedTrace.Samples.profilesInProcess) {\n for (const [tid, thread] of process) {\n if (!thread.profileTree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n\n foundThreads.push({\n pid,\n tid,\n // CPU Profile threads do not have a name.\n name: null,\n entries: thread.profileCalls,\n // There is no concept of a \"Main Frame\" in a CPU profile.\n processIsOnMainFrame: false,\n tree: thread.profileTree,\n type: ThreadType.CPU_PROFILE,\n entryToNode: parsedTrace.Samples.entryToNode,\n });\n }\n }\n }\n\n return foundThreads;\n}\n"]}
@@ -1,16 +1,18 @@
1
1
  import * as Types from '../types/types.js';
2
2
  import { ScoreClassification } from './PageLoadMetricsHandler.js';
3
- import { type TraceEventHandlerName } from './types.js';
3
+ import { type HandlerName } from './types.js';
4
4
  export declare const LONG_INTERACTION_THRESHOLD: Types.Timing.MicroSeconds;
5
5
  export interface UserInteractionsData {
6
6
  /** All the user events we found in the trace */
7
- allEvents: readonly Types.TraceEvents.TraceEventEventTiming[];
7
+ allEvents: readonly Types.Events.EventTiming[];
8
8
  /** All the BeginCommitCompositorFrame events we found in the trace */
9
- beginCommitCompositorFrameEvents: readonly Types.TraceEvents.TraceEventBeginCommitCompositorFrame[];
9
+ beginCommitCompositorFrameEvents: readonly Types.Events.BeginCommitCompositorFrame[];
10
+ /** All the ParseMetaViewport events we found in the trace */
11
+ parseMetaViewportEvents: readonly Types.Events.ParseMetaViewport[];
10
12
  /** All the interaction events we found in the trace that had an
11
13
  * interactionId and a duration > 0
12
14
  **/
13
- interactionEvents: readonly Types.TraceEvents.SyntheticInteractionPair[];
15
+ interactionEvents: readonly Types.Events.SyntheticInteractionPair[];
14
16
  /** If the user rapidly generates interaction events (think typing into a
15
17
  * text box), in the UI we only really want to show the user the longest
16
18
  * interaction in that set.
@@ -25,14 +27,14 @@ export interface UserInteractionsData {
25
27
  * all the interaction events filtered down, removing any nested interactions
26
28
  * entirely.
27
29
  **/
28
- interactionEventsWithNoNesting: readonly Types.TraceEvents.SyntheticInteractionPair[];
29
- longestInteractionEvent: Readonly<Types.TraceEvents.SyntheticInteractionPair> | null;
30
- interactionsOverThreshold: Readonly<Set<Types.TraceEvents.SyntheticInteractionPair>>;
30
+ interactionEventsWithNoNesting: readonly Types.Events.SyntheticInteractionPair[];
31
+ longestInteractionEvent: Readonly<Types.Events.SyntheticInteractionPair> | null;
32
+ interactionsOverThreshold: Readonly<Set<Types.Events.SyntheticInteractionPair>>;
31
33
  }
32
34
  export declare function reset(): void;
33
- export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
35
+ export declare function handleEvent(event: Types.Events.Event): void;
34
36
  export type InteractionCategory = 'KEYBOARD' | 'POINTER' | 'OTHER';
35
- export declare function categoryOfInteraction(interaction: Types.TraceEvents.SyntheticInteractionPair): InteractionCategory;
37
+ export declare function categoryOfInteraction(interaction: Types.Events.SyntheticInteractionPair): InteractionCategory;
36
38
  /**
37
39
  * We define a set of interactions as nested where:
38
40
  * 1. Their end times align.
@@ -56,10 +58,10 @@ export declare function categoryOfInteraction(interaction: Types.TraceEvents.Syn
56
58
  * ====C=[pointerdown]=
57
59
  * =D=[pointerup]=
58
60
  **/
59
- export declare function removeNestedInteractions(interactions: readonly Types.TraceEvents.SyntheticInteractionPair[]): readonly Types.TraceEvents.SyntheticInteractionPair[];
61
+ export declare function removeNestedInteractions(interactions: readonly Types.Events.SyntheticInteractionPair[]): readonly Types.Events.SyntheticInteractionPair[];
60
62
  export declare function finalize(): Promise<void>;
61
63
  export declare function data(): UserInteractionsData;
62
- export declare function deps(): TraceEventHandlerName[];
64
+ export declare function deps(): HandlerName[];
63
65
  /**
64
66
  * Classifications sourced from
65
67
  * https://web.dev/articles/inp#good-score