@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.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 Helpers from '../helpers/helpers.js';\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightResult, InsightSetContext, RequiredData} from './types.js';\n\nexport function deps(): ['SelectorStats'] {\n return ['SelectorStats'];\n}\n\nexport type SlowCSSSelectorInsightResult = InsightResult<{\n totalElapsedMs: Types.Timing.MilliSeconds,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topElapsedMs: Types.Events.SelectorTiming[],\n topMatchAttempts: Types.Events.SelectorTiming[],\n}>;\n\nfunction aggregateSelectorStats(\n data: Map<Types.Events.UpdateLayoutTree, {\n timings: Types.Events.SelectorTiming[],\n }>,\n context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map<String, SelectorTiming>();\n\n for (const [event, value] of data) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): SlowCSSSelectorInsightResult {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent, context);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n // sort by elapsed time\n const sortByElapsedMs = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];\n });\n\n // sort by match attempts\n const sortByMatchAttempts = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];\n });\n\n return {\n // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\n totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topElapsedMs: sortByElapsedMs.slice(0, 3),\n topMatchAttempts: sortByMatchAttempts.slice(0, 3),\n };\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';
2
+ import * as Types from '../types/types.js';
3
+ import type { InsightResult, InsightSetContext, RequiredData } from './types.js';
4
+ export declare function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];
5
+ export type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];
6
+ export interface Summary {
7
+ transferSize: number;
8
+ mainThreadTime: Types.Timing.MicroSeconds;
9
+ }
10
+ export type ThirdPartyWebInsightResult = InsightResult<{
11
+ entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Entity>;
12
+ requestsByEntity: Map<Entity, Types.Events.SyntheticNetworkRequest[]>;
13
+ summaryByRequest: Map<Types.Events.SyntheticNetworkRequest, Summary>;
14
+ summaryByEntity: Map<Entity, Summary>;
15
+ /** The entity for this navigation's URL. Any other entity is from a third party. */
16
+ firstPartyEntity?: Entity;
17
+ }>;
18
+ export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartyWebInsightResult;
@@ -0,0 +1,174 @@
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 ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';
5
+ import * as Extras from '../extras/extras.js';
6
+ import * as Helpers from '../helpers/helpers.js';
7
+ import * as Types from '../types/types.js';
8
+ export function deps() {
9
+ return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];
10
+ }
11
+ /**
12
+ * Returns the origin portion of a Chrome extension URL.
13
+ */
14
+ function getChromeExtensionOrigin(url) {
15
+ return url.protocol + '//' + url.host;
16
+ }
17
+ function makeUpChromeExtensionEntity(entityCache, url, extensionName) {
18
+ const parsedUrl = new URL(url);
19
+ const origin = getChromeExtensionOrigin(parsedUrl);
20
+ const host = new URL(origin).host;
21
+ const name = extensionName || host;
22
+ const cachedEntity = entityCache.get(origin);
23
+ if (cachedEntity) {
24
+ return cachedEntity;
25
+ }
26
+ const chromeExtensionEntity = {
27
+ name,
28
+ company: name,
29
+ category: 'Chrome Extension',
30
+ homepage: 'https://chromewebstore.google.com/detail/' + host,
31
+ categories: [],
32
+ domains: [],
33
+ averageExecutionTime: 0,
34
+ totalExecutionTime: 0,
35
+ totalOccurrences: 0,
36
+ };
37
+ entityCache.set(origin, chromeExtensionEntity);
38
+ return chromeExtensionEntity;
39
+ }
40
+ function makeUpEntity(entityCache, url) {
41
+ if (url.startsWith('chrome-extension:')) {
42
+ return makeUpChromeExtensionEntity(entityCache, url);
43
+ }
44
+ // Make up an entity only for valid http/https URLs.
45
+ if (!url.startsWith('http')) {
46
+ return;
47
+ }
48
+ // NOTE: Lighthouse uses a tld database to determine the root domain, but here
49
+ // we are using third party web's database. Doesn't really work for the case of classifying
50
+ // domains 3pweb doesn't know about, so it will just give us a guess.
51
+ const rootDomain = ThirdPartyWeb.ThirdPartyWeb.getRootDomain(url);
52
+ if (!rootDomain) {
53
+ return;
54
+ }
55
+ if (entityCache.has(rootDomain)) {
56
+ return entityCache.get(rootDomain);
57
+ }
58
+ const unrecognizedEntity = {
59
+ name: rootDomain,
60
+ company: rootDomain,
61
+ category: '',
62
+ categories: [],
63
+ domains: [rootDomain],
64
+ averageExecutionTime: 0,
65
+ totalExecutionTime: 0,
66
+ totalOccurrences: 0,
67
+ isUnrecognized: true,
68
+ };
69
+ entityCache.set(rootDomain, unrecognizedEntity);
70
+ return unrecognizedEntity;
71
+ }
72
+ function getSelfTimeByUrl(parsedTrace, context) {
73
+ const selfTimeByUrl = new Map();
74
+ for (const process of parsedTrace.Renderer.processes.values()) {
75
+ if (!process.isOnMainFrame) {
76
+ continue;
77
+ }
78
+ for (const thread of process.threads.values()) {
79
+ if (thread.name === 'CrRendererMain') {
80
+ if (!thread.tree) {
81
+ break;
82
+ }
83
+ for (const event of thread.entries) {
84
+ if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {
85
+ continue;
86
+ }
87
+ const node = parsedTrace.Renderer.entryToNode.get(event);
88
+ if (!node || !node.selfTime) {
89
+ continue;
90
+ }
91
+ const url = Extras.URLForEntry.getNonResolved(parsedTrace, event);
92
+ if (!url) {
93
+ continue;
94
+ }
95
+ selfTimeByUrl.set(url, node.selfTime + (selfTimeByUrl.get(url) ?? 0));
96
+ }
97
+ }
98
+ }
99
+ }
100
+ return selfTimeByUrl;
101
+ }
102
+ function getSummaries(requests, entityByRequest, selfTimeByUrl) {
103
+ const byRequest = new Map();
104
+ const byEntity = new Map();
105
+ const defaultSummary = { transferSize: 0, mainThreadTime: Types.Timing.MicroSeconds(0) };
106
+ for (const request of requests) {
107
+ const urlSummary = byRequest.get(request) || { ...defaultSummary };
108
+ urlSummary.transferSize += request.args.data.encodedDataLength;
109
+ urlSummary.mainThreadTime =
110
+ Types.Timing.MicroSeconds(urlSummary.mainThreadTime + (selfTimeByUrl.get(request.args.data.url) ?? 0));
111
+ byRequest.set(request, urlSummary);
112
+ }
113
+ // Map each request's stat to a particular entity.
114
+ const requestsByEntity = new Map();
115
+ for (const [request, requestSummary] of byRequest.entries()) {
116
+ const entity = entityByRequest.get(request);
117
+ if (!entity) {
118
+ byRequest.delete(request);
119
+ continue;
120
+ }
121
+ const entitySummary = byEntity.get(entity) || { ...defaultSummary };
122
+ entitySummary.transferSize += requestSummary.transferSize;
123
+ entitySummary.mainThreadTime =
124
+ Types.Timing.MicroSeconds(entitySummary.mainThreadTime + requestSummary.mainThreadTime);
125
+ byEntity.set(entity, entitySummary);
126
+ const entityRequests = requestsByEntity.get(entity) || [];
127
+ entityRequests.push(request);
128
+ requestsByEntity.set(entity, entityRequests);
129
+ }
130
+ return { byEntity, byRequest, requestsByEntity };
131
+ }
132
+ function getRelatedEvents(summaries, firstPartyEntity) {
133
+ const events = [];
134
+ for (const [entity, requests] of summaries.requestsByEntity.entries()) {
135
+ if (entity !== firstPartyEntity) {
136
+ events.push(...requests);
137
+ }
138
+ }
139
+ return events;
140
+ }
141
+ export function generateInsight(parsedTrace, context) {
142
+ const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {
143
+ if (!context.navigation) {
144
+ return false;
145
+ }
146
+ if (event.args.data.frame !== context.frameId) {
147
+ return false;
148
+ }
149
+ return Helpers.Timing.eventIsInBounds(event, context.bounds);
150
+ });
151
+ const entityByRequest = new Map();
152
+ const madeUpEntityCache = new Map();
153
+ for (const request of networkRequests) {
154
+ const url = request.args.data.url;
155
+ const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url) ?? makeUpEntity(madeUpEntityCache, url);
156
+ if (entity) {
157
+ entityByRequest.set(request, entity);
158
+ }
159
+ }
160
+ const selfTimeByUrl = getSelfTimeByUrl(parsedTrace, context);
161
+ // TODO(crbug.com/352244718): re-work to still collect main thread activity if no request is present
162
+ const summaries = getSummaries(networkRequests, entityByRequest, selfTimeByUrl);
163
+ const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;
164
+ const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || makeUpEntity(madeUpEntityCache, firstPartyUrl);
165
+ return {
166
+ relatedEvents: getRelatedEvents(summaries, firstPartyEntity),
167
+ entityByRequest,
168
+ requestsByEntity: summaries.requestsByEntity,
169
+ summaryByRequest: summaries.byRequest,
170
+ summaryByEntity: summaries.byEntity,
171
+ firstPartyEntity,
172
+ };
173
+ }
174
+ //# sourceMappingURL=ThirdPartyWeb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThirdPartyWeb.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,yDAAyD,CAAC;AACzF,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAClE,CAAC;AAkBD;;GAEG;AACH,SAAS,wBAAwB,CAAC,GAAQ;IACxC,OAAO,GAAG,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,SAAS,2BAA2B,CAAC,WAAgC,EAAE,GAAW,EAAE,aAAsB;IACxG,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;IAClC,MAAM,IAAI,GAAG,aAAa,IAAI,IAAI,CAAC;IAEnC,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,qBAAqB,GAAG;QAC5B,IAAI;QACJ,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,kBAAkB;QAC5B,QAAQ,EAAE,2CAA2C,GAAG,IAAI;QAC5D,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,oBAAoB,EAAE,CAAC;QACvB,kBAAkB,EAAE,CAAC;QACrB,gBAAgB,EAAE,CAAC;KACpB,CAAC;IAEF,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC/C,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAED,SAAS,YAAY,CAAC,WAAgC,EAAE,GAAW;IACjE,IAAI,GAAG,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACxC,OAAO,2BAA2B,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC;IAED,oDAAoD;IACpD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,8EAA8E;IAC9E,2FAA2F;IAC3F,qEAAqE;IACrE,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,kBAAkB,GAAG;QACzB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,CAAC,UAAU,CAAC;QACrB,oBAAoB,EAAE,CAAC;QACvB,kBAAkB,EAAE,CAAC;QACrB,gBAAgB,EAAE,CAAC;QACnB,cAAc,EAAE,IAAI;KACrB,CAAC;IACF,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAChD,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAQD,SAAS,gBAAgB,CAAC,WAAsC,EAAE,OAA0B;IAC1F,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEhD,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC3B,SAAS;QACX,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;oBACjB,MAAM;gBACR,CAAC;gBAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC3D,SAAS;oBACX,CAAC;oBAED,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBACzD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAC5B,SAAS;oBACX,CAAC;oBAED,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,WAAyC,EAAE,KAAK,CAAC,CAAC;oBAChG,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,SAAS;oBACX,CAAC;oBAED,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,YAAY,CACjB,QAAgD,EAChD,eAAkE,EAClE,aAAkC;IACpC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiD,CAAC;IAC3E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC5C,MAAM,cAAc,GAAY,EAAC,YAAY,EAAE,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,CAAC;IAEhG,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAC,GAAG,cAAc,EAAC,CAAC;QACjE,UAAU,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC;QAC/D,UAAU,CAAC,cAAc;YACrB,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3G,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,kDAAkD;IAClD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkD,CAAC;IACnF,KAAK,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAC,GAAG,cAAc,EAAC,CAAC;QAClE,aAAa,CAAC,YAAY,IAAI,cAAc,CAAC,YAAY,CAAC;QAC1D,aAAa,CAAC,cAAc;YACxB,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,cAAc,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;QAC5F,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAEpC,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAC,CAAC;AACjD,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAsB,EAAE,gBAAkC;IAClF,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QACtE,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACxE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,IAAI,GAAG,EAAgD,CAAC;IAChF,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpD,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAClC,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAClG,IAAI,MAAM,EAAE,CAAC;YACX,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC7D,oGAAoG;IACpG,MAAM,SAAS,GAAG,YAAY,CAAC,eAAe,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;IAEhF,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,iBAAiB,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;IACxG,MAAM,gBAAgB,GAClB,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAE3G,OAAO;QACL,aAAa,EAAE,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,CAAC;QAC5D,eAAe;QACf,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;QAC5C,gBAAgB,EAAE,SAAS,CAAC,SAAS;QACrC,eAAe,EAAE,SAAS,CAAC,QAAQ;QACnC,gBAAgB;KACjB,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 ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {InsightResult, InsightSetContext, RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\nexport interface Summary {\n transferSize: number;\n mainThreadTime: Types.Timing.MicroSeconds;\n}\n\nexport type ThirdPartyWebInsightResult = InsightResult<{\n entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Entity>,\n requestsByEntity: Map<Entity, Types.Events.SyntheticNetworkRequest[]>,\n summaryByRequest: Map<Types.Events.SyntheticNetworkRequest, Summary>,\n summaryByEntity: Map<Entity, Summary>,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Entity,\n}>;\n\n/**\n * Returns the origin portion of a Chrome extension URL.\n */\nfunction getChromeExtensionOrigin(url: URL): string {\n return url.protocol + '//' + url.host;\n}\n\nfunction makeUpChromeExtensionEntity(entityCache: Map<string, Entity>, url: string, extensionName?: string): Entity {\n const parsedUrl = new URL(url);\n const origin = getChromeExtensionOrigin(parsedUrl);\n const host = new URL(origin).host;\n const name = extensionName || host;\n\n const cachedEntity = entityCache.get(origin);\n if (cachedEntity) {\n return cachedEntity;\n }\n\n const chromeExtensionEntity = {\n name,\n company: name,\n category: 'Chrome Extension',\n homepage: 'https://chromewebstore.google.com/detail/' + host,\n categories: [],\n domains: [],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n };\n\n entityCache.set(origin, chromeExtensionEntity);\n return chromeExtensionEntity;\n}\n\nfunction makeUpEntity(entityCache: Map<string, Entity>, url: string): Entity|undefined {\n if (url.startsWith('chrome-extension:')) {\n return makeUpChromeExtensionEntity(entityCache, url);\n }\n\n // Make up an entity only for valid http/https URLs.\n if (!url.startsWith('http')) {\n return;\n }\n\n // NOTE: Lighthouse uses a tld database to determine the root domain, but here\n // we are using third party web's database. Doesn't really work for the case of classifying\n // domains 3pweb doesn't know about, so it will just give us a guess.\n const rootDomain = ThirdPartyWeb.ThirdPartyWeb.getRootDomain(url);\n if (!rootDomain) {\n return;\n }\n\n if (entityCache.has(rootDomain)) {\n return entityCache.get(rootDomain);\n }\n\n const unrecognizedEntity = {\n name: rootDomain,\n company: rootDomain,\n category: '',\n categories: [],\n domains: [rootDomain],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n isUnrecognized: true,\n };\n entityCache.set(rootDomain, unrecognizedEntity);\n return unrecognizedEntity;\n}\n\ninterface SummaryMaps {\n byEntity: Map<Entity, Summary>;\n byRequest: Map<Types.Events.SyntheticNetworkRequest, Summary>;\n requestsByEntity: Map<Entity, Types.Events.SyntheticNetworkRequest[]>;\n}\n\nfunction getSelfTimeByUrl(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): Map<string, number> {\n const selfTimeByUrl = new Map<string, number>();\n\n for (const process of parsedTrace.Renderer.processes.values()) {\n if (!process.isOnMainFrame) {\n continue;\n }\n\n for (const thread of process.threads.values()) {\n if (thread.name === 'CrRendererMain') {\n if (!thread.tree) {\n break;\n }\n\n for (const event of thread.entries) {\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\n const node = parsedTrace.Renderer.entryToNode.get(event);\n if (!node || !node.selfTime) {\n continue;\n }\n\n const url = Extras.URLForEntry.getNonResolved(parsedTrace as Handlers.Types.ParsedTrace, event);\n if (!url) {\n continue;\n }\n\n selfTimeByUrl.set(url, node.selfTime + (selfTimeByUrl.get(url) ?? 0));\n }\n }\n }\n }\n\n return selfTimeByUrl;\n}\n\nfunction getSummaries(\n requests: Types.Events.SyntheticNetworkRequest[],\n entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Entity>,\n selfTimeByUrl: Map<string, number>): SummaryMaps {\n const byRequest = new Map<Types.Events.SyntheticNetworkRequest, Summary>();\n const byEntity = new Map<Entity, Summary>();\n const defaultSummary: Summary = {transferSize: 0, mainThreadTime: Types.Timing.MicroSeconds(0)};\n\n for (const request of requests) {\n const urlSummary = byRequest.get(request) || {...defaultSummary};\n urlSummary.transferSize += request.args.data.encodedDataLength;\n urlSummary.mainThreadTime =\n Types.Timing.MicroSeconds(urlSummary.mainThreadTime + (selfTimeByUrl.get(request.args.data.url) ?? 0));\n byRequest.set(request, urlSummary);\n }\n\n // Map each request's stat to a particular entity.\n const requestsByEntity = new Map<Entity, Types.Events.SyntheticNetworkRequest[]>();\n for (const [request, requestSummary] of byRequest.entries()) {\n const entity = entityByRequest.get(request);\n if (!entity) {\n byRequest.delete(request);\n continue;\n }\n\n const entitySummary = byEntity.get(entity) || {...defaultSummary};\n entitySummary.transferSize += requestSummary.transferSize;\n entitySummary.mainThreadTime =\n Types.Timing.MicroSeconds(entitySummary.mainThreadTime + requestSummary.mainThreadTime);\n byEntity.set(entity, entitySummary);\n\n const entityRequests = requestsByEntity.get(entity) || [];\n entityRequests.push(request);\n requestsByEntity.set(entity, entityRequests);\n }\n\n return {byEntity, byRequest, requestsByEntity};\n}\n\nfunction getRelatedEvents(summaries: SummaryMaps, firstPartyEntity: Entity|undefined): Types.Events.Event[] {\n const events = [];\n\n for (const [entity, requests] of summaries.requestsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n events.push(...requests);\n }\n }\n\n return events;\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartyWebInsightResult {\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {\n if (!context.navigation) {\n return false;\n }\n\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n const entityByRequest = new Map<Types.Events.SyntheticNetworkRequest, Entity>();\n const madeUpEntityCache = new Map<string, Entity>();\n for (const request of networkRequests) {\n const url = request.args.data.url;\n const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url) ?? makeUpEntity(madeUpEntityCache, url);\n if (entity) {\n entityByRequest.set(request, entity);\n }\n }\n\n const selfTimeByUrl = getSelfTimeByUrl(parsedTrace, context);\n // TODO(crbug.com/352244718): re-work to still collect main thread activity if no request is present\n const summaries = getSummaries(networkRequests, entityByRequest, selfTimeByUrl);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity =\n ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return {\n relatedEvents: getRelatedEvents(summaries, firstPartyEntity),\n entityByRequest,\n requestsByEntity: summaries.requestsByEntity,\n summaryByRequest: summaries.byRequest,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n };\n}\n"]}
@@ -1,5 +1,8 @@
1
- import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js';
1
+ import type * as Types from '../types/types.js';
2
+ import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js';
2
3
  export declare function deps(): ['Meta', 'UserInteractions'];
3
- export declare function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext): InsightResult<{
4
+ export type ViewportInsightResult = InsightResult<{
4
5
  mobileOptimized: boolean | null;
6
+ viewportEvent?: Types.Events.ParseMetaViewport;
5
7
  }>;
8
+ export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightResult;
@@ -6,34 +6,39 @@ import { InsightWarning } from './types.js';
6
6
  export function deps() {
7
7
  return ['Meta', 'UserInteractions'];
8
8
  }
9
- export function generateInsight(traceParsedData, context) {
10
- const events = traceParsedData.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {
9
+ export function generateInsight(parsedTrace, context) {
10
+ const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {
11
11
  if (event.args.frame !== context.frameId) {
12
12
  return false;
13
13
  }
14
- const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);
15
- if (navigation?.args.data?.navigationId !== context.navigationId) {
16
- return false;
17
- }
18
- return true;
14
+ return Helpers.Timing.eventIsInBounds(event, context.bounds);
19
15
  });
20
- if (!events.length) {
16
+ if (!compositorEvents.length) {
21
17
  // Trace doesn't have the data we need.
22
18
  return {
23
19
  mobileOptimized: null,
24
20
  warnings: [InsightWarning.NO_LAYOUT],
25
21
  };
26
22
  }
23
+ const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {
24
+ if (event.args.data.frame !== context.frameId) {
25
+ return false;
26
+ }
27
+ return Helpers.Timing.eventIsInBounds(event, context.bounds);
28
+ });
27
29
  // Returns true only if all events are mobile optimized.
28
- for (const event of events) {
30
+ for (const event of compositorEvents) {
29
31
  if (!event.args.is_mobile_optimized) {
30
32
  return {
31
33
  mobileOptimized: false,
34
+ viewportEvent,
35
+ metricSavings: { INP: 300 },
32
36
  };
33
37
  }
34
38
  }
35
39
  return {
36
40
  mobileOptimized: true,
41
+ viewportEvent,
37
42
  };
38
43
  }
39
44
  //# sourceMappingURL=Viewport.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAqB,cAAc,EAAmD,MAAM,YAAY,CAAC;AAEhH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,eAA0C,EAAE,OAAiC;IAE3G,MAAM,MAAM,GAAG,eAAe,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QAC9F,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,IAAI,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACjE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,uCAAuC;QACvC,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO;gBACL,eAAe,EAAE,KAAK;aACvB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI;KACtB,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 Helpers from '../helpers/helpers.js';\n\nimport {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext):\n InsightResult<{mobileOptimized: boolean | null}> {\n const events = traceParsedData.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n if (navigation?.args.data?.navigationId !== context.navigationId) {\n return false;\n }\n\n return true;\n });\n\n if (!events.length) {\n // Trace doesn't have the data we need.\n return {\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n };\n }\n\n // Returns true only if all events are mobile optimized.\n for (const event of events) {\n if (!event.args.is_mobile_optimized) {\n return {\n mobileOptimized: false,\n };\n }\n }\n\n return {\n mobileOptimized: true,\n };\n}\n"]}
1
+ {"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAA6C,cAAc,EAAoB,MAAM,YAAY,CAAC;AAEzG,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO;gBACL,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAgC,EAAC;aACvD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,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 Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightResult = InsightResult<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightResult {\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return {\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n };\n }\n\n const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n return {\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.MilliSeconds},\n };\n }\n }\n\n return {\n mobileOptimized: true,\n viewportEvent,\n };\n}\n"]}
@@ -32,10 +32,13 @@
32
32
  "../../../../../../../front_end/models/trace/insights/Common.ts",
33
33
  "../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts",
34
34
  "../../../../../../../front_end/models/trace/insights/DocumentLatency.ts",
35
+ "../../../../../../../front_end/models/trace/insights/FontDisplay.ts",
35
36
  "../../../../../../../front_end/models/trace/insights/InsightRunners.ts",
36
37
  "../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts",
37
38
  "../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.ts",
38
39
  "../../../../../../../front_end/models/trace/insights/RenderBlocking.ts",
40
+ "../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts",
41
+ "../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts",
39
42
  "../../../../../../../front_end/models/trace/insights/Viewport.ts",
40
43
  "../../../../../../../front_end/models/trace/insights/types.ts",
41
44
  "../../../../../../../front_end/legacy/legacy-defs.d.ts",
@@ -43,6 +46,12 @@
43
46
  "../../../../../../../node_modules/@types/filesystem/index.d.ts"
44
47
  ],
45
48
  "references": [
49
+ {
50
+ "path": "../../../third_party/third-party-web/bundle-tsconfig.json"
51
+ },
52
+ {
53
+ "path": "../extras/bundle-tsconfig.json"
54
+ },
46
55
  {
47
56
  "path": "../handlers/bundle-tsconfig.json"
48
57
  },
@@ -1,2 +1,3 @@
1
+ export * as Common from './Common.js';
1
2
  export * as InsightRunners from './InsightRunners.js';
2
3
  export * as Types from './types.js';
@@ -1,6 +1,7 @@
1
1
  // Copyright 2024 The Chromium Authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
+ export * as Common from './Common.js';
4
5
  export * as InsightRunners from './InsightRunners.js';
5
6
  export * as Types from './types.js';
6
7
  //# sourceMappingURL=insights.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,YAAY,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\nexport * as InsightRunners from './InsightRunners.js';\nexport * as Types from './types.js';\n"]}
1
+ {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,YAAY,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\nexport * as Common from './Common.js';\nexport * as InsightRunners from './InsightRunners.js';\nexport * as Types from './types.js';\n"]}
@@ -3,16 +3,24 @@ import type * as Lantern from '../lantern/lantern.js';
3
3
  import type * as Types from '../types/types.js';
4
4
  import type * as InsightsRunners from './InsightRunners.js';
5
5
  /**
6
- * Context for which navigation an insight should look at.
6
+ * Context for the portion of the trace an insight should look at.
7
7
  */
8
- export interface NavigationInsightContext {
8
+ export type InsightSetContext = InsightSetContextWithoutNavigation | InsightSetContextWithNavigation;
9
+ export interface InsightSetContextWithoutNavigation {
10
+ bounds: Types.Timing.TraceWindowMicroSeconds;
9
11
  frameId: string;
12
+ navigation?: never;
13
+ }
14
+ export interface InsightSetContextWithNavigation {
15
+ bounds: Types.Timing.TraceWindowMicroSeconds;
16
+ frameId: string;
17
+ navigation: Types.Events.NavigationStart;
10
18
  navigationId: string;
11
19
  lantern?: LanternContext;
12
20
  }
13
21
  export interface LanternContext {
14
- graph: Lantern.Graph.Node<Types.TraceEvents.SyntheticNetworkRequest>;
15
- simulator: Lantern.Simulation.Simulator<Types.TraceEvents.SyntheticNetworkRequest>;
22
+ graph: Lantern.Graph.Node<Types.Events.SyntheticNetworkRequest>;
23
+ simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;
16
24
  metrics: Record<string, Lantern.Metrics.MetricResult>;
17
25
  }
18
26
  export type InsightRunnersType = typeof InsightsRunners;
@@ -22,36 +30,46 @@ export declare enum InsightWarning {
22
30
  NO_DOCUMENT_REQUEST = "NO_DOCUMENT_REQUEST",
23
31
  NO_LAYOUT = "NO_LAYOUT"
24
32
  }
33
+ export interface MetricSavings {
34
+ FCP?: Types.Timing.MilliSeconds;
35
+ LCP?: Types.Timing.MilliSeconds;
36
+ TBT?: Types.Timing.MilliSeconds;
37
+ CLS?: number;
38
+ INP?: Types.Timing.MilliSeconds;
39
+ }
25
40
  export type InsightResult<R extends Record<string, unknown>> = R & {
41
+ relatedEvents?: Types.Events.Event[];
26
42
  warnings?: InsightWarning[];
27
- metricSavings?: {
28
- FCP?: number;
29
- LCP?: number;
30
- TBT?: number;
31
- CLS?: number;
32
- INP?: number;
33
- };
43
+ metricSavings?: MetricSavings;
44
+ };
45
+ /**
46
+ * Contains insights for a specific navigation. If a trace began after a navigation already started,
47
+ * this could instead represent the duration from the beginning of the trace up to the first recorded
48
+ * navigation (or the end of the trace).
49
+ */
50
+ export type InsightSets = {
51
+ /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */
52
+ id: Types.Events.NavigationId;
53
+ /** The URL to show in the accordion list. */
54
+ url: URL;
55
+ frameId: string;
56
+ bounds: Types.Timing.TraceWindowMicroSeconds;
57
+ data: InsightResults;
58
+ navigation?: Types.Events.NavigationStart;
34
59
  };
35
- export type LCPInsightResult = InsightResult<{
36
- lcpMs?: Types.Timing.MilliSeconds;
37
- lcpTs?: Types.Timing.MilliSeconds;
38
- phases?: InsightsRunners.LargestContentfulPaint.LCPPhases;
39
- shouldRemoveLazyLoading?: boolean;
40
- shouldIncreasePriorityHint?: boolean;
41
- shouldPreloadImage?: boolean;
42
- lcpResource?: Types.TraceEvents.SyntheticNetworkRequest;
43
- earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds;
44
- }>;
45
60
  /**
46
61
  * Contains insights for a specific navigation.
47
62
  */
48
- export type NavigationInsightData = {
49
- [I in keyof InsightRunnersType]: ReturnType<InsightRunnersType[I]['generateInsight']> | Error;
63
+ export type InsightResults = {
64
+ [I in keyof InsightRunnersType]: ReturnType<InsightRunnersType[I]['generateInsight']>;
50
65
  };
51
66
  /**
52
- * Contains insights for the entire trace. Insights are grouped by `navigationId`.
67
+ * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:
68
+ *
69
+ * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no
70
+ * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.
53
71
  */
54
- export type TraceInsightData = Map<string, NavigationInsightData>;
72
+ export type TraceInsightSets = Map<Types.Events.NavigationId, InsightSets>;
55
73
  /**
56
74
  * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.
57
75
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAyB7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB","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 Handlers from '../handlers/handlers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as InsightsRunners from './InsightRunners.js';\n\n/**\n * Context for which navigation an insight should look at.\n */\nexport interface NavigationInsightContext {\n frameId: string;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n graph: Lantern.Graph.Node<Types.TraceEvents.SyntheticNetworkRequest>;\n simulator: Lantern.Simulation.Simulator<Types.TraceEvents.SyntheticNetworkRequest>;\n metrics: Record<string, Lantern.Metrics.MetricResult>;\n}\n\nexport type InsightRunnersType = typeof InsightsRunners;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport type InsightResult<R extends Record<string, unknown>> = R&{\n warnings?: InsightWarning[],\n metricSavings?: {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: number,\n LCP?: number,\n TBT?: number,\n CLS?: number,\n INP?: number,\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n};\n\nexport type LCPInsightResult = InsightResult<{\n lcpMs?: Types.Timing.MilliSeconds,\n lcpTs?: Types.Timing.MilliSeconds,\n phases?: InsightsRunners.LargestContentfulPaint.LCPPhases,\n shouldRemoveLazyLoading?: boolean,\n shouldIncreasePriorityHint?: boolean,\n shouldPreloadImage?: boolean,\n lcpResource?: Types.TraceEvents.SyntheticNetworkRequest,\n earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds,\n}>;\n\n/**\n * Contains insights for a specific navigation.\n */\nexport type NavigationInsightData = {\n [I in keyof InsightRunnersType]: ReturnType<InsightRunnersType[I]['generateInsight']>|Error;\n};\n\n/**\n * Contains insights for the entire trace. Insights are grouped by `navigationId`.\n */\nexport type TraceInsightData = Map<string, NavigationInsightData>;\n\n/**\n * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.\n */\nexport type RequiredData<D extends() => Array<keyof typeof Handlers.ModelHandlers>> =\n Handlers.Types.EnabledHandlerDataWithMeta<Pick<typeof Handlers.ModelHandlers, ReturnType<D>[number]>>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAmC7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB","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 Handlers from '../handlers/handlers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as InsightsRunners from './InsightRunners.js';\n\n/**\n * Context for the portion of the trace an insight should look at.\n */\nexport type InsightSetContext = InsightSetContextWithoutNavigation|InsightSetContextWithNavigation;\n\nexport interface InsightSetContextWithoutNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation: Types.Events.NavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n graph: Lantern.Graph.Node<Types.Events.SyntheticNetworkRequest>;\n simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;\n metrics: Record<string, Lantern.Metrics.MetricResult>;\n}\n\nexport type InsightRunnersType = typeof InsightsRunners;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.MilliSeconds;\n LCP?: Types.Timing.MilliSeconds;\n TBT?: Types.Timing.MilliSeconds;\n CLS?: number;\n INP?: Types.Timing.MilliSeconds;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport type InsightResult<R extends Record<string, unknown>> = R&{\n relatedEvents?: Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\n};\n\n/**\n * Contains insights for a specific navigation. If a trace began after a navigation already started,\n * this could instead represent the duration from the beginning of the trace up to the first recorded\n * navigation (or the end of the trace).\n */\nexport type InsightSets = {\n /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId,\n /** The URL to show in the accordion list. */\n url: URL,\n frameId: string,\n bounds: Types.Timing.TraceWindowMicroSeconds,\n data: InsightResults,\n navigation?: Types.Events.NavigationStart,\n};\n\n/**\n * Contains insights for a specific navigation.\n */\nexport type InsightResults = {\n [I in keyof InsightRunnersType]: ReturnType<InsightRunnersType[I]['generateInsight']>;\n};\n\n/**\n * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:\n *\n * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no\n * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = Map<Types.Events.NavigationId, InsightSets>;\n\n/**\n * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.\n */\nexport type RequiredData<D extends() => Array<keyof typeof Handlers.ModelHandlers>> =\n Handlers.Types.EnabledHandlerDataWithMeta<Pick<typeof Handlers.ModelHandlers, ReturnType<D>[number]>>;\n"]}
@@ -34,7 +34,7 @@ declare class NetworkAnalyzer {
34
34
  static groupByOrigin(records: Lantern.NetworkRequest[]): Map<string, Lantern.NetworkRequest[]>;
35
35
  static getSummary(values: number[]): Summary;
36
36
  static summarize(values: Map<string, number[]>): Map<string, Summary>;
37
- static _estimateValueByOrigin(requests: Lantern.NetworkRequest[], iteratee: (e: RequestInfo) => number | number[] | undefined): Map<string, number[]>;
37
+ static estimateValueByOrigin(requests: Lantern.NetworkRequest[], iteratee: (e: RequestInfo) => number | number[] | undefined): Map<string, number[]>;
38
38
  /**
39
39
  * Estimates the observed RTT to each origin based on how long the connection setup.
40
40
  * For h1 and h2, this could includes two estimates - one for the TCP handshake, another for
@@ -43,31 +43,31 @@ declare class NetworkAnalyzer {
43
43
  * single handshake.
44
44
  * This is the most accurate and preferred method of measurement when the data is available.
45
45
  */
46
- static _estimateRTTViaConnectionTiming(info: RequestInfo): number[] | number | undefined;
46
+ static estimateRTTViaConnectionTiming(info: RequestInfo): number[] | number | undefined;
47
47
  /**
48
48
  * Estimates the observed RTT to each origin based on how long a download took on a fresh connection.
49
49
  * NOTE: this will tend to overestimate the actual RTT quite significantly as the download can be
50
50
  * slow for other reasons as well such as bandwidth constraints.
51
51
  */
52
- static _estimateRTTViaDownloadTiming(info: RequestInfo): number | undefined;
52
+ static estimateRTTViaDownloadTiming(info: RequestInfo): number | undefined;
53
53
  /**
54
54
  * Estimates the observed RTT to each origin based on how long it took until Chrome could
55
55
  * start sending the actual request when a new connection was required.
56
56
  * NOTE: this will tend to overestimate the actual RTT as the request can be delayed for other
57
57
  * reasons as well such as more SSL handshakes if TLS False Start is not enabled.
58
58
  */
59
- static _estimateRTTViaSendStartTiming(info: RequestInfo): number | undefined;
59
+ static estimateRTTViaSendStartTiming(info: RequestInfo): number | undefined;
60
60
  /**
61
61
  * Estimates the observed RTT to each origin based on how long it took until Chrome received the
62
62
  * headers of the response (~TTFB).
63
63
  * NOTE: this is the most inaccurate way to estimate the RTT, but in some environments it's all
64
64
  * we have access to :(
65
65
  */
66
- static _estimateRTTViaHeadersEndTiming(info: RequestInfo): number | undefined;
66
+ static estimateRTTViaHeadersEndTiming(info: RequestInfo): number | undefined;
67
67
  /**
68
68
  * Given the RTT to each origin, estimates the observed server response times.
69
69
  */
70
- static _estimateResponseTimeByOrigin(records: Lantern.NetworkRequest[], rttByOrigin: Map<string, number>): Map<string, number[]>;
70
+ static estimateResponseTimeByOrigin(records: Lantern.NetworkRequest[], rttByOrigin: Map<string, number>): Map<string, number[]>;
71
71
  static canTrustConnectionInformation(requests: Lantern.NetworkRequest[]): boolean;
72
72
  /**
73
73
  * Returns a map of requestId -> connectionReused, estimating the information if the information
@@ -93,7 +93,7 @@ class NetworkAnalyzer {
93
93
  summaryByKey.set(NetworkAnalyzer.summary, NetworkAnalyzer.getSummary(allEstimates));
94
94
  return summaryByKey;
95
95
  }
96
- static _estimateValueByOrigin(requests, iteratee) {
96
+ static estimateValueByOrigin(requests, iteratee) {
97
97
  const connectionWasReused = NetworkAnalyzer.estimateIfConnectionWasReused(requests);
98
98
  const groupedByOrigin = NetworkAnalyzer.groupByOrigin(requests);
99
99
  const estimates = new Map();
@@ -128,7 +128,7 @@ class NetworkAnalyzer {
128
128
  * single handshake.
129
129
  * This is the most accurate and preferred method of measurement when the data is available.
130
130
  */
131
- static _estimateRTTViaConnectionTiming(info) {
131
+ static estimateRTTViaConnectionTiming(info) {
132
132
  const { timing, connectionReused, request } = info;
133
133
  if (connectionReused) {
134
134
  return;
@@ -152,7 +152,7 @@ class NetworkAnalyzer {
152
152
  * NOTE: this will tend to overestimate the actual RTT quite significantly as the download can be
153
153
  * slow for other reasons as well such as bandwidth constraints.
154
154
  */
155
- static _estimateRTTViaDownloadTiming(info) {
155
+ static estimateRTTViaDownloadTiming(info) {
156
156
  const { timing, connectionReused, request } = info;
157
157
  if (connectionReused) {
158
158
  return;
@@ -181,7 +181,7 @@ class NetworkAnalyzer {
181
181
  * NOTE: this will tend to overestimate the actual RTT as the request can be delayed for other
182
182
  * reasons as well such as more SSL handshakes if TLS False Start is not enabled.
183
183
  */
184
- static _estimateRTTViaSendStartTiming(info) {
184
+ static estimateRTTViaSendStartTiming(info) {
185
185
  const { timing, connectionReused, request } = info;
186
186
  if (connectionReused) {
187
187
  return;
@@ -207,7 +207,7 @@ class NetworkAnalyzer {
207
207
  * NOTE: this is the most inaccurate way to estimate the RTT, but in some environments it's all
208
208
  * we have access to :(
209
209
  */
210
- static _estimateRTTViaHeadersEndTiming(info) {
210
+ static estimateRTTViaHeadersEndTiming(info) {
211
211
  const { timing, connectionReused, request } = info;
212
212
  if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) {
213
213
  return;
@@ -237,8 +237,8 @@ class NetworkAnalyzer {
237
237
  /**
238
238
  * Given the RTT to each origin, estimates the observed server response times.
239
239
  */
240
- static _estimateResponseTimeByOrigin(records, rttByOrigin) {
241
- return NetworkAnalyzer._estimateValueByOrigin(records, ({ request, timing }) => {
240
+ static estimateResponseTimeByOrigin(records, rttByOrigin) {
241
+ return NetworkAnalyzer.estimateValueByOrigin(records, ({ request, timing }) => {
242
242
  if (request.serverResponseTime !== undefined) {
243
243
  return request.serverResponseTime;
244
244
  }
@@ -334,7 +334,7 @@ class NetworkAnalyzer {
334
334
  }
335
335
  }
336
336
  if (!forceCoarseEstimates) {
337
- collectEstimates(this._estimateRTTViaConnectionTiming);
337
+ collectEstimates(this.estimateRTTViaConnectionTiming);
338
338
  }
339
339
  // Connection timing can be missing for a few reasons:
340
340
  // - Origin was preconnected, which we don't have instrumentation for.
@@ -343,13 +343,13 @@ class NetworkAnalyzer {
343
343
  // - Not provided in LR netstack.
344
344
  if (!originEstimates.length) {
345
345
  if (useDownloadEstimates) {
346
- collectEstimates(this._estimateRTTViaDownloadTiming, coarseEstimateMultiplier);
346
+ collectEstimates(this.estimateRTTViaDownloadTiming, coarseEstimateMultiplier);
347
347
  }
348
348
  if (useSendStartEstimates) {
349
- collectEstimates(this._estimateRTTViaSendStartTiming, coarseEstimateMultiplier);
349
+ collectEstimates(this.estimateRTTViaSendStartTiming, coarseEstimateMultiplier);
350
350
  }
351
351
  if (useHeadersEndEstimates) {
352
- collectEstimates(this._estimateRTTViaHeadersEndTiming, coarseEstimateMultiplier);
352
+ collectEstimates(this.estimateRTTViaHeadersEndTiming, coarseEstimateMultiplier);
353
353
  }
354
354
  }
355
355
  if (originEstimates.length) {
@@ -374,7 +374,7 @@ class NetworkAnalyzer {
374
374
  rttByOrigin.set(origin, summary.min);
375
375
  }
376
376
  }
377
- const estimatesByOrigin = NetworkAnalyzer._estimateResponseTimeByOrigin(records, rttByOrigin);
377
+ const estimatesByOrigin = NetworkAnalyzer.estimateResponseTimeByOrigin(records, rttByOrigin);
378
378
  return NetworkAnalyzer.summarize(estimatesByOrigin);
379
379
  }
380
380
  /**