@paulirish/trace_engine 0.0.41 → 0.0.43

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 (218) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/generated/protocol.d.ts +79 -3
  3. package/locales/en-US.json +210 -0
  4. package/locales/en-XL.json +210 -0
  5. package/models/cpu_profile/CPUProfileDataModel.d.ts +7 -0
  6. package/models/cpu_profile/CPUProfileDataModel.js +9 -2
  7. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
  8. package/models/cpu_profile/ProfileTreeModel.d.ts +1 -1
  9. package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
  10. package/models/trace/LanternComputationData.d.ts +1 -1
  11. package/models/trace/LanternComputationData.js +8 -6
  12. package/models/trace/LanternComputationData.js.map +1 -1
  13. package/models/trace/Processor.d.ts +2 -16
  14. package/models/trace/Processor.js +6 -4
  15. package/models/trace/Processor.js.map +1 -1
  16. package/models/trace/extras/FilmStrip.d.ts +5 -5
  17. package/models/trace/extras/FilmStrip.js +2 -1
  18. package/models/trace/extras/FilmStrip.js.map +1 -1
  19. package/models/trace/extras/MainThreadActivity.d.ts +1 -1
  20. package/models/trace/extras/MainThreadActivity.js +3 -3
  21. package/models/trace/extras/MainThreadActivity.js.map +1 -1
  22. package/models/trace/extras/ThirdParties.d.ts +14 -13
  23. package/models/trace/extras/ThirdParties.js +51 -61
  24. package/models/trace/extras/ThirdParties.js.map +1 -1
  25. package/models/trace/extras/TimelineJSProfile.d.ts +1 -1
  26. package/models/trace/extras/TimelineJSProfile.js +9 -4
  27. package/models/trace/extras/TimelineJSProfile.js.map +1 -1
  28. package/models/trace/extras/TraceTree.d.ts +19 -6
  29. package/models/trace/extras/TraceTree.js +6 -3
  30. package/models/trace/extras/TraceTree.js.map +1 -1
  31. package/models/trace/extras/extras.d.ts +0 -1
  32. package/models/trace/extras/extras.js +0 -1
  33. package/models/trace/handlers/AnimationFramesHandler.js +1 -1
  34. package/models/trace/handlers/AnimationFramesHandler.js.map +1 -1
  35. package/models/trace/handlers/ExtensionTraceDataHandler.js +8 -2
  36. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  37. package/models/trace/handlers/FlowsHandler.js.map +1 -1
  38. package/models/trace/handlers/FramesHandler.d.ts +12 -12
  39. package/models/trace/handlers/FramesHandler.js +3 -3
  40. package/models/trace/handlers/FramesHandler.js.map +1 -1
  41. package/models/trace/handlers/LayoutShiftsHandler.d.ts +2 -2
  42. package/models/trace/handlers/LayoutShiftsHandler.js +25 -16
  43. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  44. package/models/trace/handlers/MetaHandler.d.ts +2 -2
  45. package/models/trace/handlers/MetaHandler.js +21 -21
  46. package/models/trace/handlers/MetaHandler.js.map +1 -1
  47. package/models/trace/handlers/NetworkRequestsHandler.js +37 -38
  48. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  49. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +6 -6
  50. package/models/trace/handlers/PageLoadMetricsHandler.js +9 -9
  51. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  52. package/models/trace/handlers/RendererHandler.d.ts +1 -1
  53. package/models/trace/handlers/RendererHandler.js +4 -4
  54. package/models/trace/handlers/RendererHandler.js.map +1 -1
  55. package/models/trace/handlers/SamplesHandler.d.ts +1 -1
  56. package/models/trace/handlers/SamplesHandler.js +50 -42
  57. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  58. package/models/trace/handlers/ScreenshotsHandler.d.ts +6 -3
  59. package/models/trace/handlers/ScreenshotsHandler.js +22 -8
  60. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  61. package/models/trace/handlers/ServerTimingsHandler.js +4 -4
  62. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -1
  63. package/models/trace/handlers/Threads.js +3 -4
  64. package/models/trace/handlers/Threads.js.map +1 -1
  65. package/models/trace/handlers/UserInteractionsHandler.d.ts +2 -2
  66. package/models/trace/handlers/UserInteractionsHandler.js +12 -12
  67. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  68. package/models/trace/handlers/WarningsHandler.d.ts +2 -2
  69. package/models/trace/handlers/WarningsHandler.js +2 -2
  70. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  71. package/models/trace/handlers/helpers.d.ts +3 -3
  72. package/models/trace/handlers/helpers.js +16 -19
  73. package/models/trace/handlers/helpers.js.map +1 -1
  74. package/models/trace/handlers/types.d.ts +1 -1
  75. package/models/trace/handlers/types.js.map +1 -1
  76. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
  77. package/models/trace/helpers/SamplesIntegrator.js +54 -15
  78. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  79. package/models/trace/helpers/Timing.d.ts +23 -23
  80. package/models/trace/helpers/Timing.js +11 -11
  81. package/models/trace/helpers/Timing.js.map +1 -1
  82. package/models/trace/helpers/Trace.d.ts +15 -14
  83. package/models/trace/helpers/Trace.js +11 -5
  84. package/models/trace/helpers/Trace.js.map +1 -1
  85. package/models/trace/helpers/TreeHelpers.d.ts +2 -2
  86. package/models/trace/helpers/TreeHelpers.js +5 -5
  87. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  88. package/models/trace/insights/CLSCulprits.d.ts +46 -1
  89. package/models/trace/insights/CLSCulprits.js +85 -10
  90. package/models/trace/insights/CLSCulprits.js.map +1 -1
  91. package/models/trace/insights/Common.d.ts +11 -7
  92. package/models/trace/insights/Common.js +85 -26
  93. package/models/trace/insights/Common.js.map +1 -1
  94. package/models/trace/insights/DOMSize.d.ts +26 -1
  95. package/models/trace/insights/DOMSize.js +44 -7
  96. package/models/trace/insights/DOMSize.js.map +1 -1
  97. package/models/trace/insights/DocumentLatency.d.ts +42 -5
  98. package/models/trace/insights/DocumentLatency.js +64 -8
  99. package/models/trace/insights/DocumentLatency.js.map +1 -1
  100. package/models/trace/insights/FontDisplay.d.ts +8 -2
  101. package/models/trace/insights/FontDisplay.js +10 -4
  102. package/models/trace/insights/FontDisplay.js.map +1 -1
  103. package/models/trace/insights/ForcedReflow.d.ts +30 -0
  104. package/models/trace/insights/ForcedReflow.js +181 -0
  105. package/models/trace/insights/ForcedReflow.js.map +1 -0
  106. package/models/trace/insights/ImageDelivery.d.ts +15 -1
  107. package/models/trace/insights/ImageDelivery.js +21 -1
  108. package/models/trace/insights/ImageDelivery.js.map +1 -1
  109. package/models/trace/insights/InteractionToNextPaint.d.ts +26 -1
  110. package/models/trace/insights/InteractionToNextPaint.js +27 -1
  111. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  112. package/models/trace/insights/LCPDiscovery.d.ts +30 -6
  113. package/models/trace/insights/LCPDiscovery.js +36 -8
  114. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  115. package/models/trace/insights/LCPPhases.d.ts +36 -7
  116. package/models/trace/insights/LCPPhases.js +37 -8
  117. package/models/trace/insights/LCPPhases.js.map +1 -1
  118. package/models/trace/insights/LongCriticalNetworkTree.d.ts +22 -0
  119. package/models/trace/insights/LongCriticalNetworkTree.js +40 -0
  120. package/models/trace/insights/LongCriticalNetworkTree.js.map +1 -0
  121. package/models/trace/insights/Models.d.ts +2 -0
  122. package/models/trace/insights/Models.js +2 -0
  123. package/models/trace/insights/Models.js.map +1 -1
  124. package/models/trace/insights/RenderBlocking.d.ts +14 -1
  125. package/models/trace/insights/RenderBlocking.js +14 -1
  126. package/models/trace/insights/RenderBlocking.js.map +1 -1
  127. package/models/trace/insights/SlowCSSSelector.d.ts +27 -2
  128. package/models/trace/insights/SlowCSSSelector.js +27 -2
  129. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  130. package/models/trace/insights/ThirdParties.d.ts +13 -4
  131. package/models/trace/insights/ThirdParties.js +21 -12
  132. package/models/trace/insights/ThirdParties.js.map +1 -1
  133. package/models/trace/insights/Viewport.d.ts +2 -1
  134. package/models/trace/insights/Viewport.js +2 -1
  135. package/models/trace/insights/Viewport.js.map +1 -1
  136. package/models/trace/insights/insights-tsconfig.json +2 -0
  137. package/models/trace/insights/types.d.ts +27 -8
  138. package/models/trace/insights/types.js.map +1 -1
  139. package/models/trace/lantern/graph/BaseNode.d.ts +1 -1
  140. package/models/trace/lantern/graph/BaseNode.js +1 -1
  141. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  142. package/models/trace/lantern/graph/CPUNode.d.ts +1 -1
  143. package/models/trace/lantern/graph/CPUNode.js.map +1 -1
  144. package/models/trace/lantern/graph/NetworkNode.d.ts +1 -1
  145. package/models/trace/lantern/graph/NetworkNode.js.map +1 -1
  146. package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +1 -1
  147. package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
  148. package/models/trace/lantern/simulation/ConnectionPool.js +1 -1
  149. package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
  150. package/models/trace/lantern/simulation/Simulator.d.ts +2 -2
  151. package/models/trace/lantern/simulation/Simulator.js +3 -3
  152. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  153. package/models/trace/lantern/types/Lantern.d.ts +2 -2
  154. package/models/trace/lantern/types/Lantern.js.map +1 -1
  155. package/models/trace/root-causes/LayoutShift.d.ts +1 -1
  156. package/models/trace/root-causes/LayoutShift.js +4 -4
  157. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  158. package/models/trace/types/Configuration.d.ts +15 -0
  159. package/models/trace/types/Configuration.js.map +1 -1
  160. package/models/trace/types/File.d.ts +4 -4
  161. package/models/trace/types/File.js.map +1 -1
  162. package/models/trace/types/Timing.d.ts +7 -13
  163. package/models/trace/types/Timing.js +5 -2
  164. package/models/trace/types/Timing.js.map +1 -1
  165. package/models/trace/types/TraceEvents.d.ts +145 -110
  166. package/models/trace/types/TraceEvents.js +9 -7
  167. package/models/trace/types/TraceEvents.js.map +1 -1
  168. package/package.json +1 -1
  169. package/test/test-trace-engine.mjs +18 -14
  170. package/core/platform/PromiseUtilities.d.ts +0 -10
  171. package/core/platform/PromiseUtilities.js +0 -18
  172. package/core/platform/PromiseUtilities.js.map +0 -1
  173. package/core/platform/SetUtilities.d.ts +0 -2
  174. package/core/platform/SetUtilities.js +0 -23
  175. package/core/platform/SetUtilities.js.map +0 -1
  176. package/models/trace/EntriesFilter.d.ts +0 -72
  177. package/models/trace/EntriesFilter.js +0 -296
  178. package/models/trace/EntriesFilter.js.map +0 -1
  179. package/models/trace/LegacyTracingModel.js.map +0 -1
  180. package/models/trace/extras/URLForEntry.d.ts +0 -13
  181. package/models/trace/extras/URLForEntry.js +0 -44
  182. package/models/trace/extras/URLForEntry.js.map +0 -1
  183. package/models/trace/handlers/EnhancedTracesHandler.d.ts +0 -48
  184. package/models/trace/handlers/EnhancedTracesHandler.js +0 -165
  185. package/models/trace/handlers/EnhancedTracesHandler.js.map +0 -1
  186. package/models/trace/insights/CumulativeLayoutShift.d.ts +0 -34
  187. package/models/trace/insights/CumulativeLayoutShift.js +0 -209
  188. package/models/trace/insights/CumulativeLayoutShift.js.map +0 -1
  189. package/models/trace/insights/InsightRunners.d.ts +0 -6
  190. package/models/trace/insights/InsightRunners.js +0 -10
  191. package/models/trace/insights/InsightRunners.js.map +0 -1
  192. package/models/trace/insights/LargestContentfulPaint.d.ts +0 -25
  193. package/models/trace/insights/LargestContentfulPaint.js +0 -93
  194. package/models/trace/insights/LargestContentfulPaint.js.map +0 -1
  195. package/models/trace/lantern/BaseNode.d.ts +0 -91
  196. package/models/trace/lantern/BaseNode.js +0 -268
  197. package/models/trace/lantern/BaseNode.js.map +0 -1
  198. package/models/trace/lantern/CPUNode.d.ts +0 -24
  199. package/models/trace/lantern/CPUNode.js +0 -64
  200. package/models/trace/lantern/CPUNode.js.map +0 -1
  201. package/models/trace/lantern/LanternError.d.ts +0 -3
  202. package/models/trace/lantern/LanternError.js +0 -7
  203. package/models/trace/lantern/LanternError.js.map +0 -1
  204. package/models/trace/lantern/MetricsModule.d.ts +0 -11
  205. package/models/trace/lantern/MetricsModule.js +0 -14
  206. package/models/trace/lantern/MetricsModule.js.map +0 -1
  207. package/models/trace/lantern/NetworkNode.d.ts +0 -22
  208. package/models/trace/lantern/NetworkNode.js +0 -83
  209. package/models/trace/lantern/NetworkNode.js.map +0 -1
  210. package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
  211. package/models/trace/lantern/PageDependencyGraph.js +0 -509
  212. package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
  213. package/models/trace/lantern/SimulationModule.d.ts +0 -17
  214. package/models/trace/lantern/SimulationModule.js +0 -13
  215. package/models/trace/lantern/SimulationModule.js.map +0 -1
  216. package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
  217. package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
  218. package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: 'Third parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description: 'Third party code can significantly impact load performance. ' +\n '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\\'s content.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type ThirdPartiesInsightModel = InsightModel<{\n entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Entity>,\n requestsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.Event[]>,\n summaryByEvent: Map<Types.Events.Event, Extras.ThirdParties.Summary>,\n summaryByEntity: Map<Extras.ThirdParties.Entity, Extras.ThirdParties.Summary>,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.SummaryMaps,\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const events = [];\n\n for (const [entity, requests] of summaries.eventsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n events.push(...requests);\n }\n }\n\n return events;\n}\n\nfunction finalize(partialModel: Omit<ThirdPartiesInsightModel, 'title'|'description'|'category'|'shouldShow'>):\n ThirdPartiesInsightModel {\n return {\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n shouldShow:\n Boolean([...partialModel.summaryByEntity.entries()].find(kv => kv[0] !== partialModel.firstPartyEntity)),\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartiesInsightModel {\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, madeUpEntityCache, summaries} = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(\n parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Handlers.Helpers.makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(summaries, firstPartyEntity),\n entityByRequest,\n requestsByEntity: summaries.eventsByEntity,\n summaryByEvent: summaries.byEvent,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n });\n}\n"]}
1
+ {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n type InsightModel,\n type InsightSetContext,\n type PartialInsightModel,\n type RequiredData\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: 'Third parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description: 'Third party code can significantly impact load performance. ' +\n '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\\'s content.',\n /** Label for a table column that displays the name of a third-party provider. */\n columnThirdParty: 'Third party',\n /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */\n columnTransferSize: 'Transfer size',\n /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */\n columnBlockingTime: 'Blocking time',\n /**\n * @description Text block indicating that no third party content was detected on the page\n */\n noThirdParties: 'No third parties found',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type ThirdPartiesInsightModel = InsightModel<typeof UIStrings, {\n eventsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.Event[]>,\n summaryByEntity: Map<Extras.ThirdParties.Entity, Extras.ThirdParties.Summary>,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.ThirdPartySummary,\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const relatedEvents = [];\n\n for (const [entity, events] of summaries.eventsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n relatedEvents.push(...events);\n }\n }\n\n return relatedEvents;\n}\n\nfunction finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>): ThirdPartiesInsightModel {\n return {\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n shouldShow:\n Boolean([...partialModel.summaryByEntity.entries()].find(kv => kv[0] !== partialModel.firstPartyEntity)),\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartiesInsightModel {\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 thirdPartySummary = Extras.ThirdParties.summarizeThirdParties(\n parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Handlers.Helpers.makeUpEntity(thirdPartySummary.madeUpEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(thirdPartySummary, firstPartyEntity),\n eventsByEntity: thirdPartySummary.eventsByEntity,\n summaryByEntity: thirdPartySummary.byEntity,\n firstPartyEntity,\n });\n}\n"]}
@@ -8,8 +8,9 @@ export declare const UIStrings: {
8
8
  */
9
9
  description: string;
10
10
  };
11
+ export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => Record<string, string>;
11
12
  export declare function deps(): ['Meta', 'UserInteractions'];
12
- export type ViewportInsightModel = InsightModel<{
13
+ export type ViewportInsightModel = InsightModel<typeof UIStrings, {
13
14
  mobileOptimized: boolean | null;
14
15
  viewportEvent?: Types.Events.ParseMetaViewport;
15
16
  }>;
@@ -13,12 +13,13 @@ export const UIStrings = {
13
13
  description: 'Tap interactions may be [delayed by up to 300\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',
14
14
  };
15
15
  // const str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);
16
- const i18nString = string => string; // i18n.i18n.getLocalizedString.bind(undefined, str_);
16
+ export const i18nString = string => string; // i18n.i18n.getLocalizedString.bind(undefined, str_);
17
17
  export function deps() {
18
18
  return ['Meta', 'UserInteractions'];
19
19
  }
20
20
  function finalize(partialModel) {
21
21
  return {
22
+ strings: UIStrings,
22
23
  title: i18nString(UIStrings.title),
23
24
  description: i18nString(UIStrings.description),
24
25
  category: InsightCategory.INP,
@@ -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,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EACL,eAAe,EAGf,cAAc,GAEf,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,8GAA8G;IAC9G,KAAK,EAAE,8BAA8B;IACrC;;OAEG;IACH,WAAW,EACP,iKAAiK;CACtK,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,SAAS,QAAQ,CAAC,YAAuF;IAEvG,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;QAClC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QAC9C,QAAQ,EAAE,eAAe,CAAC,GAAG;QAC7B,UAAU,EAAE,YAAY,CAAC,eAAe,KAAK,KAAK;QAClD,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,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,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,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,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAgC,EAAC;aACvD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC,CAAC;AACL,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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type RequiredData,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Optimize viewport for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'Tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightModel = InsightModel<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nfunction finalize(partialModel: Omit<ViewportInsightModel, 'title'|'description'|'category'|'shouldShow'>):\n ViewportInsightModel {\n return {\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n shouldShow: partialModel.mobileOptimized === false,\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightModel {\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 finalize({\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 finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.MilliSeconds},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\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,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EACL,eAAe,EAGf,cAAc,GAGf,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,8GAA8G;IAC9G,KAAK,EAAE,8BAA8B;IACrC;;OAEG;IACH,WAAW,EACP,iKAAiK;CACtK,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAE7E,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,SAAS,QAAQ,CAAC,YAAuD;IACvE,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;QAClC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QAC9C,QAAQ,EAAE,eAAe,CAAC,GAAG;QAC7B,UAAU,EAAE,YAAY,CAAC,eAAe,KAAK,KAAK;QAClD,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,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,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,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,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAyB,EAAC;aAChD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC,CAAC;AACL,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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type PartialInsightModel,\n type RequiredData,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Optimize viewport for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'Tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightModel = InsightModel<typeof UIStrings, {\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<ViewportInsightModel>): ViewportInsightModel {\n return {\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n shouldShow: partialModel.mobileOptimized === false,\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightModel {\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 finalize({\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 finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.Milli},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n"]}
@@ -34,10 +34,12 @@
34
34
  "../../../../../../../front_end/models/trace/insights/DOMSize.ts",
35
35
  "../../../../../../../front_end/models/trace/insights/DocumentLatency.ts",
36
36
  "../../../../../../../front_end/models/trace/insights/FontDisplay.ts",
37
+ "../../../../../../../front_end/models/trace/insights/ForcedReflow.ts",
37
38
  "../../../../../../../front_end/models/trace/insights/ImageDelivery.ts",
38
39
  "../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts",
39
40
  "../../../../../../../front_end/models/trace/insights/LCPDiscovery.ts",
40
41
  "../../../../../../../front_end/models/trace/insights/LCPPhases.ts",
42
+ "../../../../../../../front_end/models/trace/insights/LongCriticalNetworkTree.ts",
41
43
  "../../../../../../../front_end/models/trace/insights/Models.ts",
42
44
  "../../../../../../../front_end/models/trace/insights/RenderBlocking.ts",
43
45
  "../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts",
@@ -1,4 +1,5 @@
1
1
  // import type * as Common from '../../../core/common/common.js';
2
+ import type * as Protocol from '../../../generated/protocol.js';
2
3
  import type * as Handlers from '../handlers/handlers.js';
3
4
  import type * as Lantern from '../lantern/lantern.js';
4
5
  import type * as Types from '../types/types.js';
@@ -8,12 +9,12 @@ import type * as Models from './Models.js';
8
9
  */
9
10
  export type InsightSetContext = InsightSetContextWithoutNavigation | InsightSetContextWithNavigation;
10
11
  export interface InsightSetContextWithoutNavigation {
11
- bounds: Types.Timing.TraceWindowMicroSeconds;
12
+ bounds: Types.Timing.TraceWindowMicro;
12
13
  frameId: string;
13
14
  navigation?: never;
14
15
  }
15
16
  export interface InsightSetContextWithNavigation {
16
- bounds: Types.Timing.TraceWindowMicroSeconds;
17
+ bounds: Types.Timing.TraceWindowMicro;
17
18
  frameId: string;
18
19
  navigation: Types.Events.NavigationStart;
19
20
  navigationId: string;
@@ -24,6 +25,17 @@ export interface LanternContext {
24
25
  simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;
25
26
  metrics: Record<string, Lantern.Metrics.MetricResult>;
26
27
  }
28
+ export interface ForcedReflowAggregatedData {
29
+ topLevelFunctionCall: Types.Events.CallFrame | Protocol.Runtime.CallFrame;
30
+ totalReflowTime: number;
31
+ bottomUpData: Set<string>;
32
+ topLevelFunctionCallEvents: Types.Events.Event[];
33
+ }
34
+ export interface BottomUpCallStack {
35
+ bottomUpData: Types.Events.CallFrame | Protocol.Runtime.CallFrame;
36
+ totalTime: number;
37
+ relatedEvents: Types.Events.Event[];
38
+ }
27
39
  export type InsightModelsType = typeof Models;
28
40
  export declare enum InsightWarning {
29
41
  NO_FP = "NO_FP",
@@ -32,11 +44,11 @@ export declare enum InsightWarning {
32
44
  NO_LAYOUT = "NO_LAYOUT"
33
45
  }
34
46
  export interface MetricSavings {
35
- FCP?: Types.Timing.MilliSeconds;
36
- LCP?: Types.Timing.MilliSeconds;
37
- TBT?: Types.Timing.MilliSeconds;
47
+ FCP?: Types.Timing.Milli;
48
+ LCP?: Types.Timing.Milli;
49
+ TBT?: Types.Timing.Milli;
38
50
  CLS?: number;
39
- INP?: Types.Timing.MilliSeconds;
51
+ INP?: Types.Timing.Milli;
40
52
  }
41
53
  export declare enum InsightCategory {
42
54
  ALL = "All",
@@ -45,7 +57,13 @@ export declare enum InsightCategory {
45
57
  CLS = "CLS"
46
58
  }
47
59
  export type RelatedEventsMap = Map<Types.Events.Event, string[]>;
48
- export type InsightModel<R extends Record<string, unknown>> = R & {
60
+ export type Checklist<Keys extends string> = Record<Keys, {
61
+ label: string;
62
+ value: boolean;
63
+ }>;
64
+ export type InsightModel<UIStrings extends Record<string, string>, R extends Record<string, unknown>> = R & {
65
+ /** Not used within DevTools - this is for external consumers (like Lighthouse). */
66
+ strings: UIStrings;
49
67
  title: string;
50
68
  description: string;
51
69
  category: InsightCategory;
@@ -55,6 +73,7 @@ export type InsightModel<R extends Record<string, unknown>> = R & {
55
73
  warnings?: InsightWarning[];
56
74
  metricSavings?: MetricSavings;
57
75
  };
76
+ export type PartialInsightModel<T> = Omit<T, 'strings' | 'title' | 'description' | 'category' | 'shouldShow'>;
58
77
  /**
59
78
  * Contains insights for a specific navigation. If a trace began after a navigation already started,
60
79
  * this could instead represent the duration from the beginning of the trace up to the first recorded
@@ -66,7 +85,7 @@ export interface InsightSet {
66
85
  /** The URL to show in the accordion list. */
67
86
  url: URL;
68
87
  frameId: string;
69
- bounds: Types.Timing.TraceWindowMicroSeconds;
88
+ bounds: Types.Timing.TraceWindowMicro;
70
89
  model: InsightModels;
71
90
  navigation?: Types.Events.NavigationStart;
72
91
  }
@@ -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;AAoC7B,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;AAYD,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B","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 Common from '../../../core/common/common.js';\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 Models from './Models.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 InsightModelsType = typeof Models;\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 enum InsightCategory {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n}\n\nexport type RelatedEventsMap = Map<Types.Events.Event, string[]>;\n\nexport type InsightModel<R extends Record<string, unknown>> = R&{\n title: Common.UIString.LocalizedString,\n description: Common.UIString.LocalizedString,\n category: InsightCategory,\n /** True if there is anything of interest to display to the user. */\n shouldShow: boolean,\n relatedEvents?: RelatedEventsMap | 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 interface InsightSet {\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 model: InsightModels;\n navigation?: Types.Events.NavigationStart;\n}\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: ReturnType<InsightModelsType[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, InsightSet>;\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;AAkD7B,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;AAYD,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B","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 Common from '../../../core/common/common.js';\nimport type * as Protocol from '../../../generated/protocol.js';\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 Models from './Models.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.TraceWindowMicro;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicro;\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 interface ForcedReflowAggregatedData {\n topLevelFunctionCall: Types.Events.CallFrame|Protocol.Runtime.CallFrame;\n totalReflowTime: number;\n bottomUpData: Set<string>;\n topLevelFunctionCallEvents: Types.Events.Event[];\n}\n\nexport interface BottomUpCallStack {\n bottomUpData: Types.Events.CallFrame|Protocol.Runtime.CallFrame;\n totalTime: number;\n relatedEvents: Types.Events.Event[];\n}\n\nexport type InsightModelsType = typeof Models;\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.Milli;\n LCP?: Types.Timing.Milli;\n TBT?: Types.Timing.Milli;\n CLS?: number;\n INP?: Types.Timing.Milli;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum InsightCategory {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n}\n\nexport type RelatedEventsMap = Map<Types.Events.Event, string[]>;\n\nexport type Checklist<Keys extends string> = Record<Keys, {label: Common.UIString.LocalizedString, value: boolean}>;\n\nexport type InsightModel<UIStrings extends Record<string, string>, R extends Record<string, unknown>> = R&{\n /** Not used within DevTools - this is for external consumers (like Lighthouse). */\n strings: UIStrings,\n title: Common.UIString.LocalizedString,\n description: Common.UIString.LocalizedString,\n category: InsightCategory,\n /** True if there is anything of interest to display to the user. */\n shouldShow: boolean,\n relatedEvents?: RelatedEventsMap | Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\n};\n\nexport type PartialInsightModel<T> = Omit<T, 'strings'|'title'|'description'|'category'|'shouldShow'>;\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 interface InsightSet {\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.TraceWindowMicro;\n model: InsightModels;\n navigation?: Types.Events.NavigationStart;\n}\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: ReturnType<InsightModelsType[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, InsightSet>;\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"]}
@@ -66,7 +66,7 @@ declare class BaseNode<T = Lantern.AnyNetworkObject> {
66
66
  * node this was called on is not included in the resulting filtered graph, the method will throw.
67
67
  *
68
68
  * This does not clone NetworkNode's `record` or `rawRecord` fields. It may be reasonable to clone the former,
69
- * to assist in graph construction, but the latter should never be cloned as one contraint of Lantern is that
69
+ * to assist in graph construction, but the latter should never be cloned as one constraint of Lantern is that
70
70
  * the underlying data records are accessible for plain object reference equality checks.
71
71
  */
72
72
  cloneWithRelationships(predicate?: (arg0: Node) => boolean): Node;
@@ -138,7 +138,7 @@ class BaseNode {
138
138
  * node this was called on is not included in the resulting filtered graph, the method will throw.
139
139
  *
140
140
  * This does not clone NetworkNode's `record` or `rawRecord` fields. It may be reasonable to clone the former,
141
- * to assist in graph construction, but the latter should never be cloned as one contraint of Lantern is that
141
+ * to assist in graph construction, but the latter should never be cloned as one constraint of Lantern is that
142
142
  * the underlying data records are accessible for plain object reference equality checks.
143
143
  */
144
144
  cloneWithRelationships(predicate) {
@@ -1 +1 @@
1
- {"version":3,"file":"BaseNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/BaseNode.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 Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport type {CPUNode} from './CPUNode.js';\nimport type {NetworkNode} from './NetworkNode.js';\n\n/**\n * A union of all types derived from BaseNode, allowing type check discrimination\n * based on `node.type`. If a new node type is created, it should be added here.\n */\nexport type Node<T = Lantern.AnyNetworkObject> = CPUNode<T>|NetworkNode<T>;\n\n/**\n * @fileoverview This class encapsulates logic for handling resources and tasks used to model the\n * execution dependency graph of the page. A node has a unique identifier and can depend on other\n * nodes/be depended on. The construction of the graph maintains some important invariants that are\n * inherent to the model:\n *\n * 1. The graph is a DAG, there are no cycles.\n * 2. There is always a root node upon which all other nodes eventually depend.\n *\n * This allows particular optimizations in this class so that we do no need to check for cycles as\n * these methods are called and we can always start traversal at the root node.\n */\n\nclass BaseNode<T = Lantern.AnyNetworkObject> {\n static types = {\n NETWORK: 'network',\n CPU: 'cpu',\n } as const;\n\n _id: string;\n _isMainDocument: boolean;\n dependents: Node[];\n dependencies: Node[];\n\n constructor(id: string) {\n this._id = id;\n this._isMainDocument = false;\n this.dependents = [];\n this.dependencies = [];\n }\n\n get id(): string {\n return this._id;\n }\n\n get type(): 'network'|'cpu' {\n throw new Core.LanternError('Unimplemented');\n }\n\n /**\n * In microseconds\n */\n get startTime(): number {\n throw new Core.LanternError('Unimplemented');\n }\n\n /**\n * In microseconds\n */\n get endTime(): number {\n throw new Core.LanternError('Unimplemented');\n }\n\n setIsMainDocument(value: boolean): void {\n this._isMainDocument = value;\n }\n\n isMainDocument(): boolean {\n return this._isMainDocument;\n }\n\n getDependents(): Node[] {\n return this.dependents.slice();\n }\n\n getNumberOfDependents(): number {\n return this.dependents.length;\n }\n\n getDependencies(): Node[] {\n return this.dependencies.slice();\n }\n\n getNumberOfDependencies(): number {\n return this.dependencies.length;\n }\n\n getRootNode(): Node<T> {\n let rootNode = this as BaseNode as Node;\n while (rootNode.dependencies.length) {\n rootNode = rootNode.dependencies[0];\n }\n\n return rootNode;\n }\n\n addDependent(node: Node): void {\n node.addDependency(this as BaseNode as Node);\n }\n\n addDependency(node: Node): void {\n // @ts-expect-error - in checkJs, ts doesn't know that CPUNode and NetworkNode *are* BaseNodes.\n if (node === this) {\n throw new Core.LanternError('Cannot add dependency on itself');\n }\n\n if (this.dependencies.includes(node)) {\n return;\n }\n\n node.dependents.push(this as BaseNode as Node);\n this.dependencies.push(node);\n }\n\n removeDependent(node: Node): void {\n node.removeDependency(this as BaseNode as Node);\n }\n\n removeDependency(node: Node): void {\n if (!this.dependencies.includes(node)) {\n return;\n }\n\n const thisIndex = node.dependents.indexOf(this as BaseNode as Node);\n node.dependents.splice(thisIndex, 1);\n this.dependencies.splice(this.dependencies.indexOf(node), 1);\n }\n\n removeAllDependencies(): void {\n for (const node of this.dependencies.slice()) {\n this.removeDependency(node);\n }\n }\n\n /**\n * Computes whether the given node is anywhere in the dependency graph of this node.\n * While this method can prevent cycles, it walks the graph and should be used sparingly.\n * Nodes are always considered dependent on themselves for the purposes of cycle detection.\n */\n isDependentOn(node: BaseNode<T>): boolean {\n let isDependentOnNode = false;\n this.traverse(\n currentNode => {\n if (isDependentOnNode) {\n return;\n }\n isDependentOnNode = currentNode === node;\n },\n currentNode => {\n // If we've already found the dependency, don't traverse further.\n if (isDependentOnNode) {\n return [];\n }\n // Otherwise, traverse the dependencies.\n return currentNode.getDependencies();\n });\n\n return isDependentOnNode;\n }\n\n /**\n * Clones the node's information without adding any dependencies/dependents.\n */\n cloneWithoutRelationships(): Node<T> {\n const node = new BaseNode(this.id) as Node<T>;\n node.setIsMainDocument(this._isMainDocument);\n return node;\n }\n\n /**\n * Clones the entire graph connected to this node filtered by the optional predicate. If a node is\n * included by the predicate, all nodes along the paths between the node and the root will be included. If the\n * node this was called on is not included in the resulting filtered graph, the method will throw.\n *\n * This does not clone NetworkNode's `record` or `rawRecord` fields. It may be reasonable to clone the former,\n * to assist in graph construction, but the latter should never be cloned as one contraint of Lantern is that\n * the underlying data records are accessible for plain object reference equality checks.\n */\n cloneWithRelationships(predicate?: (arg0: Node) => boolean): Node {\n const rootNode = this.getRootNode();\n\n const idsToIncludedClones = new Map<string, Node>();\n\n // Walk down dependents.\n rootNode.traverse(node => {\n if (idsToIncludedClones.has(node.id)) {\n return;\n }\n\n if (predicate === undefined) {\n // No condition for entry, so clone every node.\n idsToIncludedClones.set(node.id, node.cloneWithoutRelationships());\n return;\n }\n\n if (predicate(node)) {\n // Node included, so walk back up dependencies, cloning nodes from here back to the root.\n node.traverse(\n node => idsToIncludedClones.set(node.id, node.cloneWithoutRelationships()),\n // Dependencies already cloned have already cloned ancestors, so no need to visit again.\n node => node.dependencies.filter(parent => !idsToIncludedClones.has(parent.id)),\n );\n }\n });\n\n // Copy dependencies between nodes.\n rootNode.traverse(originalNode => {\n const clonedNode = idsToIncludedClones.get(originalNode.id);\n if (!clonedNode) {\n return;\n }\n\n for (const dependency of originalNode.dependencies) {\n const clonedDependency = idsToIncludedClones.get(dependency.id);\n if (!clonedDependency) {\n throw new Core.LanternError('Dependency somehow not cloned');\n }\n clonedNode.addDependency(clonedDependency);\n }\n });\n\n const clonedThisNode = idsToIncludedClones.get(this.id);\n if (!clonedThisNode) {\n throw new Core.LanternError('Cloned graph missing node');\n }\n return clonedThisNode;\n }\n\n /**\n * Traverses all connected nodes in BFS order, calling `callback` exactly once\n * on each. `traversalPath` is the shortest (though not necessarily unique)\n * path from `node` to the root of the iteration.\n *\n * The `getNextNodes` function takes a visited node and returns which nodes to\n * visit next. It defaults to returning the node's dependents.\n */\n traverse(callback: (node: Node<T>, traversalPath: Node<T>[]) => void, getNextNodes?: (arg0: Node<T>) => Node<T>[]):\n void {\n for (const {node, traversalPath} of this.traverseGenerator(getNextNodes)) {\n callback(node, traversalPath);\n }\n }\n\n /**\n * @see BaseNode.traverse\n */\n // clang-format off\n *traverseGenerator(getNextNodes?: (arg0: Node) => Node[]):\n Generator<{node: Node, traversalPath: Node[]}, void, unknown> {\n // clang-format on\n if (!getNextNodes) {\n getNextNodes = node => node.getDependents();\n }\n\n // @ts-expect-error - only traverses graphs of Node, so force tsc to treat `this` as one\n const queue: Node[][] = [[this]];\n const visited = new Set([this.id]);\n\n while (queue.length) {\n // @ts-expect-error - queue has length so it's guaranteed to have an item\n const traversalPath: Node[] = queue.shift();\n const node = traversalPath[0];\n yield {node, traversalPath};\n\n for (const nextNode of getNextNodes(node)) {\n if (visited.has(nextNode.id)) {\n continue;\n }\n visited.add(nextNode.id);\n\n queue.push([nextNode, ...traversalPath]);\n }\n }\n }\n\n /**\n * Returns whether the given node has a cycle in its dependent graph by performing a DFS.\n */\n static hasCycle(node: Node, direction: 'dependents'|'dependencies'|'both' = 'both'): boolean {\n // Checking 'both' is the default entrypoint to recursively check both directions\n if (direction === 'both') {\n return BaseNode.hasCycle(node, 'dependents') || BaseNode.hasCycle(node, 'dependencies');\n }\n\n const visited = new Set();\n const currentPath: BaseNode[] = [];\n const toVisit = [node];\n const depthAdded = new Map([[node, 0]]);\n\n // Keep going while we have nodes to visit in the stack\n while (toVisit.length) {\n // Get the last node in the stack (DFS uses stack, not queue)\n // @ts-expect-error - toVisit has length so it's guaranteed to have an item\n const currentNode: BaseNode = toVisit.pop();\n\n // We've hit a cycle if the node we're visiting is in our current dependency path\n if (currentPath.includes(currentNode)) {\n return true;\n }\n // If we've already visited the node, no need to revisit it\n if (visited.has(currentNode)) {\n continue;\n }\n\n // Since we're visiting this node, clear out any nodes in our path that we had to backtrack\n // @ts-expect-error\n while (currentPath.length > depthAdded.get(currentNode)) {\n currentPath.pop();\n }\n\n // Update our data structures to reflect that we're adding this node to our path\n visited.add(currentNode);\n currentPath.push(currentNode);\n\n // Add all of its dependents to our toVisit stack\n const nodesToExplore = direction === 'dependents' ? currentNode.dependents : currentNode.dependencies;\n for (const nextNode of nodesToExplore) {\n if (toVisit.includes(nextNode)) {\n continue;\n }\n toVisit.push(nextNode);\n depthAdded.set(nextNode, currentPath.length);\n }\n }\n\n return false;\n }\n\n canDependOn(node: Node): boolean {\n return node.startTime <= this.startTime;\n }\n}\n\nexport {BaseNode};\n"]}
1
+ {"version":3,"file":"BaseNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/BaseNode.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 Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport type {CPUNode} from './CPUNode.js';\nimport type {NetworkNode} from './NetworkNode.js';\n\n/**\n * A union of all types derived from BaseNode, allowing type check discrimination\n * based on `node.type`. If a new node type is created, it should be added here.\n */\nexport type Node<T = Lantern.AnyNetworkObject> = CPUNode<T>|NetworkNode<T>;\n\n/**\n * @fileoverview This class encapsulates logic for handling resources and tasks used to model the\n * execution dependency graph of the page. A node has a unique identifier and can depend on other\n * nodes/be depended on. The construction of the graph maintains some important invariants that are\n * inherent to the model:\n *\n * 1. The graph is a DAG, there are no cycles.\n * 2. There is always a root node upon which all other nodes eventually depend.\n *\n * This allows particular optimizations in this class so that we do no need to check for cycles as\n * these methods are called and we can always start traversal at the root node.\n */\n\nclass BaseNode<T = Lantern.AnyNetworkObject> {\n static types = {\n NETWORK: 'network',\n CPU: 'cpu',\n } as const;\n\n _id: string;\n _isMainDocument: boolean;\n dependents: Node[];\n dependencies: Node[];\n\n constructor(id: string) {\n this._id = id;\n this._isMainDocument = false;\n this.dependents = [];\n this.dependencies = [];\n }\n\n get id(): string {\n return this._id;\n }\n\n get type(): 'network'|'cpu' {\n throw new Core.LanternError('Unimplemented');\n }\n\n /**\n * In microseconds\n */\n get startTime(): number {\n throw new Core.LanternError('Unimplemented');\n }\n\n /**\n * In microseconds\n */\n get endTime(): number {\n throw new Core.LanternError('Unimplemented');\n }\n\n setIsMainDocument(value: boolean): void {\n this._isMainDocument = value;\n }\n\n isMainDocument(): boolean {\n return this._isMainDocument;\n }\n\n getDependents(): Node[] {\n return this.dependents.slice();\n }\n\n getNumberOfDependents(): number {\n return this.dependents.length;\n }\n\n getDependencies(): Node[] {\n return this.dependencies.slice();\n }\n\n getNumberOfDependencies(): number {\n return this.dependencies.length;\n }\n\n getRootNode(): Node<T> {\n let rootNode = this as BaseNode as Node;\n while (rootNode.dependencies.length) {\n rootNode = rootNode.dependencies[0];\n }\n\n return rootNode;\n }\n\n addDependent(node: Node): void {\n node.addDependency(this as BaseNode as Node);\n }\n\n addDependency(node: Node): void {\n // @ts-expect-error - in checkJs, ts doesn't know that CPUNode and NetworkNode *are* BaseNodes.\n if (node === this) {\n throw new Core.LanternError('Cannot add dependency on itself');\n }\n\n if (this.dependencies.includes(node)) {\n return;\n }\n\n node.dependents.push(this as BaseNode as Node);\n this.dependencies.push(node);\n }\n\n removeDependent(node: Node): void {\n node.removeDependency(this as BaseNode as Node);\n }\n\n removeDependency(node: Node): void {\n if (!this.dependencies.includes(node)) {\n return;\n }\n\n const thisIndex = node.dependents.indexOf(this as BaseNode as Node);\n node.dependents.splice(thisIndex, 1);\n this.dependencies.splice(this.dependencies.indexOf(node), 1);\n }\n\n removeAllDependencies(): void {\n for (const node of this.dependencies.slice()) {\n this.removeDependency(node);\n }\n }\n\n /**\n * Computes whether the given node is anywhere in the dependency graph of this node.\n * While this method can prevent cycles, it walks the graph and should be used sparingly.\n * Nodes are always considered dependent on themselves for the purposes of cycle detection.\n */\n isDependentOn(node: BaseNode<T>): boolean {\n let isDependentOnNode = false;\n this.traverse(\n currentNode => {\n if (isDependentOnNode) {\n return;\n }\n isDependentOnNode = currentNode === node;\n },\n currentNode => {\n // If we've already found the dependency, don't traverse further.\n if (isDependentOnNode) {\n return [];\n }\n // Otherwise, traverse the dependencies.\n return currentNode.getDependencies();\n });\n\n return isDependentOnNode;\n }\n\n /**\n * Clones the node's information without adding any dependencies/dependents.\n */\n cloneWithoutRelationships(): Node<T> {\n const node = new BaseNode(this.id) as Node<T>;\n node.setIsMainDocument(this._isMainDocument);\n return node;\n }\n\n /**\n * Clones the entire graph connected to this node filtered by the optional predicate. If a node is\n * included by the predicate, all nodes along the paths between the node and the root will be included. If the\n * node this was called on is not included in the resulting filtered graph, the method will throw.\n *\n * This does not clone NetworkNode's `record` or `rawRecord` fields. It may be reasonable to clone the former,\n * to assist in graph construction, but the latter should never be cloned as one constraint of Lantern is that\n * the underlying data records are accessible for plain object reference equality checks.\n */\n cloneWithRelationships(predicate?: (arg0: Node) => boolean): Node {\n const rootNode = this.getRootNode();\n\n const idsToIncludedClones = new Map<string, Node>();\n\n // Walk down dependents.\n rootNode.traverse(node => {\n if (idsToIncludedClones.has(node.id)) {\n return;\n }\n\n if (predicate === undefined) {\n // No condition for entry, so clone every node.\n idsToIncludedClones.set(node.id, node.cloneWithoutRelationships());\n return;\n }\n\n if (predicate(node)) {\n // Node included, so walk back up dependencies, cloning nodes from here back to the root.\n node.traverse(\n node => idsToIncludedClones.set(node.id, node.cloneWithoutRelationships()),\n // Dependencies already cloned have already cloned ancestors, so no need to visit again.\n node => node.dependencies.filter(parent => !idsToIncludedClones.has(parent.id)),\n );\n }\n });\n\n // Copy dependencies between nodes.\n rootNode.traverse(originalNode => {\n const clonedNode = idsToIncludedClones.get(originalNode.id);\n if (!clonedNode) {\n return;\n }\n\n for (const dependency of originalNode.dependencies) {\n const clonedDependency = idsToIncludedClones.get(dependency.id);\n if (!clonedDependency) {\n throw new Core.LanternError('Dependency somehow not cloned');\n }\n clonedNode.addDependency(clonedDependency);\n }\n });\n\n const clonedThisNode = idsToIncludedClones.get(this.id);\n if (!clonedThisNode) {\n throw new Core.LanternError('Cloned graph missing node');\n }\n return clonedThisNode;\n }\n\n /**\n * Traverses all connected nodes in BFS order, calling `callback` exactly once\n * on each. `traversalPath` is the shortest (though not necessarily unique)\n * path from `node` to the root of the iteration.\n *\n * The `getNextNodes` function takes a visited node and returns which nodes to\n * visit next. It defaults to returning the node's dependents.\n */\n traverse(callback: (node: Node<T>, traversalPath: Node<T>[]) => void, getNextNodes?: (arg0: Node<T>) => Node<T>[]):\n void {\n for (const {node, traversalPath} of this.traverseGenerator(getNextNodes)) {\n callback(node, traversalPath);\n }\n }\n\n /**\n * @see BaseNode.traverse\n */\n // clang-format off\n *traverseGenerator(getNextNodes?: (arg0: Node) => Node[]):\n Generator<{node: Node, traversalPath: Node[]}, void, unknown> {\n // clang-format on\n if (!getNextNodes) {\n getNextNodes = node => node.getDependents();\n }\n\n // @ts-expect-error - only traverses graphs of Node, so force tsc to treat `this` as one\n const queue: Node[][] = [[this]];\n const visited = new Set([this.id]);\n\n while (queue.length) {\n // @ts-expect-error - queue has length so it's guaranteed to have an item\n const traversalPath: Node[] = queue.shift();\n const node = traversalPath[0];\n yield {node, traversalPath};\n\n for (const nextNode of getNextNodes(node)) {\n if (visited.has(nextNode.id)) {\n continue;\n }\n visited.add(nextNode.id);\n\n queue.push([nextNode, ...traversalPath]);\n }\n }\n }\n\n /**\n * Returns whether the given node has a cycle in its dependent graph by performing a DFS.\n */\n static hasCycle(node: Node, direction: 'dependents'|'dependencies'|'both' = 'both'): boolean {\n // Checking 'both' is the default entrypoint to recursively check both directions\n if (direction === 'both') {\n return BaseNode.hasCycle(node, 'dependents') || BaseNode.hasCycle(node, 'dependencies');\n }\n\n const visited = new Set();\n const currentPath: BaseNode[] = [];\n const toVisit = [node];\n const depthAdded = new Map([[node, 0]]);\n\n // Keep going while we have nodes to visit in the stack\n while (toVisit.length) {\n // Get the last node in the stack (DFS uses stack, not queue)\n // @ts-expect-error - toVisit has length so it's guaranteed to have an item\n const currentNode: BaseNode = toVisit.pop();\n\n // We've hit a cycle if the node we're visiting is in our current dependency path\n if (currentPath.includes(currentNode)) {\n return true;\n }\n // If we've already visited the node, no need to revisit it\n if (visited.has(currentNode)) {\n continue;\n }\n\n // Since we're visiting this node, clear out any nodes in our path that we had to backtrack\n // @ts-expect-error\n while (currentPath.length > depthAdded.get(currentNode)) {\n currentPath.pop();\n }\n\n // Update our data structures to reflect that we're adding this node to our path\n visited.add(currentNode);\n currentPath.push(currentNode);\n\n // Add all of its dependents to our toVisit stack\n const nodesToExplore = direction === 'dependents' ? currentNode.dependents : currentNode.dependencies;\n for (const nextNode of nodesToExplore) {\n if (toVisit.includes(nextNode)) {\n continue;\n }\n toVisit.push(nextNode);\n depthAdded.set(nextNode, currentPath.length);\n }\n }\n\n return false;\n }\n\n canDependOn(node: Node): boolean {\n return node.startTime <= this.startTime;\n }\n}\n\nexport {BaseNode};\n"]}
@@ -1,5 +1,5 @@
1
- import { BaseNode } from './BaseNode.js';
2
1
  import type * as Lantern from '../types/types.js';
2
+ import { BaseNode } from './BaseNode.js';
3
3
  declare class CPUNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {
4
4
  _event: Lantern.TraceEvent;
5
5
  _childEvents: Lantern.TraceEvent[];
@@ -1 +1 @@
1
- {"version":3,"file":"CPUNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/CPUNode.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAGvC,MAAM,OAAsC,SAAQ,QAAW;IAC7D,MAAM,CAAqB;IAC3B,YAAY,CAAuB;IACnC,cAAc,CAAmB;IAEjC,YAAY,WAA+B,EAAE,cAAoC,EAAE,EAAE,cAAuB;QAC1G,MAAM,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,CAAC;QACtD,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED,IAAa,IAAI;QACf,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;IAC5B,CAAC;IAED,IAAa,SAAS;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACxB,CAAC;IAED,IAAa,OAAO;QAClB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,cAAc,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;IACvC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,yBAAyB;QAChC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1E,CAAC;CACF;AAED,OAAO,EAAC,OAAO,EAAC,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 {BaseNode} from './BaseNode.js';\nimport type * as Lantern from '../types/types.js';\n\nclass CPUNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {\n _event: Lantern.TraceEvent;\n _childEvents: Lantern.TraceEvent[];\n correctedEndTs: number|undefined;\n\n constructor(parentEvent: Lantern.TraceEvent, childEvents: Lantern.TraceEvent[] = [], correctedEndTs?: number) {\n const nodeId = `${parentEvent.tid}.${parentEvent.ts}`;\n super(nodeId);\n\n this._event = parentEvent;\n this._childEvents = childEvents;\n this.correctedEndTs = correctedEndTs;\n }\n\n override get type(): 'cpu' {\n return BaseNode.types.CPU;\n }\n\n override get startTime(): number {\n return this._event.ts;\n }\n\n override get endTime(): number {\n if (this.correctedEndTs) {\n return this.correctedEndTs;\n }\n return this._event.ts + this._event.dur;\n }\n\n get duration(): number {\n return this.endTime - this.startTime;\n }\n\n get event(): Lantern.TraceEvent {\n return this._event;\n }\n\n get childEvents(): Lantern.TraceEvent[] {\n return this._childEvents;\n }\n\n /**\n * Returns true if this node contains a Layout task.\n */\n didPerformLayout(): boolean {\n return this._childEvents.some(evt => evt.name === 'Layout');\n }\n\n /**\n * Returns the script URLs that had their EvaluateScript events occur in this task.\n */\n getEvaluateScriptURLs(): Set<string> {\n const urls = new Set<string>();\n for (const event of this._childEvents) {\n if (event.name !== 'EvaluateScript') {\n continue;\n }\n if (!event.args.data || !event.args.data.url) {\n continue;\n }\n urls.add(event.args.data.url);\n }\n\n return urls;\n }\n\n override cloneWithoutRelationships(): CPUNode {\n return new CPUNode(this._event, this._childEvents, this.correctedEndTs);\n }\n}\n\nexport {CPUNode};\n"]}
1
+ {"version":3,"file":"CPUNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/CPUNode.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAEvC,MAAM,OAAsC,SAAQ,QAAW;IAC7D,MAAM,CAAqB;IAC3B,YAAY,CAAuB;IACnC,cAAc,CAAmB;IAEjC,YAAY,WAA+B,EAAE,cAAoC,EAAE,EAAE,cAAuB;QAC1G,MAAM,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,CAAC;QACtD,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED,IAAa,IAAI;QACf,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;IAC5B,CAAC;IAED,IAAa,SAAS;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACxB,CAAC;IAED,IAAa,OAAO;QAClB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,cAAc,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;IACvC,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,yBAAyB;QAChC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1E,CAAC;CACF;AAED,OAAO,EAAC,OAAO,EAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Lantern from '../types/types.js';\n\nimport {BaseNode} from './BaseNode.js';\n\nclass CPUNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {\n _event: Lantern.TraceEvent;\n _childEvents: Lantern.TraceEvent[];\n correctedEndTs: number|undefined;\n\n constructor(parentEvent: Lantern.TraceEvent, childEvents: Lantern.TraceEvent[] = [], correctedEndTs?: number) {\n const nodeId = `${parentEvent.tid}.${parentEvent.ts}`;\n super(nodeId);\n\n this._event = parentEvent;\n this._childEvents = childEvents;\n this.correctedEndTs = correctedEndTs;\n }\n\n override get type(): 'cpu' {\n return BaseNode.types.CPU;\n }\n\n override get startTime(): number {\n return this._event.ts;\n }\n\n override get endTime(): number {\n if (this.correctedEndTs) {\n return this.correctedEndTs;\n }\n return this._event.ts + this._event.dur;\n }\n\n get duration(): number {\n return this.endTime - this.startTime;\n }\n\n get event(): Lantern.TraceEvent {\n return this._event;\n }\n\n get childEvents(): Lantern.TraceEvent[] {\n return this._childEvents;\n }\n\n /**\n * Returns true if this node contains a Layout task.\n */\n didPerformLayout(): boolean {\n return this._childEvents.some(evt => evt.name === 'Layout');\n }\n\n /**\n * Returns the script URLs that had their EvaluateScript events occur in this task.\n */\n getEvaluateScriptURLs(): Set<string> {\n const urls = new Set<string>();\n for (const event of this._childEvents) {\n if (event.name !== 'EvaluateScript') {\n continue;\n }\n if (!event.args.data || !event.args.data.url) {\n continue;\n }\n urls.add(event.args.data.url);\n }\n\n return urls;\n }\n\n override cloneWithoutRelationships(): CPUNode {\n return new CPUNode(this._event, this._childEvents, this.correctedEndTs);\n }\n}\n\nexport {CPUNode};\n"]}
@@ -1,5 +1,5 @@
1
- import { BaseNode } from './BaseNode.js';
2
1
  import type * as Lantern from '../types/types.js';
2
+ import { BaseNode } from './BaseNode.js';
3
3
  declare class NetworkNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {
4
4
  _request: Lantern.NetworkRequest<T>;
5
5
  constructor(networkRequest: Lantern.NetworkRequest<T>);
@@ -1 +1 @@
1
- {"version":3,"file":"NetworkNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/NetworkNode.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 {BaseNode} from './BaseNode.js';\nimport type * as Lantern from '../types/types.js';\n\nconst NON_NETWORK_SCHEMES = [\n 'blob', // @see https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL\n 'data', // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n 'intent', // @see https://developer.chrome.com/docs/multidevice/android/intents/\n 'file', // @see https://en.wikipedia.org/wiki/File_URI_scheme\n 'filesystem', // @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystem\n 'chrome-extension',\n];\n\n/**\n * Note: the `protocol` field from CDP can be 'h2', 'http', (not 'https'!) or it'll be url's scheme.\n * https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/protocol/network_handler.cc;l=598-611;drc=56d4a9a9deb30be73adcee8737c73bcb2a5ab64f\n * However, a `new URL(href).protocol` has a colon suffix.\n * https://url.spec.whatwg.org/#dom-url-protocol\n * A URL's `scheme` is specced as the `protocol` sans-colon, but isn't exposed on a URL object.\n * This method can take all 3 of these string types as a parameter.\n *\n * @param protocol Either a networkRequest's `protocol` per CDP or a `new URL(href).protocol`\n */\nfunction isNonNetworkProtocol(protocol: string): boolean {\n // Strip off any colon\n const urlScheme = protocol.includes(':') ? protocol.slice(0, protocol.indexOf(':')) : protocol;\n return NON_NETWORK_SCHEMES.includes(urlScheme);\n}\n\nclass NetworkNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {\n _request: Lantern.NetworkRequest<T>;\n\n constructor(networkRequest: Lantern.NetworkRequest<T>) {\n super(networkRequest.requestId);\n this._request = networkRequest;\n }\n\n override get type(): 'network' {\n return BaseNode.types.NETWORK;\n }\n\n override get startTime(): number {\n return this._request.rendererStartTime * 1000;\n }\n\n override get endTime(): number {\n return this._request.networkEndTime * 1000;\n }\n\n get rawRequest(): Readonly<T> {\n return this._request.rawRequest as Required<T>;\n }\n\n get request(): Lantern.NetworkRequest<T> {\n return this._request;\n }\n\n get initiatorType(): string {\n return this._request.initiator && this._request.initiator.type;\n }\n\n get fromDiskCache(): boolean {\n return Boolean(this._request.fromDiskCache);\n }\n\n get isNonNetworkProtocol(): boolean {\n // The 'protocol' field in devtools a string more like a `scheme`\n return isNonNetworkProtocol(this.request.protocol) ||\n // But `protocol` can fail to be populated if the request fails, so fallback to scheme.\n isNonNetworkProtocol(this.request.parsedURL.scheme);\n }\n\n /**\n * Returns whether this network request can be downloaded without a TCP connection.\n * During simulation we treat data coming in over a network connection separately from on-device data.\n */\n get isConnectionless(): boolean {\n return this.fromDiskCache || this.isNonNetworkProtocol;\n }\n\n hasRenderBlockingPriority(): boolean {\n const priority = this._request.priority;\n const isScript = this._request.resourceType === 'Script';\n const isDocument = this._request.resourceType === 'Document';\n const isBlockingScript = priority === 'High' && isScript;\n const isBlockingHtmlImport = priority === 'High' && isDocument;\n return priority === 'VeryHigh' || isBlockingScript || isBlockingHtmlImport;\n }\n\n override cloneWithoutRelationships(): NetworkNode<T> {\n const node = new NetworkNode(this._request);\n node.setIsMainDocument(this._isMainDocument);\n return node;\n }\n}\n\nexport {NetworkNode};\n"]}
1
+ {"version":3,"file":"NetworkNode.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/NetworkNode.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Lantern from '../types/types.js';\n\nimport {BaseNode} from './BaseNode.js';\n\nconst NON_NETWORK_SCHEMES = [\n 'blob', // @see https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL\n 'data', // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs\n 'intent', // @see https://developer.chrome.com/docs/multidevice/android/intents/\n 'file', // @see https://en.wikipedia.org/wiki/File_URI_scheme\n 'filesystem', // @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystem\n 'chrome-extension',\n];\n\n/**\n * Note: the `protocol` field from CDP can be 'h2', 'http', (not 'https'!) or it'll be url's scheme.\n * https://source.chromium.org/chromium/chromium/src/+/main:content/browser/devtools/protocol/network_handler.cc;l=598-611;drc=56d4a9a9deb30be73adcee8737c73bcb2a5ab64f\n * However, a `new URL(href).protocol` has a colon suffix.\n * https://url.spec.whatwg.org/#dom-url-protocol\n * A URL's `scheme` is specced as the `protocol` sans-colon, but isn't exposed on a URL object.\n * This method can take all 3 of these string types as a parameter.\n *\n * @param protocol Either a networkRequest's `protocol` per CDP or a `new URL(href).protocol`\n */\nfunction isNonNetworkProtocol(protocol: string): boolean {\n // Strip off any colon\n const urlScheme = protocol.includes(':') ? protocol.slice(0, protocol.indexOf(':')) : protocol;\n return NON_NETWORK_SCHEMES.includes(urlScheme);\n}\n\nclass NetworkNode<T = Lantern.AnyNetworkObject> extends BaseNode<T> {\n _request: Lantern.NetworkRequest<T>;\n\n constructor(networkRequest: Lantern.NetworkRequest<T>) {\n super(networkRequest.requestId);\n this._request = networkRequest;\n }\n\n override get type(): 'network' {\n return BaseNode.types.NETWORK;\n }\n\n override get startTime(): number {\n return this._request.rendererStartTime * 1000;\n }\n\n override get endTime(): number {\n return this._request.networkEndTime * 1000;\n }\n\n get rawRequest(): Readonly<T> {\n return this._request.rawRequest as Required<T>;\n }\n\n get request(): Lantern.NetworkRequest<T> {\n return this._request;\n }\n\n get initiatorType(): string {\n return this._request.initiator && this._request.initiator.type;\n }\n\n get fromDiskCache(): boolean {\n return Boolean(this._request.fromDiskCache);\n }\n\n get isNonNetworkProtocol(): boolean {\n // The 'protocol' field in devtools a string more like a `scheme`\n return isNonNetworkProtocol(this.request.protocol) ||\n // But `protocol` can fail to be populated if the request fails, so fallback to scheme.\n isNonNetworkProtocol(this.request.parsedURL.scheme);\n }\n\n /**\n * Returns whether this network request can be downloaded without a TCP connection.\n * During simulation we treat data coming in over a network connection separately from on-device data.\n */\n get isConnectionless(): boolean {\n return this.fromDiskCache || this.isNonNetworkProtocol;\n }\n\n hasRenderBlockingPriority(): boolean {\n const priority = this._request.priority;\n const isScript = this._request.resourceType === 'Script';\n const isDocument = this._request.resourceType === 'Document';\n const isBlockingScript = priority === 'High' && isScript;\n const isBlockingHtmlImport = priority === 'High' && isDocument;\n return priority === 'VeryHigh' || isBlockingScript || isBlockingHtmlImport;\n }\n\n override cloneWithoutRelationships(): NetworkNode<T> {\n const node = new NetworkNode(this._request);\n node.setIsMainDocument(this._isMainDocument);\n return node;\n }\n}\n\nexport {NetworkNode};\n"]}
@@ -3,7 +3,7 @@ import type * as Types from '../types/types.js';
3
3
  import { Metric, type MetricCoefficients } from './Metric.js';
4
4
  interface FirstPaintBasedGraphOpts<T> {
5
5
  /**
6
- * The timestamp used to filter out tasks that occured after our paint of interest.
6
+ * The timestamp used to filter out tasks that occurred after our paint of interest.
7
7
  * Typically this is First Contentful Paint or First Meaningful Paint.
8
8
  */
9
9
  cutoffTimestamp: number;
@@ -1 +1 @@
1
- {"version":3,"file":"FirstContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.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 Graph from '../graph/graph.js';\nimport type * as Types from '../types/types.js';\n\nimport {Metric, type MetricCoefficients} from './Metric.js';\n\ninterface FirstPaintBasedGraphOpts<T> {\n /**\n * The timestamp used to filter out tasks that occured after our paint of interest.\n * Typically this is First Contentful Paint or First Meaningful Paint.\n */\n cutoffTimestamp: number;\n /**\n * The function that determines which resources should be considered *possibly*\n * render-blocking.\n */\n treatNodeAsRenderBlocking: (node: Graph.NetworkNode<T>) => boolean;\n /**\n * The function that determines which CPU nodes should also be included in our\n * blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.\n */\n additionalCpuNodesToTreatAsRenderBlocking?: (node: Graph.CPUNode) => boolean;\n}\n\nclass FirstContentfulPaint extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Computes the set of URLs that *appeared* to be render-blocking based on our filter,\n * *but definitely were not* render-blocking based on the timing of their EvaluateScript task.\n * It also computes the set of corresponding CPU node ids that were needed for the paint at the\n * given timestamp.\n */\n static getRenderBlockingNodeData<T = unknown>(\n graph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): {definitelyNotRenderBlockingScriptUrls: Set<string>, renderBlockingCpuNodeIds: Set<string>} {\n /** A map of blocking script URLs to the earliest EvaluateScript task node that executed them. */\n const scriptUrlToNodeMap = new Map<string, Graph.CPUNode>();\n\n const cpuNodes: Graph.CPUNode[] = [];\n graph.traverse(node => {\n if (node.type === Graph.BaseNode.types.CPU) {\n // A task is *possibly* render blocking if it *started* before cutoffTimestamp.\n // We use startTime here because the paint event can be *inside* the task that was render blocking.\n if (node.startTime <= cutoffTimestamp) {\n cpuNodes.push(node);\n }\n\n // Build our script URL map to find the earliest EvaluateScript task node.\n const scriptUrls = node.getEvaluateScriptURLs();\n for (const url of scriptUrls) {\n // Use the earliest CPU node we find.\n const existing = scriptUrlToNodeMap.get(url) || node;\n scriptUrlToNodeMap.set(url, node.startTime < existing.startTime ? node : existing);\n }\n }\n });\n\n cpuNodes.sort((a, b) => a.startTime - b.startTime);\n\n // A script is *possibly* render blocking if it finished loading before cutoffTimestamp.\n const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {\n // The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,\n // but here it only receives scripts to evaluate. It's a no-op in this case, but it will\n // matter below in the getFirstPaintBasedGraph clone operation.\n return node.endTime <= cutoffTimestamp && treatNodeAsRenderBlocking(node);\n });\n\n // A script is *definitely not* render blocking if its EvaluateScript task started after cutoffTimestamp.\n const definitelyNotRenderBlockingScriptUrls = new Set<string>();\n const renderBlockingCpuNodeIds = new Set<string>();\n for (const url of possiblyRenderBlockingScriptUrls) {\n // Lookup the CPU node that had the earliest EvaluateScript for this URL.\n const cpuNodeForUrl = scriptUrlToNodeMap.get(url);\n\n // If we can't find it at all, we can't conclude anything, so just skip it.\n if (!cpuNodeForUrl) {\n continue;\n }\n\n // If we found it and it was in our `cpuNodes` set that means it finished before cutoffTimestamp, so it really is render-blocking.\n if (cpuNodes.includes(cpuNodeForUrl)) {\n renderBlockingCpuNodeIds.add(cpuNodeForUrl.id);\n continue;\n }\n\n // We couldn't find the evaluate script in the set of CPU nodes that ran before our paint, so\n // it must not have been necessary for the paint.\n definitelyNotRenderBlockingScriptUrls.add(url);\n }\n\n // The first layout, first paint, and first ParseHTML are almost always necessary for first paint,\n // so we always include those CPU nodes.\n const firstLayout = cpuNodes.find(node => node.didPerformLayout());\n if (firstLayout) {\n renderBlockingCpuNodeIds.add(firstLayout.id);\n }\n const firstPaint = cpuNodes.find(node => node.childEvents.some(e => e.name === 'Paint'));\n if (firstPaint) {\n renderBlockingCpuNodeIds.add(firstPaint.id);\n }\n const firstParse = cpuNodes.find(node => node.childEvents.some(e => e.name === 'ParseHTML'));\n if (firstParse) {\n renderBlockingCpuNodeIds.add(firstParse.id);\n }\n\n // If a CPU filter was passed in, we also want to include those extra nodes.\n if (additionalCpuNodesToTreatAsRenderBlocking) {\n cpuNodes.filter(additionalCpuNodesToTreatAsRenderBlocking).forEach(node => renderBlockingCpuNodeIds.add(node.id));\n }\n\n return {\n definitelyNotRenderBlockingScriptUrls,\n renderBlockingCpuNodeIds,\n };\n }\n\n /**\n * Computes the graph required for the first paint of interest.\n */\n static getFirstPaintBasedGraph<T>(\n dependencyGraph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): Graph.Node<T> {\n const rbData = this.getRenderBlockingNodeData(dependencyGraph, {\n cutoffTimestamp,\n treatNodeAsRenderBlocking,\n additionalCpuNodesToTreatAsRenderBlocking,\n });\n const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;\n\n return dependencyGraph.cloneWithRelationships(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n // Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)\n // endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.\n const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;\n if (endedAfterPaint && !node.isMainDocument()) {\n return false;\n }\n\n const url = node.request.url;\n // If the URL definitely wasn't render-blocking then we filter it out.\n if (definitelyNotRenderBlockingScriptUrls.has(url)) {\n return false;\n }\n\n // Lastly, build up the FCP graph of all nodes we consider render blocking\n return treatNodeAsRenderBlocking(node);\n }\n // If it's a CPU node, just check if it was blocking.\n return renderBlockingCpuNodeIds.has(node.id);\n });\n }\n\n static override getOptimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n // In the optimistic graph we exclude resources that appeared to be render blocking but were\n // initiated by a script. While they typically have a very high importance and tend to have a\n // significant impact on the page's content, these resources don't technically block rendering.\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority() && node.initiatorType !== 'script',\n });\n }\n\n static override getPessimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority(),\n });\n }\n}\n\nexport {FirstContentfulPaint};\n"]}
1
+ {"version":3,"file":"FirstContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.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 Graph from '../graph/graph.js';\nimport type * as Types from '../types/types.js';\n\nimport {Metric, type MetricCoefficients} from './Metric.js';\n\ninterface FirstPaintBasedGraphOpts<T> {\n /**\n * The timestamp used to filter out tasks that occurred after our paint of interest.\n * Typically this is First Contentful Paint or First Meaningful Paint.\n */\n cutoffTimestamp: number;\n /**\n * The function that determines which resources should be considered *possibly*\n * render-blocking.\n */\n treatNodeAsRenderBlocking: (node: Graph.NetworkNode<T>) => boolean;\n /**\n * The function that determines which CPU nodes should also be included in our\n * blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.\n */\n additionalCpuNodesToTreatAsRenderBlocking?: (node: Graph.CPUNode) => boolean;\n}\n\nclass FirstContentfulPaint extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Computes the set of URLs that *appeared* to be render-blocking based on our filter,\n * *but definitely were not* render-blocking based on the timing of their EvaluateScript task.\n * It also computes the set of corresponding CPU node ids that were needed for the paint at the\n * given timestamp.\n */\n static getRenderBlockingNodeData<T = unknown>(\n graph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): {definitelyNotRenderBlockingScriptUrls: Set<string>, renderBlockingCpuNodeIds: Set<string>} {\n /** A map of blocking script URLs to the earliest EvaluateScript task node that executed them. */\n const scriptUrlToNodeMap = new Map<string, Graph.CPUNode>();\n\n const cpuNodes: Graph.CPUNode[] = [];\n graph.traverse(node => {\n if (node.type === Graph.BaseNode.types.CPU) {\n // A task is *possibly* render blocking if it *started* before cutoffTimestamp.\n // We use startTime here because the paint event can be *inside* the task that was render blocking.\n if (node.startTime <= cutoffTimestamp) {\n cpuNodes.push(node);\n }\n\n // Build our script URL map to find the earliest EvaluateScript task node.\n const scriptUrls = node.getEvaluateScriptURLs();\n for (const url of scriptUrls) {\n // Use the earliest CPU node we find.\n const existing = scriptUrlToNodeMap.get(url) || node;\n scriptUrlToNodeMap.set(url, node.startTime < existing.startTime ? node : existing);\n }\n }\n });\n\n cpuNodes.sort((a, b) => a.startTime - b.startTime);\n\n // A script is *possibly* render blocking if it finished loading before cutoffTimestamp.\n const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {\n // The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,\n // but here it only receives scripts to evaluate. It's a no-op in this case, but it will\n // matter below in the getFirstPaintBasedGraph clone operation.\n return node.endTime <= cutoffTimestamp && treatNodeAsRenderBlocking(node);\n });\n\n // A script is *definitely not* render blocking if its EvaluateScript task started after cutoffTimestamp.\n const definitelyNotRenderBlockingScriptUrls = new Set<string>();\n const renderBlockingCpuNodeIds = new Set<string>();\n for (const url of possiblyRenderBlockingScriptUrls) {\n // Lookup the CPU node that had the earliest EvaluateScript for this URL.\n const cpuNodeForUrl = scriptUrlToNodeMap.get(url);\n\n // If we can't find it at all, we can't conclude anything, so just skip it.\n if (!cpuNodeForUrl) {\n continue;\n }\n\n // If we found it and it was in our `cpuNodes` set that means it finished before cutoffTimestamp, so it really is render-blocking.\n if (cpuNodes.includes(cpuNodeForUrl)) {\n renderBlockingCpuNodeIds.add(cpuNodeForUrl.id);\n continue;\n }\n\n // We couldn't find the evaluate script in the set of CPU nodes that ran before our paint, so\n // it must not have been necessary for the paint.\n definitelyNotRenderBlockingScriptUrls.add(url);\n }\n\n // The first layout, first paint, and first ParseHTML are almost always necessary for first paint,\n // so we always include those CPU nodes.\n const firstLayout = cpuNodes.find(node => node.didPerformLayout());\n if (firstLayout) {\n renderBlockingCpuNodeIds.add(firstLayout.id);\n }\n const firstPaint = cpuNodes.find(node => node.childEvents.some(e => e.name === 'Paint'));\n if (firstPaint) {\n renderBlockingCpuNodeIds.add(firstPaint.id);\n }\n const firstParse = cpuNodes.find(node => node.childEvents.some(e => e.name === 'ParseHTML'));\n if (firstParse) {\n renderBlockingCpuNodeIds.add(firstParse.id);\n }\n\n // If a CPU filter was passed in, we also want to include those extra nodes.\n if (additionalCpuNodesToTreatAsRenderBlocking) {\n cpuNodes.filter(additionalCpuNodesToTreatAsRenderBlocking).forEach(node => renderBlockingCpuNodeIds.add(node.id));\n }\n\n return {\n definitelyNotRenderBlockingScriptUrls,\n renderBlockingCpuNodeIds,\n };\n }\n\n /**\n * Computes the graph required for the first paint of interest.\n */\n static getFirstPaintBasedGraph<T>(\n dependencyGraph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): Graph.Node<T> {\n const rbData = this.getRenderBlockingNodeData(dependencyGraph, {\n cutoffTimestamp,\n treatNodeAsRenderBlocking,\n additionalCpuNodesToTreatAsRenderBlocking,\n });\n const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;\n\n return dependencyGraph.cloneWithRelationships(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n // Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)\n // endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.\n const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;\n if (endedAfterPaint && !node.isMainDocument()) {\n return false;\n }\n\n const url = node.request.url;\n // If the URL definitely wasn't render-blocking then we filter it out.\n if (definitelyNotRenderBlockingScriptUrls.has(url)) {\n return false;\n }\n\n // Lastly, build up the FCP graph of all nodes we consider render blocking\n return treatNodeAsRenderBlocking(node);\n }\n // If it's a CPU node, just check if it was blocking.\n return renderBlockingCpuNodeIds.has(node.id);\n });\n }\n\n static override getOptimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n // In the optimistic graph we exclude resources that appeared to be render blocking but were\n // initiated by a script. While they typically have a very high importance and tend to have a\n // significant impact on the page's content, these resources don't technically block rendering.\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority() && node.initiatorType !== 'script',\n });\n }\n\n static override getPessimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority(),\n });\n }\n}\n\nexport {FirstContentfulPaint};\n"]}
@@ -5,7 +5,7 @@ import * as Core from '../core/core.js';
5
5
  import { TCPConnection } from './TCPConnection.js';
6
6
  const DEFAULT_SERVER_RESPONSE_TIME = 30;
7
7
  const TLS_SCHEMES = ['https', 'wss'];
8
- // Each origin can have 6 simulatenous connections open
8
+ // Each origin can have 6 simultaneous connections open
9
9
  // https://cs.chromium.org/chromium/src/net/socket/client_socket_pool_manager.cc?type=cs&q="int+g_max_sockets_per_group"
10
10
  const CONNECTIONS_PER_ORIGIN = 6;
11
11
  export class ConnectionPool {
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionPool.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.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 Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {TCPConnection} from './TCPConnection.js';\n\nconst DEFAULT_SERVER_RESPONSE_TIME = 30;\nconst TLS_SCHEMES = ['https', 'wss'];\n\n// Each origin can have 6 simulatenous connections open\n// https://cs.chromium.org/chromium/src/net/socket/client_socket_pool_manager.cc?type=cs&q=\"int+g_max_sockets_per_group\"\nconst CONNECTIONS_PER_ORIGIN = 6;\n\nexport class ConnectionPool {\n options: Required<Lantern.Simulation.Options>;\n records: Lantern.NetworkRequest[];\n connectionsByOrigin: Map<string, TCPConnection[]>;\n connectionsByRequest: Map<Lantern.NetworkRequest, TCPConnection>;\n _connectionsInUse: Set<TCPConnection>;\n connectionReusedByRequestId: Map<string, boolean>;\n\n constructor(records: Lantern.NetworkRequest[], options: Required<Lantern.Simulation.Options>) {\n this.options = options;\n\n this.records = records;\n this.connectionsByOrigin = new Map();\n this.connectionsByRequest = new Map();\n this._connectionsInUse = new Set();\n this.connectionReusedByRequestId = Core.NetworkAnalyzer.estimateIfConnectionWasReused(records, {\n forceCoarseEstimates: true,\n });\n\n this.initializeConnections();\n }\n\n connectionsInUse(): TCPConnection[] {\n return Array.from(this._connectionsInUse);\n }\n\n initializeConnections(): void {\n const connectionReused = this.connectionReusedByRequestId;\n const additionalRttByOrigin = this.options.additionalRttByOrigin;\n const serverResponseTimeByOrigin = this.options.serverResponseTimeByOrigin;\n\n const recordsByOrigin = Core.NetworkAnalyzer.groupByOrigin(this.records);\n for (const [origin, requests] of recordsByOrigin.entries()) {\n const connections = [];\n const additionalRtt = additionalRttByOrigin.get(origin) || 0;\n const responseTime = serverResponseTimeByOrigin.get(origin) || DEFAULT_SERVER_RESPONSE_TIME;\n\n for (const request of requests) {\n if (connectionReused.get(request.requestId)) {\n continue;\n }\n\n const isTLS = TLS_SCHEMES.includes(request.parsedURL.scheme);\n const isH2 = request.protocol === 'h2';\n const connection = new TCPConnection(\n this.options.rtt + additionalRtt,\n this.options.throughput,\n responseTime,\n isTLS,\n isH2,\n );\n\n connections.push(connection);\n }\n\n if (!connections.length) {\n throw new Core.LanternError(`Could not find a connection for origin: ${origin}`);\n }\n\n // Make sure each origin has minimum number of connections available for max throughput.\n // But only if it's not over H2 which maximizes throughput already.\n const minConnections = connections[0].isH2() ? 1 : CONNECTIONS_PER_ORIGIN;\n while (connections.length < minConnections) {\n connections.push(connections[0].clone());\n }\n\n this.connectionsByOrigin.set(origin, connections);\n }\n }\n\n findAvailableConnectionWithLargestCongestionWindow(connections: TCPConnection[]): TCPConnection|null {\n let maxConnection: TCPConnection|null = null;\n for (let i = 0; i < connections.length; i++) {\n const connection = connections[i];\n\n // Connections that are in use are never available.\n if (this._connectionsInUse.has(connection)) {\n continue;\n }\n\n // This connection is a match and is available! Update our max if it has a larger congestionWindow\n const currentMax = (maxConnection?.congestionWindow) || -Infinity;\n if (connection.congestionWindow > currentMax) {\n maxConnection = connection;\n }\n }\n\n return maxConnection;\n }\n\n /**\n * This method finds an available connection to the origin specified by the network request or null\n * if no connection was available. If returned, connection will not be available for other network\n * records until release is called.\n */\n acquire(request: Lantern.NetworkRequest): TCPConnection|null {\n if (this.connectionsByRequest.has(request)) {\n throw new Core.LanternError('Record already has a connection');\n }\n\n const origin = request.parsedURL.securityOrigin;\n const connections = this.connectionsByOrigin.get(origin) || [];\n const connectionToUse = this.findAvailableConnectionWithLargestCongestionWindow(connections);\n\n if (!connectionToUse) {\n return null;\n }\n\n this._connectionsInUse.add(connectionToUse);\n this.connectionsByRequest.set(request, connectionToUse);\n return connectionToUse;\n }\n\n /**\n * Return the connection currently being used to fetch a request. If no connection\n * currently being used for this request, an error will be thrown.\n */\n acquireActiveConnectionFromRequest(request: Lantern.NetworkRequest): TCPConnection {\n const activeConnection = this.connectionsByRequest.get(request);\n if (!activeConnection) {\n throw new Core.LanternError('Could not find an active connection for request');\n }\n\n return activeConnection;\n }\n\n release(request: Lantern.NetworkRequest): void {\n const connection = this.connectionsByRequest.get(request);\n this.connectionsByRequest.delete(request);\n if (connection) {\n this._connectionsInUse.delete(connection);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"ConnectionPool.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.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 Core from '../core/core.js';\nimport type * as Lantern from '../types/types.js';\n\nimport {TCPConnection} from './TCPConnection.js';\n\nconst DEFAULT_SERVER_RESPONSE_TIME = 30;\nconst TLS_SCHEMES = ['https', 'wss'];\n\n// Each origin can have 6 simultaneous connections open\n// https://cs.chromium.org/chromium/src/net/socket/client_socket_pool_manager.cc?type=cs&q=\"int+g_max_sockets_per_group\"\nconst CONNECTIONS_PER_ORIGIN = 6;\n\nexport class ConnectionPool {\n options: Required<Lantern.Simulation.Options>;\n records: Lantern.NetworkRequest[];\n connectionsByOrigin: Map<string, TCPConnection[]>;\n connectionsByRequest: Map<Lantern.NetworkRequest, TCPConnection>;\n _connectionsInUse: Set<TCPConnection>;\n connectionReusedByRequestId: Map<string, boolean>;\n\n constructor(records: Lantern.NetworkRequest[], options: Required<Lantern.Simulation.Options>) {\n this.options = options;\n\n this.records = records;\n this.connectionsByOrigin = new Map();\n this.connectionsByRequest = new Map();\n this._connectionsInUse = new Set();\n this.connectionReusedByRequestId = Core.NetworkAnalyzer.estimateIfConnectionWasReused(records, {\n forceCoarseEstimates: true,\n });\n\n this.initializeConnections();\n }\n\n connectionsInUse(): TCPConnection[] {\n return Array.from(this._connectionsInUse);\n }\n\n initializeConnections(): void {\n const connectionReused = this.connectionReusedByRequestId;\n const additionalRttByOrigin = this.options.additionalRttByOrigin;\n const serverResponseTimeByOrigin = this.options.serverResponseTimeByOrigin;\n\n const recordsByOrigin = Core.NetworkAnalyzer.groupByOrigin(this.records);\n for (const [origin, requests] of recordsByOrigin.entries()) {\n const connections = [];\n const additionalRtt = additionalRttByOrigin.get(origin) || 0;\n const responseTime = serverResponseTimeByOrigin.get(origin) || DEFAULT_SERVER_RESPONSE_TIME;\n\n for (const request of requests) {\n if (connectionReused.get(request.requestId)) {\n continue;\n }\n\n const isTLS = TLS_SCHEMES.includes(request.parsedURL.scheme);\n const isH2 = request.protocol === 'h2';\n const connection = new TCPConnection(\n this.options.rtt + additionalRtt,\n this.options.throughput,\n responseTime,\n isTLS,\n isH2,\n );\n\n connections.push(connection);\n }\n\n if (!connections.length) {\n throw new Core.LanternError(`Could not find a connection for origin: ${origin}`);\n }\n\n // Make sure each origin has minimum number of connections available for max throughput.\n // But only if it's not over H2 which maximizes throughput already.\n const minConnections = connections[0].isH2() ? 1 : CONNECTIONS_PER_ORIGIN;\n while (connections.length < minConnections) {\n connections.push(connections[0].clone());\n }\n\n this.connectionsByOrigin.set(origin, connections);\n }\n }\n\n findAvailableConnectionWithLargestCongestionWindow(connections: TCPConnection[]): TCPConnection|null {\n let maxConnection: TCPConnection|null = null;\n for (let i = 0; i < connections.length; i++) {\n const connection = connections[i];\n\n // Connections that are in use are never available.\n if (this._connectionsInUse.has(connection)) {\n continue;\n }\n\n // This connection is a match and is available! Update our max if it has a larger congestionWindow\n const currentMax = (maxConnection?.congestionWindow) || -Infinity;\n if (connection.congestionWindow > currentMax) {\n maxConnection = connection;\n }\n }\n\n return maxConnection;\n }\n\n /**\n * This method finds an available connection to the origin specified by the network request or null\n * if no connection was available. If returned, connection will not be available for other network\n * records until release is called.\n */\n acquire(request: Lantern.NetworkRequest): TCPConnection|null {\n if (this.connectionsByRequest.has(request)) {\n throw new Core.LanternError('Record already has a connection');\n }\n\n const origin = request.parsedURL.securityOrigin;\n const connections = this.connectionsByOrigin.get(origin) || [];\n const connectionToUse = this.findAvailableConnectionWithLargestCongestionWindow(connections);\n\n if (!connectionToUse) {\n return null;\n }\n\n this._connectionsInUse.add(connectionToUse);\n this.connectionsByRequest.set(request, connectionToUse);\n return connectionToUse;\n }\n\n /**\n * Return the connection currently being used to fetch a request. If no connection\n * currently being used for this request, an error will be thrown.\n */\n acquireActiveConnectionFromRequest(request: Lantern.NetworkRequest): TCPConnection {\n const activeConnection = this.connectionsByRequest.get(request);\n if (!activeConnection) {\n throw new Core.LanternError('Could not find an active connection for request');\n }\n\n return activeConnection;\n }\n\n release(request: Lantern.NetworkRequest): void {\n const connection = this.connectionsByRequest.get(request);\n this.connectionsByRequest.delete(request);\n if (connection) {\n this._connectionsInUse.delete(connection);\n }\n }\n}\n"]}
@@ -42,7 +42,7 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
42
42
  */
43
43
  updateNetworkCapacity(): void;
44
44
  /**
45
- * Estimates the number of milliseconds remaining given current condidtions before the node is complete.
45
+ * Estimates the number of milliseconds remaining given current conditions before the node is complete.
46
46
  */
47
47
  estimateTimeRemaining(node: Graph.Node): number;
48
48
  estimateCPUTimeRemaining(cpuNode: Graph.CPUNode): number;
@@ -52,7 +52,7 @@ declare class Simulator<T = Lantern.AnyNetworkObject> {
52
52
  */
53
53
  findNextNodeCompletionTime(): number;
54
54
  /**
55
- * Given a time period, computes the progress toward completion that the node made durin that time.
55
+ * Given a time period, computes the progress toward completion that the node made during that time.
56
56
  */
57
57
  updateProgressMadeInTimePeriod(node: Graph.Node, timePeriodLength: number, totalElapsedTime: number): void;
58
58
  computeFinalNodeTimings(): {
@@ -223,7 +223,7 @@ class Simulator {
223
223
  }
224
224
  }
225
225
  /**
226
- * Estimates the number of milliseconds remaining given current condidtions before the node is complete.
226
+ * Estimates the number of milliseconds remaining given current conditions before the node is complete.
227
227
  */
228
228
  estimateTimeRemaining(node) {
229
229
  if (node.type === Graph.BaseNode.types.CPU) {
@@ -285,7 +285,7 @@ class Simulator {
285
285
  return minimumTime;
286
286
  }
287
287
  /**
288
- * Given a time period, computes the progress toward completion that the node made durin that time.
288
+ * Given a time period, computes the progress toward completion that the node made during that time.
289
289
  */
290
290
  updateProgressMadeInTimePeriod(node, timePeriodLength, totalElapsedTime) {
291
291
  const timingData = this.nodeTimings.getInProgress(node);
@@ -394,7 +394,7 @@ class Simulator {
394
394
  // have to give up.
395
395
  throw new Core.LanternError('Failed to start a node');
396
396
  }
397
- // set the available throughput for all connections based on # inflight
397
+ // set the available throughput for all connections based on # in-flight
398
398
  this.updateNetworkCapacity();
399
399
  // find the time that the next node will finish
400
400
  const minimumTime = this.findNextNodeCompletionTime();