@paulirish/trace_engine 0.0.58 → 0.0.60
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.
- package/.tmp/tsbuildinfo/analyze-trace.d.mts +2 -3
- package/.tmp/tsbuildinfo/analyze-trace.d.mts.map +1 -1
- package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
- package/LICENSE +1 -1
- package/README.md +28 -1
- package/analyze-trace.mjs +5 -3
- package/core/platform/ArrayUtilities.d.ts +1 -0
- package/core/platform/ArrayUtilities.js +2 -2
- package/core/platform/ArrayUtilities.js.map +1 -1
- package/core/platform/Brand.js +1 -1
- package/core/platform/Brand.js.map +1 -1
- package/core/platform/Constructor.js +1 -1
- package/core/platform/Constructor.js.map +1 -1
- package/core/platform/DOMUtilities.js +1 -1
- package/core/platform/DOMUtilities.js.map +1 -1
- package/core/platform/DateUtilities.js +1 -1
- package/core/platform/DateUtilities.js.map +1 -1
- package/core/platform/DevToolsPath.js +1 -1
- package/core/platform/DevToolsPath.js.map +1 -1
- package/core/platform/KeyboardUtilities.js +1 -1
- package/core/platform/KeyboardUtilities.js.map +1 -1
- package/core/platform/MapUtilities.js +1 -1
- package/core/platform/MapUtilities.js.map +1 -1
- package/core/platform/MimeType.js +1 -1
- package/core/platform/MimeType.js.map +1 -1
- package/core/platform/NumberUtilities.js +1 -1
- package/core/platform/NumberUtilities.js.map +1 -1
- package/core/platform/StringUtilities.d.ts +2 -1
- package/core/platform/StringUtilities.js +34 -32
- package/core/platform/StringUtilities.js.map +1 -1
- package/core/platform/Timing.js +1 -1
- package/core/platform/Timing.js.map +1 -1
- package/core/platform/TypedArrayUtilities.js +1 -1
- package/core/platform/TypedArrayUtilities.js.map +1 -1
- package/core/platform/TypescriptUtilities.js +1 -1
- package/core/platform/TypescriptUtilities.js.map +1 -1
- package/core/platform/UIString.js +1 -1
- package/core/platform/UIString.js.map +1 -1
- package/core/platform/UserVisibleError.js +1 -1
- package/core/platform/UserVisibleError.js.map +1 -1
- package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/core/platform/platform-tsconfig.json +6 -2
- package/core/platform/platform.js +3 -29
- package/core/platform/platform.js.map +1 -1
- package/generated/protocol.d.ts +224 -14
- package/generated/protocol.js +1 -1
- package/locales/af.json +0 -9
- package/locales/am.json +0 -9
- package/locales/ar.json +0 -9
- package/locales/as.json +0 -9
- package/locales/az.json +0 -9
- package/locales/be.json +0 -9
- package/locales/bg.json +0 -9
- package/locales/bn.json +1 -10
- package/locales/bs.json +0 -9
- package/locales/ca.json +0 -9
- package/locales/cs.json +0 -9
- package/locales/cy.json +0 -9
- package/locales/da.json +0 -9
- package/locales/de.json +0 -9
- package/locales/el.json +0 -9
- package/locales/en-GB.json +0 -9
- package/locales/en-US.json +8 -8
- package/locales/en-XL.json +8 -8
- package/locales/es-419.json +0 -9
- package/locales/es.json +0 -9
- package/locales/et.json +0 -9
- package/locales/eu.json +0 -9
- package/locales/fa.json +0 -9
- package/locales/fi.json +0 -9
- package/locales/fil.json +0 -9
- package/locales/fr-CA.json +0 -9
- package/locales/fr.json +0 -9
- package/locales/gl.json +0 -9
- package/locales/gu.json +0 -9
- package/locales/he.json +0 -9
- package/locales/hi.json +0 -9
- package/locales/hr.json +4 -13
- package/locales/hu.json +0 -9
- package/locales/hy.json +0 -9
- package/locales/id.json +0 -9
- package/locales/is.json +0 -9
- package/locales/it.json +0 -9
- package/locales/ja.json +0 -9
- package/locales/ka.json +0 -9
- package/locales/kk.json +0 -9
- package/locales/km.json +0 -9
- package/locales/kn.json +0 -9
- package/locales/ko.json +0 -9
- package/locales/ky.json +0 -9
- package/locales/lo.json +0 -9
- package/locales/lt.json +0 -9
- package/locales/lv.json +0 -9
- package/locales/mk.json +0 -9
- package/locales/ml.json +0 -9
- package/locales/mn.json +0 -9
- package/locales/mr.json +0 -9
- package/locales/ms.json +0 -9
- package/locales/my.json +1 -10
- package/locales/ne.json +22 -31
- package/locales/nl.json +0 -9
- package/locales/no.json +0 -9
- package/locales/or.json +0 -9
- package/locales/pa.json +0 -9
- package/locales/pl.json +0 -9
- package/locales/pt-PT.json +0 -9
- package/locales/pt.json +0 -9
- package/locales/ro.json +0 -9
- package/locales/ru.json +0 -9
- package/locales/si.json +1 -10
- package/locales/sk.json +0 -9
- package/locales/sl.json +0 -9
- package/locales/sq.json +0 -9
- package/locales/sr-Latn.json +0 -9
- package/locales/sr.json +0 -9
- package/locales/sv.json +0 -9
- package/locales/sw.json +0 -9
- package/locales/ta.json +0 -9
- package/locales/te.json +0 -9
- package/locales/th.json +0 -9
- package/locales/tr.json +0 -9
- package/locales/uk.json +0 -9
- package/locales/ur.json +0 -9
- package/locales/uz.json +0 -9
- package/locales/vi.json +0 -9
- package/locales/zh-HK.json +0 -9
- package/locales/zh-TW.json +0 -9
- package/locales/zh.json +0 -9
- package/locales/zu.json +0 -9
- package/models/cpu_profile/CPUProfileDataModel.d.ts +1 -0
- package/models/cpu_profile/CPUProfileDataModel.js +1 -1
- package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
- package/models/cpu_profile/ProfileTreeModel.d.ts +1 -1
- package/models/cpu_profile/ProfileTreeModel.js +1 -1
- package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
- package/models/cpu_profile/cpu_profile-tsconfig.json +6 -2
- package/models/cpu_profile/cpu_profile.js +1 -1
- package/models/cpu_profile/cpu_profile.js.map +1 -1
- package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/EntityMapper.d.ts +33 -0
- package/models/trace/EntityMapper.js +123 -0
- package/models/trace/EntityMapper.js.map +1 -0
- package/models/trace/EventsSerializer.d.ts +11 -0
- package/models/trace/EventsSerializer.js +82 -0
- package/models/trace/EventsSerializer.js.map +1 -0
- package/models/trace/LanternComputationData.d.ts +3 -3
- package/models/trace/LanternComputationData.js +12 -10
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +7 -14
- package/models/trace/ModelImpl.js +25 -52
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Name.d.ts +12 -0
- package/models/trace/Name.js +115 -0
- package/models/trace/Name.js.map +1 -0
- package/models/trace/Processor.d.ts +1 -1
- package/models/trace/Processor.js +42 -61
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/Styles.d.ts +50 -0
- package/models/trace/Styles.js +816 -0
- package/models/trace/Styles.js.map +1 -0
- package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/extras/FilmStrip.d.ts +1 -1
- package/models/trace/extras/FilmStrip.js +7 -7
- package/models/trace/extras/FilmStrip.js.map +1 -1
- package/models/trace/extras/MainThreadActivity.js +1 -1
- package/models/trace/extras/MainThreadActivity.js.map +1 -1
- package/models/trace/extras/ScriptDuplication.js +1 -1
- package/models/trace/extras/ScriptDuplication.js.map +1 -1
- package/models/trace/extras/StackTraceForEvent.d.ts +2 -2
- package/models/trace/extras/StackTraceForEvent.js +21 -21
- package/models/trace/extras/StackTraceForEvent.js.map +1 -1
- package/models/trace/extras/ThirdParties.d.ts +2 -2
- package/models/trace/extras/ThirdParties.js +17 -17
- package/models/trace/extras/ThirdParties.js.map +1 -1
- package/models/trace/extras/TraceFilter.d.ts +1 -1
- package/models/trace/extras/TraceFilter.js +1 -1
- package/models/trace/extras/TraceFilter.js.map +1 -1
- package/models/trace/extras/TraceTree.d.ts +1 -0
- package/models/trace/extras/TraceTree.js +2 -2
- package/models/trace/extras/TraceTree.js.map +1 -1
- package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/extras/extras-tsconfig.json +6 -2
- package/models/trace/extras/extras.js.map +1 -1
- package/models/trace/handlers/AnimationFramesHandler.js +11 -11
- package/models/trace/handlers/AnimationFramesHandler.js.map +1 -1
- package/models/trace/handlers/AnimationHandler.js +5 -5
- package/models/trace/handlers/AnimationHandler.js.map +1 -1
- package/models/trace/handlers/AsyncJSCallsHandler.d.ts +3 -3
- package/models/trace/handlers/AsyncJSCallsHandler.js +9 -9
- package/models/trace/handlers/AsyncJSCallsHandler.js.map +1 -1
- package/models/trace/handlers/AuctionWorkletsHandler.js +12 -12
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
- package/models/trace/handlers/DOMStatsHandler.js +3 -3
- package/models/trace/handlers/DOMStatsHandler.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +15 -2
- package/models/trace/handlers/ExtensionTraceDataHandler.js +53 -64
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/FlowsHandler.js +11 -11
- package/models/trace/handlers/FlowsHandler.js.map +1 -1
- package/models/trace/handlers/FramesHandler.d.ts +7 -0
- package/models/trace/handlers/FramesHandler.js +12 -10
- package/models/trace/handlers/FramesHandler.js.map +1 -1
- package/models/trace/handlers/GPUHandler.js +3 -3
- package/models/trace/handlers/GPUHandler.js.map +1 -1
- package/models/trace/handlers/ImagePaintingHandler.js +13 -13
- package/models/trace/handlers/ImagePaintingHandler.js.map +1 -1
- package/models/trace/handlers/InitiatorsHandler.js +32 -41
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
- package/models/trace/handlers/InvalidationsHandler.js +63 -44
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
- package/models/trace/handlers/LargestImagePaintHandler.js +5 -4
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
- package/models/trace/handlers/LargestTextPaintHandler.js +3 -3
- package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -1
- package/models/trace/handlers/LayerTreeHandler.js +11 -11
- package/models/trace/handlers/LayerTreeHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +17 -4
- package/models/trace/handlers/LayoutShiftsHandler.js +47 -40
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/MemoryHandler.js +3 -3
- package/models/trace/handlers/MemoryHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.d.ts +22 -1
- package/models/trace/handlers/MetaHandler.js +30 -29
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.js +1 -1
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +10 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +44 -25
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageFramesHandler.js +3 -3
- package/models/trace/handlers/PageFramesHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.js +5 -5
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/RendererHandler.d.ts +1 -1
- package/models/trace/handlers/RendererHandler.js +22 -22
- package/models/trace/handlers/RendererHandler.js.map +1 -1
- package/models/trace/handlers/SamplesHandler.d.ts +2 -2
- package/models/trace/handlers/SamplesHandler.js +7 -9
- package/models/trace/handlers/SamplesHandler.js.map +1 -1
- package/models/trace/handlers/ScreenshotsHandler.js +9 -10
- package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
- package/models/trace/handlers/ScriptsHandler.js +9 -8
- package/models/trace/handlers/ScriptsHandler.js.map +1 -1
- package/models/trace/handlers/SelectorStatsHandler.d.ts +2 -2
- package/models/trace/handlers/SelectorStatsHandler.js +13 -13
- package/models/trace/handlers/SelectorStatsHandler.js.map +1 -1
- package/models/trace/handlers/Threads.d.ts +2 -2
- package/models/trace/handlers/Threads.js +9 -9
- package/models/trace/handlers/Threads.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.d.ts +10 -3
- package/models/trace/handlers/UserInteractionsHandler.js +104 -84
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/handlers/UserTimingsHandler.d.ts +21 -0
- package/models/trace/handlers/UserTimingsHandler.js +67 -39
- package/models/trace/handlers/UserTimingsHandler.js.map +1 -1
- package/models/trace/handlers/WarningsHandler.js +14 -14
- package/models/trace/handlers/WarningsHandler.js.map +1 -1
- package/models/trace/handlers/WorkersHandler.js +7 -7
- package/models/trace/handlers/WorkersHandler.js.map +1 -1
- package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/handlers/handlers-tsconfig.json +6 -2
- package/models/trace/handlers/handlers.js +1 -1
- package/models/trace/handlers/handlers.js.map +1 -1
- package/models/trace/handlers/helpers.d.ts +3 -2
- package/models/trace/handlers/helpers.js +10 -10
- package/models/trace/handlers/helpers.js.map +1 -1
- package/models/trace/handlers/types.d.ts +25 -2
- package/models/trace/handlers/types.js.map +1 -1
- package/models/trace/helpers/Extensions.js +8 -8
- package/models/trace/helpers/Extensions.js.map +1 -1
- package/models/trace/helpers/Network.js.map +1 -1
- package/models/trace/helpers/SamplesIntegrator.js +11 -9
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
- package/models/trace/helpers/SyntheticEvents.js +1 -1
- package/models/trace/helpers/SyntheticEvents.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +4 -0
- package/models/trace/helpers/Timing.js +6 -4
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +21 -23
- package/models/trace/helpers/Trace.js +188 -67
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/TreeHelpers.js +1 -1
- package/models/trace/helpers/TreeHelpers.js.map +1 -1
- package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/helpers/helpers-tsconfig.json +6 -2
- package/models/trace/helpers/helpers.js +1 -1
- package/models/trace/helpers/helpers.js.map +1 -1
- package/models/trace/insights/CLSCulprits.d.ts +2 -2
- package/models/trace/insights/CLSCulprits.js +14 -14
- package/models/trace/insights/CLSCulprits.js.map +1 -1
- package/models/trace/insights/Cache.d.ts +2 -1
- package/models/trace/insights/Cache.js +8 -5
- package/models/trace/insights/Cache.js.map +1 -1
- package/models/trace/insights/Common.d.ts +9 -1
- package/models/trace/insights/Common.js +33 -1
- package/models/trace/insights/Common.js.map +1 -1
- package/models/trace/insights/DOMSize.d.ts +3 -2
- package/models/trace/insights/DOMSize.js +10 -7
- package/models/trace/insights/DOMSize.js.map +1 -1
- package/models/trace/insights/DocumentLatency.d.ts +2 -2
- package/models/trace/insights/DocumentLatency.js +18 -17
- package/models/trace/insights/DocumentLatency.js.map +1 -1
- package/models/trace/insights/DuplicatedJavaScript.d.ts +2 -2
- package/models/trace/insights/DuplicatedJavaScript.js +5 -5
- package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
- package/models/trace/insights/FontDisplay.d.ts +2 -1
- package/models/trace/insights/FontDisplay.js +7 -4
- package/models/trace/insights/FontDisplay.js.map +1 -1
- package/models/trace/insights/ForcedReflow.d.ts +2 -1
- package/models/trace/insights/ForcedReflow.js +6 -3
- package/models/trace/insights/ForcedReflow.js.map +1 -1
- package/models/trace/insights/INPBreakdown.d.ts +3 -3
- package/models/trace/insights/INPBreakdown.js +16 -5
- package/models/trace/insights/INPBreakdown.js.map +1 -1
- package/models/trace/insights/ImageDelivery.d.ts +2 -2
- package/models/trace/insights/ImageDelivery.js +13 -13
- package/models/trace/insights/ImageDelivery.js.map +1 -1
- package/models/trace/insights/LCPBreakdown.d.ts +3 -2
- package/models/trace/insights/LCPBreakdown.js +21 -15
- package/models/trace/insights/LCPBreakdown.js.map +1 -1
- package/models/trace/insights/LCPDiscovery.d.ts +2 -2
- package/models/trace/insights/LCPDiscovery.js +9 -11
- package/models/trace/insights/LCPDiscovery.js.map +1 -1
- package/models/trace/insights/LegacyJavaScript.d.ts +1 -1
- package/models/trace/insights/LegacyJavaScript.js +5 -4
- package/models/trace/insights/LegacyJavaScript.js.map +1 -1
- package/models/trace/insights/Models.js +1 -1
- package/models/trace/insights/Models.js.map +1 -1
- package/models/trace/insights/ModernHTTP.d.ts +2 -2
- package/models/trace/insights/ModernHTTP.js +6 -6
- package/models/trace/insights/ModernHTTP.js.map +1 -1
- package/models/trace/insights/NetworkDependencyTree.d.ts +6 -3
- package/models/trace/insights/NetworkDependencyTree.js +19 -16
- package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
- package/models/trace/insights/RenderBlocking.d.ts +2 -2
- package/models/trace/insights/RenderBlocking.js +11 -11
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/SlowCSSSelector.d.ts +3 -2
- package/models/trace/insights/SlowCSSSelector.js +9 -6
- package/models/trace/insights/SlowCSSSelector.js.map +1 -1
- package/models/trace/insights/Statistics.js +1 -1
- package/models/trace/insights/Statistics.js.map +1 -1
- package/models/trace/insights/ThirdParties.d.ts +2 -1
- package/models/trace/insights/ThirdParties.js +8 -5
- package/models/trace/insights/ThirdParties.js.map +1 -1
- package/models/trace/insights/Viewport.d.ts +2 -1
- package/models/trace/insights/Viewport.js +8 -5
- package/models/trace/insights/Viewport.js.map +1 -1
- package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/insights/insights-tsconfig.json +6 -2
- package/models/trace/insights/insights.d.ts +2 -0
- package/models/trace/insights/insights.js +3 -1
- package/models/trace/insights/insights.js.map +1 -1
- package/models/trace/insights/types.d.ts +4 -1
- package/models/trace/insights/types.js +2 -1
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/core/LanternError.js +1 -1
- package/models/trace/lantern/core/LanternError.js.map +1 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js +1 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
- package/models/trace/lantern/core/core-tsconfig.json +6 -2
- package/models/trace/lantern/core/core.js +1 -1
- package/models/trace/lantern/core/core.js.map +1 -1
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/graph/BaseNode.js +1 -1
- package/models/trace/lantern/graph/BaseNode.js.map +1 -1
- package/models/trace/lantern/graph/CPUNode.js +1 -1
- package/models/trace/lantern/graph/CPUNode.js.map +1 -1
- package/models/trace/lantern/graph/NetworkNode.js +1 -1
- package/models/trace/lantern/graph/NetworkNode.js.map +1 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js +1 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/graph/graph-tsconfig.json +6 -2
- package/models/trace/lantern/graph/graph.js +1 -1
- package/models/trace/lantern/graph/graph.js.map +1 -1
- package/models/trace/lantern/lantern-tsconfig.json +6 -2
- package/models/trace/lantern/lantern.js +1 -1
- package/models/trace/lantern/lantern.js.map +1 -1
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +1 -1
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.js +1 -1
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.js +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.js +1 -1
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.js +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TBTUtils.js +1 -1
- package/models/trace/lantern/metrics/TBTUtils.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.js +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -1
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/metrics/metrics-tsconfig.json +6 -2
- package/models/trace/lantern/metrics/metrics.js +1 -1
- package/models/trace/lantern/metrics/metrics.js.map +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
- package/models/trace/lantern/simulation/Constants.js +1 -1
- package/models/trace/lantern/simulation/Constants.js.map +1 -1
- package/models/trace/lantern/simulation/DNSCache.js +1 -1
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.js +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.js +1 -1
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/TCPConnection.js +1 -1
- package/models/trace/lantern/simulation/TCPConnection.js.map +1 -1
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/simulation/simulation-tsconfig.json +6 -2
- package/models/trace/lantern/simulation/simulation.js +1 -1
- package/models/trace/lantern/simulation/simulation.js.map +1 -1
- package/models/trace/lantern/types/Lantern.js +1 -1
- package/models/trace/lantern/types/Lantern.js.map +1 -1
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/lantern/types/types-tsconfig.json +6 -2
- package/models/trace/lantern/types/types.js +1 -1
- package/models/trace/lantern/types/types.js.map +1 -1
- package/models/trace/trace-tsconfig.json +10 -2
- package/models/trace/trace.d.ts +5 -1
- package/models/trace/trace.js +6 -2
- package/models/trace/trace.js.map +1 -1
- package/models/trace/types/Configuration.d.ts +11 -0
- package/models/trace/types/Configuration.js +1 -1
- package/models/trace/types/Configuration.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +25 -13
- package/models/trace/types/Extensions.js +6 -3
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +13 -2
- package/models/trace/types/File.js +1 -1
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/Overlays.d.ts +5 -4
- package/models/trace/types/Overlays.js +1 -1
- package/models/trace/types/Overlays.js.map +1 -1
- package/models/trace/types/Timing.d.ts +1 -0
- package/models/trace/types/Timing.js +1 -1
- package/models/trace/types/Timing.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +81 -61
- package/models/trace/types/TraceEvents.js +42 -29
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +6 -2
- package/models/trace/types/types-tsconfig.json +6 -2
- package/models/trace/types/types.js +1 -1
- package/models/trace/types/types.js.map +1 -1
- package/package.json +1 -1
- package/test/test-trace-engine.mjs +4 -4
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Common from '../../core/common/common.js';
|
|
5
|
+
// import * as i18n from '../../core/i18n/i18n.js';
|
|
6
|
+
import * as Handlers from './handlers/handlers.js';
|
|
7
|
+
import { getEventStyle } from './Styles.js';
|
|
8
|
+
import * as Types from './types/types.js';
|
|
9
|
+
const UIStrings = {
|
|
10
|
+
/**
|
|
11
|
+
* @description Text shown for an entry in the flame chart that has no explicit name.
|
|
12
|
+
*/
|
|
13
|
+
anonymous: '(anonymous)',
|
|
14
|
+
/**
|
|
15
|
+
* @description Text used to show an EventDispatch event which has a type associated with it
|
|
16
|
+
* @example {click} PH1
|
|
17
|
+
*/
|
|
18
|
+
eventDispatchS: 'Event: {PH1}',
|
|
19
|
+
/**
|
|
20
|
+
* @description Text shown for an entry in the flame chart that represents a frame.
|
|
21
|
+
*/
|
|
22
|
+
frame: 'Frame',
|
|
23
|
+
/**
|
|
24
|
+
* @description Text in Timeline Flame Chart Data Provider of the Performance panel
|
|
25
|
+
*/
|
|
26
|
+
wsConnectionOpened: 'WebSocket opened',
|
|
27
|
+
/**
|
|
28
|
+
* @description Text in Timeline Flame Chart Data Provider of the Performance panel
|
|
29
|
+
* @example {ws://example.com} PH1
|
|
30
|
+
*/
|
|
31
|
+
wsConnectionOpenedWithUrl: 'WebSocket opened: {PH1}',
|
|
32
|
+
/**
|
|
33
|
+
* @description Text in Timeline Flame Chart Data Provider of the Performance panel
|
|
34
|
+
*/
|
|
35
|
+
wsConnectionClosed: 'WebSocket closed',
|
|
36
|
+
/**
|
|
37
|
+
* @description Text in Timeline Flame Chart Data Provider of the Performance panel
|
|
38
|
+
*/
|
|
39
|
+
layoutShift: 'Layout shift',
|
|
40
|
+
};
|
|
41
|
+
// const str_ = i18n.i18n.registerUIStrings('models/trace/Name.ts', UIStrings);
|
|
42
|
+
const i18nString = (i18nId, values) => ({i18nId, values}); // i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
43
|
+
/**
|
|
44
|
+
* Calculates the display name for a given entry.
|
|
45
|
+
* @param parsedTrace If the trace data is provided
|
|
46
|
+
* as the second argument it can be used to find source map resolved names for
|
|
47
|
+
* profile calls.
|
|
48
|
+
* Use this function to customize the user visible name for an entry. If no
|
|
49
|
+
* custom name is found, we will fallback to the `name` property in the trace
|
|
50
|
+
* entry.
|
|
51
|
+
*/
|
|
52
|
+
export function forEntry(entry, parsedTrace) {
|
|
53
|
+
if (Types.Events.isProfileCall(entry)) {
|
|
54
|
+
if (parsedTrace) {
|
|
55
|
+
const potentialCallName = Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.data.Samples, entry);
|
|
56
|
+
// We need this extra check because the call name could be the empty
|
|
57
|
+
// string. If it is, we want to fallback.
|
|
58
|
+
if (potentialCallName) {
|
|
59
|
+
return potentialCallName;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return entry.callFrame.functionName || i18nString(UIStrings.anonymous);
|
|
63
|
+
}
|
|
64
|
+
if (Types.Events.isLegacyTimelineFrame(entry)) {
|
|
65
|
+
return i18n.i18n.lockedString(UIStrings.frame);
|
|
66
|
+
}
|
|
67
|
+
if (Types.Events.isDispatch(entry)) {
|
|
68
|
+
// EventDispatch represent user actions such as clicks, so in this case
|
|
69
|
+
// rather than show the event title (which is always just "Event"), we
|
|
70
|
+
// add the type ("click") to help the user understand the event.
|
|
71
|
+
return i18nString(UIStrings.eventDispatchS, { PH1: entry.args.data.type });
|
|
72
|
+
}
|
|
73
|
+
if (Types.Events.isSyntheticNetworkRequest(entry)) {
|
|
74
|
+
const parsedURL = new Common.ParsedURL.ParsedURL(entry.args.data.url);
|
|
75
|
+
const text = parsedURL.isValid ? `${parsedURL.displayName} (${parsedURL.host})` : entry.args.data.url || 'Network request';
|
|
76
|
+
return text;
|
|
77
|
+
}
|
|
78
|
+
if (Types.Events.isWebSocketCreate(entry)) {
|
|
79
|
+
if (entry.args.data.url) {
|
|
80
|
+
return i18nString(UIStrings.wsConnectionOpenedWithUrl, { PH1: entry.args.data.url });
|
|
81
|
+
}
|
|
82
|
+
return i18nString(UIStrings.wsConnectionOpened);
|
|
83
|
+
}
|
|
84
|
+
if (Types.Events.isWebSocketDestroy(entry)) {
|
|
85
|
+
return i18nString(UIStrings.wsConnectionClosed);
|
|
86
|
+
}
|
|
87
|
+
if (Types.Events.isSyntheticInteraction(entry)) {
|
|
88
|
+
return nameForInteractionEvent(entry);
|
|
89
|
+
}
|
|
90
|
+
if (Types.Events.isSyntheticLayoutShift(entry)) {
|
|
91
|
+
return i18nString(UIStrings.layoutShift);
|
|
92
|
+
}
|
|
93
|
+
if (Types.Events.isSyntheticAnimation(entry) && entry.args.data.beginEvent.args.data.displayName) {
|
|
94
|
+
return entry.args.data.beginEvent.args.data.displayName;
|
|
95
|
+
}
|
|
96
|
+
const eventStyleCustomName = getEventStyle(entry.name)?.title;
|
|
97
|
+
return eventStyleCustomName || entry.name;
|
|
98
|
+
}
|
|
99
|
+
function nameForInteractionEvent(event) {
|
|
100
|
+
const category = Handlers.ModelHandlers.UserInteractions.categoryOfInteraction(event);
|
|
101
|
+
// Because we hide nested interactions, we do not want to show the
|
|
102
|
+
// specific type of the interaction that was not hidden, so instead we
|
|
103
|
+
// show just the category of that interaction.
|
|
104
|
+
if (category === 'OTHER') {
|
|
105
|
+
return 'Other';
|
|
106
|
+
}
|
|
107
|
+
if (category === 'KEYBOARD') {
|
|
108
|
+
return 'Keyboard';
|
|
109
|
+
}
|
|
110
|
+
if (category === 'POINTER') {
|
|
111
|
+
return 'Pointer';
|
|
112
|
+
}
|
|
113
|
+
return event.type;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=Name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Name.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Name.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAEhD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAE1C,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,SAAS,EAAE,aAAa;IACxB;;;OAGG;IACH,cAAc,EAAE,cAAc;IAC9B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,kBAAkB,EAAE,kBAAkB;IACtC;;;OAGG;IACH,yBAAyB,EAAE,yBAAyB;IACpD;;OAEG;IACH,kBAAkB,EAAE,kBAAkB;IACtC;;OAEG;IACH,WAAW,EAAE,cAAc;CACnB,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,SAAS,CAAC,CAAC;AAC5E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACpB,KAAyB,EACzB,WAAyB;IAE3B,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,iBAAiB,GACnB,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,0BAA0B,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC/F,oEAAoE;YACpE,yCAAyC;YACzC,IAAI,iBAAiB,EAAE,CAAC;gBACtB,OAAO,iBAAiB,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,SAAS,CAAC,YAAY,IAAI,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,uEAAuE;QACvE,sEAAsE;QACtE,gEAAgE;QAChE,OAAO,UAAU,CAAC,SAAS,CAAC,cAAc,EAAE,EAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAC,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtE,MAAM,IAAI,GACN,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,KAAK,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,iBAAiB,CAAC;QAClH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACxB,OAAO,UAAU,CAAC,SAAS,CAAC,yBAAyB,EAAE,EAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAC,CAAC,CAAC;QACrF,CAAC;QAED,OAAO,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;IAC1D,CAAC;IAED,MAAM,oBAAoB,GAAG,aAAa,CAAC,KAAK,CAAC,IAAyB,CAAC,EAAE,KAAK,CAAC;IAEnF,OAAO,oBAAoB,IAAI,KAAK,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED,SAAS,uBAAuB,CAAC,KAA4C;IAC3E,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACtF,kEAAkE;IAClE,sEAAsE;IACtE,8CAA8C;IAC9C,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors\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 Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\n\nimport * as Handlers from './handlers/handlers.js';\nimport type {ParsedTrace} from './ModelImpl.js';\nimport {getEventStyle} from './Styles.js';\nimport * as Types from './types/types.js';\n\nconst UIStrings = {\n /**\n * @description Text shown for an entry in the flame chart that has no explicit name.\n */\n anonymous: '(anonymous)',\n /**\n * @description Text used to show an EventDispatch event which has a type associated with it\n * @example {click} PH1\n */\n eventDispatchS: 'Event: {PH1}',\n /**\n * @description Text shown for an entry in the flame chart that represents a frame.\n */\n frame: 'Frame',\n /**\n * @description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n wsConnectionOpened: 'WebSocket opened',\n /**\n * @description Text in Timeline Flame Chart Data Provider of the Performance panel\n * @example {ws://example.com} PH1\n */\n wsConnectionOpenedWithUrl: 'WebSocket opened: {PH1}',\n /**\n * @description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n wsConnectionClosed: 'WebSocket closed',\n /**\n * @description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n layoutShift: 'Layout shift',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/Name.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * Calculates the display name for a given entry.\n * @param parsedTrace If the trace data is provided\n * as the second argument it can be used to find source map resolved names for\n * profile calls.\n * Use this function to customize the user visible name for an entry. If no\n * custom name is found, we will fallback to the `name` property in the trace\n * entry.\n */\nexport function forEntry(\n entry: Types.Events.Event,\n parsedTrace?: ParsedTrace,\n ): string {\n if (Types.Events.isProfileCall(entry)) {\n if (parsedTrace) {\n const potentialCallName =\n Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.data.Samples, entry);\n // We need this extra check because the call name could be the empty\n // string. If it is, we want to fallback.\n if (potentialCallName) {\n return potentialCallName;\n }\n }\n return entry.callFrame.functionName || i18nString(UIStrings.anonymous);\n }\n\n if (Types.Events.isLegacyTimelineFrame(entry)) {\n return i18n.i18n.lockedString(UIStrings.frame);\n }\n\n if (Types.Events.isDispatch(entry)) {\n // EventDispatch represent user actions such as clicks, so in this case\n // rather than show the event title (which is always just \"Event\"), we\n // add the type (\"click\") to help the user understand the event.\n return i18nString(UIStrings.eventDispatchS, {PH1: entry.args.data.type});\n }\n if (Types.Events.isSyntheticNetworkRequest(entry)) {\n const parsedURL = new Common.ParsedURL.ParsedURL(entry.args.data.url);\n const text =\n parsedURL.isValid ? `${parsedURL.displayName} (${parsedURL.host})` : entry.args.data.url || 'Network request';\n return text;\n }\n\n if (Types.Events.isWebSocketCreate(entry)) {\n if (entry.args.data.url) {\n return i18nString(UIStrings.wsConnectionOpenedWithUrl, {PH1: entry.args.data.url});\n }\n\n return i18nString(UIStrings.wsConnectionOpened);\n }\n\n if (Types.Events.isWebSocketDestroy(entry)) {\n return i18nString(UIStrings.wsConnectionClosed);\n }\n\n if (Types.Events.isSyntheticInteraction(entry)) {\n return nameForInteractionEvent(entry);\n }\n\n if (Types.Events.isSyntheticLayoutShift(entry)) {\n return i18nString(UIStrings.layoutShift);\n }\n\n if (Types.Events.isSyntheticAnimation(entry) && entry.args.data.beginEvent.args.data.displayName) {\n return entry.args.data.beginEvent.args.data.displayName;\n }\n\n const eventStyleCustomName = getEventStyle(entry.name as Types.Events.Name)?.title;\n\n return eventStyleCustomName || entry.name;\n}\n\nfunction nameForInteractionEvent(event: Types.Events.SyntheticInteractionPair): string {\n const category = Handlers.ModelHandlers.UserInteractions.categoryOfInteraction(event);\n // Because we hide nested interactions, we do not want to show the\n // specific type of the interaction that was not hidden, so instead we\n // show just the category of that interaction.\n if (category === 'OTHER') {\n return 'Other';\n }\n if (category === 'KEYBOARD') {\n return 'Keyboard';\n }\n if (category === 'POINTER') {\n return 'Pointer';\n }\n return event.type;\n}\n"]}
|
|
@@ -22,7 +22,7 @@ export declare class TraceProcessor extends EventTarget {
|
|
|
22
22
|
constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration);
|
|
23
23
|
reset(): void;
|
|
24
24
|
parse(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): Promise<void>;
|
|
25
|
-
get
|
|
25
|
+
get data(): Handlers.Types.HandlerData | null;
|
|
26
26
|
get insights(): Insights.Types.TraceInsightSets | null;
|
|
27
27
|
/**
|
|
28
28
|
* Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// Copyright 2023 The Chromium Authors
|
|
1
|
+
// Copyright 2023 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
+
var _a;
|
|
4
5
|
import * as Handlers from './handlers/handlers.js';
|
|
5
6
|
import * as Helpers from './helpers/helpers.js';
|
|
6
7
|
import * as Insights from './insights/insights.js';
|
|
@@ -31,7 +32,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
31
32
|
#data = null;
|
|
32
33
|
#insights = null;
|
|
33
34
|
static createWithAllHandlers() {
|
|
34
|
-
return new
|
|
35
|
+
return new _a(Handlers.ModelHandlers, Types.Configuration.defaults());
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* This function is kept for testing with `stub`.
|
|
@@ -111,6 +112,9 @@ export class TraceProcessor extends EventTarget {
|
|
|
111
112
|
if (this.#status !== "IDLE" /* Status.IDLE */) {
|
|
112
113
|
throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);
|
|
113
114
|
}
|
|
115
|
+
if (typeof options.isCPUProfile === 'undefined' && options.metadata) {
|
|
116
|
+
options.isCPUProfile = options.metadata.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;
|
|
117
|
+
}
|
|
114
118
|
options.logger?.start('total');
|
|
115
119
|
try {
|
|
116
120
|
this.#status = "PARSING" /* Status.PARSING */;
|
|
@@ -187,42 +191,16 @@ export class TraceProcessor extends EventTarget {
|
|
|
187
191
|
const percent = calculateProgress(i / sortedHandlers.length, 0.8 /* ProgressPhase.FINALIZE */);
|
|
188
192
|
this.dispatchEvent(new TraceParseProgressEvent({ percent }));
|
|
189
193
|
}
|
|
190
|
-
|
|
191
|
-
// return a shallow clone of its internal data structures. However, that pattern
|
|
192
|
-
// easily results in egregious amounts of allocation. Now .data() does not do any
|
|
193
|
-
// cloning, and it happens here instead so that users of the trace processor may
|
|
194
|
-
// still assume that the parsed data is theirs.
|
|
195
|
-
// See: crbug/41484172
|
|
196
|
-
const shallowClone = (value, recurse = true) => {
|
|
197
|
-
if (value instanceof Map) {
|
|
198
|
-
return new Map(value);
|
|
199
|
-
}
|
|
200
|
-
if (value instanceof Set) {
|
|
201
|
-
return new Set(value);
|
|
202
|
-
}
|
|
203
|
-
if (Array.isArray(value)) {
|
|
204
|
-
return [...value];
|
|
205
|
-
}
|
|
206
|
-
if (typeof value === 'object' && value && recurse) {
|
|
207
|
-
const obj = {};
|
|
208
|
-
for (const [key, v] of Object.entries(value)) {
|
|
209
|
-
obj[key] = shallowClone(v, false);
|
|
210
|
-
}
|
|
211
|
-
return obj;
|
|
212
|
-
}
|
|
213
|
-
return value;
|
|
214
|
-
};
|
|
215
|
-
options.logger?.start('parse:clone');
|
|
194
|
+
options.logger?.start('parse:handler.data()');
|
|
216
195
|
const parsedTrace = {};
|
|
217
196
|
for (const [name, handler] of Object.entries(this.#traceHandlers)) {
|
|
218
|
-
|
|
219
|
-
Object.assign(parsedTrace, { [name]: data });
|
|
197
|
+
Object.assign(parsedTrace, { [name]: handler.data() });
|
|
220
198
|
}
|
|
221
|
-
options.logger?.end('parse:
|
|
199
|
+
options.logger?.end('parse:handler.data()');
|
|
222
200
|
this.dispatchEvent(new TraceParseProgressEvent({ percent: 1 /* ProgressPhase.CLONE */ }));
|
|
223
201
|
this.#data = parsedTrace;
|
|
224
202
|
}
|
|
225
|
-
get
|
|
203
|
+
get data() {
|
|
226
204
|
if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
|
|
227
205
|
return null;
|
|
228
206
|
}
|
|
@@ -234,15 +212,15 @@ export class TraceProcessor extends EventTarget {
|
|
|
234
212
|
}
|
|
235
213
|
return this.#insights;
|
|
236
214
|
}
|
|
237
|
-
#createLanternContext(
|
|
215
|
+
#createLanternContext(data, traceEvents, frameId, navigationId, options) {
|
|
238
216
|
// Check for required handlers.
|
|
239
|
-
if (!
|
|
217
|
+
if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {
|
|
240
218
|
return;
|
|
241
219
|
}
|
|
242
|
-
if (!
|
|
220
|
+
if (!data.NetworkRequests.byTime.length) {
|
|
243
221
|
throw new Lantern.Core.LanternError('No network requests found in trace');
|
|
244
222
|
}
|
|
245
|
-
const navStarts =
|
|
223
|
+
const navStarts = data.Meta.navigationsByFrameId.get(frameId);
|
|
246
224
|
const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);
|
|
247
225
|
if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {
|
|
248
226
|
throw new Lantern.Core.LanternError('Could not find navigation start');
|
|
@@ -255,9 +233,9 @@ export class TraceProcessor extends EventTarget {
|
|
|
255
233
|
const trace = {
|
|
256
234
|
traceEvents: boundedTraceEvents,
|
|
257
235
|
};
|
|
258
|
-
const requests = LanternComputationData.createNetworkRequests(trace,
|
|
259
|
-
const graph = LanternComputationData.createGraph(requests, trace,
|
|
260
|
-
const processedNavigation = LanternComputationData.createProcessedNavigation(
|
|
236
|
+
const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);
|
|
237
|
+
const graph = LanternComputationData.createGraph(requests, trace, data);
|
|
238
|
+
const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigationId);
|
|
261
239
|
const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
|
|
262
240
|
if (!networkAnalysis) {
|
|
263
241
|
return;
|
|
@@ -371,24 +349,24 @@ export class TraceProcessor extends EventTarget {
|
|
|
371
349
|
}
|
|
372
350
|
insightSet.model = newModel;
|
|
373
351
|
}
|
|
374
|
-
#computeInsightSet(
|
|
352
|
+
#computeInsightSet(data, context) {
|
|
353
|
+
const logger = context.options.logger;
|
|
375
354
|
let id, urlString, navigation;
|
|
376
355
|
if (context.navigation) {
|
|
377
356
|
id = context.navigationId;
|
|
378
|
-
urlString =
|
|
379
|
-
parsedTrace.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? parsedTrace.Meta.mainFrameURL;
|
|
357
|
+
urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;
|
|
380
358
|
navigation = context.navigation;
|
|
381
359
|
}
|
|
382
360
|
else {
|
|
383
361
|
id = Types.Events.NO_NAVIGATION;
|
|
384
|
-
urlString =
|
|
362
|
+
urlString = data.Meta.finalDisplayUrlByNavigationId.get('') ?? data.Meta.mainFrameURL;
|
|
385
363
|
}
|
|
386
364
|
const insightSetModel = {};
|
|
387
|
-
for (const [name, insight] of Object.entries(
|
|
365
|
+
for (const [name, insight] of Object.entries(_a.getInsightRunners())) {
|
|
388
366
|
let model;
|
|
389
367
|
try {
|
|
390
|
-
|
|
391
|
-
model = insight.generateInsight(
|
|
368
|
+
logger?.start(`insights:${name}`);
|
|
369
|
+
model = insight.generateInsight(data, context);
|
|
392
370
|
model.frameId = context.frameId;
|
|
393
371
|
const navId = context.navigation?.args.data?.navigationId;
|
|
394
372
|
if (navId) {
|
|
@@ -403,7 +381,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
403
381
|
model = err;
|
|
404
382
|
}
|
|
405
383
|
finally {
|
|
406
|
-
|
|
384
|
+
logger?.end(`insights:${name}`);
|
|
407
385
|
}
|
|
408
386
|
Object.assign(insightSetModel, { [name]: model });
|
|
409
387
|
}
|
|
@@ -447,45 +425,46 @@ export class TraceProcessor extends EventTarget {
|
|
|
447
425
|
this.#insights = new Map();
|
|
448
426
|
}
|
|
449
427
|
this.#insights.set(insightSet.id, insightSet);
|
|
450
|
-
this.sortInsightSet(insightSet, options.metadata ?? null);
|
|
428
|
+
this.sortInsightSet(insightSet, context.options.metadata ?? null);
|
|
451
429
|
}
|
|
452
430
|
/**
|
|
453
431
|
* Run all the insights and set the result to `#insights`.
|
|
454
432
|
*/
|
|
455
|
-
#computeInsights(
|
|
433
|
+
#computeInsights(data, traceEvents, options) {
|
|
456
434
|
// This insights map will be populated by the helper methods.
|
|
457
435
|
this.#insights = new Map();
|
|
458
436
|
// Filter main frame navigations to those that have the necessary data (frameId and navigationId).
|
|
459
437
|
// TODO(cjamcl): Does this filtering makes the "use the next nav as the end time" logic potentially broken? Are navs without nav id or frame even real?
|
|
460
|
-
const navigations =
|
|
461
|
-
this.#computeInsightsForInitialTracePeriod(
|
|
438
|
+
const navigations = data.Meta.mainFrameNavigations.filter(navigation => navigation.args.frame && navigation.args.data?.navigationId);
|
|
439
|
+
this.#computeInsightsForInitialTracePeriod(data, navigations, options);
|
|
462
440
|
for (const [index, navigation] of navigations.entries()) {
|
|
463
441
|
const min = navigation.ts;
|
|
464
442
|
// Use trace end for the last navigation, otherwise use the start of the next navigation.
|
|
465
|
-
const max = index + 1 < navigations.length ? navigations[index + 1].ts :
|
|
443
|
+
const max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;
|
|
466
444
|
const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);
|
|
467
|
-
this.#computeInsightsForNavigation(navigation, bounds,
|
|
445
|
+
this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);
|
|
468
446
|
}
|
|
469
447
|
}
|
|
470
448
|
/**
|
|
471
449
|
* Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.
|
|
472
450
|
*/
|
|
473
|
-
#computeInsightsForInitialTracePeriod(
|
|
451
|
+
#computeInsightsForInitialTracePeriod(data, navigations, options) {
|
|
474
452
|
// Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.
|
|
475
453
|
const bounds = navigations.length > 0 ?
|
|
476
|
-
Helpers.Timing.traceWindowFromMicroSeconds(
|
|
477
|
-
|
|
454
|
+
Helpers.Timing.traceWindowFromMicroSeconds(data.Meta.traceBounds.min, navigations[0].ts) :
|
|
455
|
+
data.Meta.traceBounds;
|
|
478
456
|
const context = {
|
|
457
|
+
options,
|
|
479
458
|
bounds,
|
|
480
|
-
frameId:
|
|
459
|
+
frameId: data.Meta.mainFrameId,
|
|
481
460
|
// No navigation or lantern context applies to this initial/no-navigation period.
|
|
482
461
|
};
|
|
483
|
-
this.#computeInsightSet(
|
|
462
|
+
this.#computeInsightSet(data, context);
|
|
484
463
|
}
|
|
485
464
|
/**
|
|
486
465
|
* Computes insights for a specific navigation event.
|
|
487
466
|
*/
|
|
488
|
-
#computeInsightsForNavigation(navigation, bounds,
|
|
467
|
+
#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options) {
|
|
489
468
|
const frameId = navigation.args.frame;
|
|
490
469
|
// Guaranteed by the filter in #computeInsights
|
|
491
470
|
const navigationId = navigation.args.data?.navigationId;
|
|
@@ -495,7 +474,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
495
474
|
let lantern;
|
|
496
475
|
try {
|
|
497
476
|
options.logger?.start('insights:createLanternContext');
|
|
498
|
-
lantern = this.#createLanternContext(
|
|
477
|
+
lantern = this.#createLanternContext(data, traceEvents, frameId, navigationId, options);
|
|
499
478
|
}
|
|
500
479
|
catch (e) {
|
|
501
480
|
// Handle Lantern errors gracefully
|
|
@@ -524,15 +503,17 @@ export class TraceProcessor extends EventTarget {
|
|
|
524
503
|
options.logger?.end('insights:createLanternContext');
|
|
525
504
|
}
|
|
526
505
|
const context = {
|
|
506
|
+
options,
|
|
527
507
|
bounds,
|
|
528
508
|
frameId,
|
|
529
509
|
navigation,
|
|
530
510
|
navigationId,
|
|
531
511
|
lantern,
|
|
532
512
|
};
|
|
533
|
-
this.#computeInsightSet(
|
|
513
|
+
this.#computeInsightSet(data, context);
|
|
534
514
|
}
|
|
535
515
|
}
|
|
516
|
+
_a = TraceProcessor;
|
|
536
517
|
/**
|
|
537
518
|
* Some Handlers need data provided by others. Dependencies of a handler handler are
|
|
538
519
|
* declared in the `deps` field.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport type * as Model from './ModelImpl.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: Model.TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\n\n/**\n * Parsing a trace can take time. On large traces we see a breakdown of time like so:\n * - handleEvent() loop: ~20%\n * - finalize() loop: ~60%\n * - shallowClone calls: ~20%\n * The numbers below are set so we can report a progress percentage of [0...1]\n */\nconst enum ProgressPhase {\n HANDLE_EVENT = 0.2,\n FINALIZE = 0.8,\n CLONE = 1.0,\n}\nfunction calculateProgress(value: number, phase: ProgressPhase): number {\n // Finalize values should be [0.2...0.8]\n if (phase === ProgressPhase.FINALIZE) {\n return (value * (ProgressPhase.FINALIZE - ProgressPhase.HANDLE_EVENT)) + ProgressPhase.HANDLE_EVENT;\n }\n return value * phase;\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.ParsedTrace|null = null;\n #insights: Insights.Types.TraceInsightSets|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys = new Set<Handlers.Types.HandlerName>();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.HandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n const percent = calculateProgress(i / traceEvents.length, ProgressPhase.HANDLE_EVENT);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n const finalizeOptions: Handlers.Types.FinalizeOptions = {\n ...options,\n allTraceEvents: traceEvents,\n };\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}:finalize`);\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize(finalizeOptions);\n options.logger?.end(`parse:${name}:finalize`);\n }\n const percent = calculateProgress(i / sortedHandlers.length, ProgressPhase.FINALIZE);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n options.logger?.start('parse:clone');\n const parsedTrace = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(parsedTrace, {[name]: data});\n }\n options.logger?.end('parse:clone');\n\n this.dispatchEvent(new TraceParseProgressEvent({percent: ProgressPhase.CLONE}));\n\n this.#data = parsedTrace as Handlers.Types.ParsedTrace;\n }\n\n get parsedTrace(): Handlers.Types.ParsedTrace|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightSets|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[], frameId: string,\n navigationId: string, options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!parsedTrace.NetworkRequests || !parsedTrace.Workers || !parsedTrace.PageLoadMetrics) {\n return;\n }\n if (!parsedTrace.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n const navStarts = parsedTrace.Meta.navigationsByFrameId.get(frameId);\n const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);\n if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {\n throw new Lantern.Core.LanternError('Could not find navigation start');\n }\n\n const startTime = navStarts[navStartIndex].ts;\n const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;\n const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);\n\n // Lantern.Types.TraceEvent and Types.Events.Event represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: boundedTraceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, parsedTrace, startTime, endTime);\n const graph = LanternComputationData.createGraph(requests, trace, parsedTrace);\n const processedNavigation = LanternComputationData.createProcessedNavigation(parsedTrace, frameId, navigationId);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\n // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture\n // that? Do we need to set 'devtools' throttlingMethod?\n networkAnalysis,\n throttlingMethod: 'provided',\n ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(insightSet).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(insightSet)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, model] of Object.entries(insightSet.model)) {\n const lcp = model.metricSavings?.LCP ?? 0;\n const inp = model.metricSavings?.INP ?? 0;\n const cls = model.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(\n parsedTrace: Handlers.Types.ParsedTrace, context: Insights.Types.InsightSetContext,\n options: Types.Configuration.ParseOptions): void {\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString =\n parsedTrace.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? parsedTrace.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = parsedTrace.Meta.finalDisplayUrlByNavigationId.get('') ?? parsedTrace.Meta.mainFrameURL;\n }\n\n const insightSetModel = {} as Insights.Types.InsightSet['model'];\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n let model: Insights.Types.InsightModel|Error;\n try {\n options.logger?.start(`insights:${name}`);\n model = insight.generateInsight(parsedTrace, context);\n model.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n model.navigationId = navId;\n }\n model.createOverlays = () => {\n // @ts-expect-error: model is a union of all possible insight model types.\n return insight.createOverlays(model);\n };\n } catch (err) {\n model = err;\n } finally {\n options.logger?.end(`insights:${name}`);\n }\n Object.assign(insightSetModel, {[name]: model});\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses = Object.values(insightSetModel)\n .filter(model => !(model instanceof Error))\n .every(model => model.state === 'pass');\n\n const noLcp = !insightSetModel.LCPBreakdown.lcpEvent;\n const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;\n const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\n }\n\n let url;\n try {\n url = new URL(urlString);\n } catch {\n // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't\n // happen for real traces.\n return;\n }\n\n const insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model: insightSetModel,\n };\n if (!this.#insights) {\n this.#insights = new Map();\n }\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = parsedTrace.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(parsedTrace, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : parsedTrace.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, parsedTrace, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n parsedTrace: Handlers.Types.ParsedTrace, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(parsedTrace.Meta.traceBounds.min, navigations[0].ts) :\n parsedTrace.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId: parsedTrace.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(parsedTrace, context, options);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro,\n parsedTrace: Handlers.Types.ParsedTrace, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\n const navigationId = navigation.args.data?.navigationId as string;\n\n // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n let lantern: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(parsedTrace, traceEvents, frameId, navigationId, options);\n } catch (e) {\n // Handle Lantern errors gracefully\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(parsedTrace, context, options);\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<Handlers.Types.HandlerName, Handlers.Types.Handler>>):\n Map<Handlers.Types.HandlerName, Handlers.Types.Handler> {\n const sortedMap = new Map<Handlers.Types.HandlerName, Handlers.Types.Handler>();\n const visited = new Set<Handlers.Types.HandlerName>();\n const visitHandler = (handlerName: Handlers.Types.HandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.HandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport type * as Model from './ModelImpl.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: Model.TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\n\n/**\n * Parsing a trace can take time. On large traces we see a breakdown of time like so:\n * - handleEvent() loop: ~20%\n * - finalize() loop: ~60%\n * - shallowClone calls: ~20%\n * The numbers below are set so we can report a progress percentage of [0...1]\n */\nconst enum ProgressPhase {\n HANDLE_EVENT = 0.2,\n FINALIZE = 0.8,\n CLONE = 1.0,\n}\nfunction calculateProgress(value: number, phase: ProgressPhase): number {\n // Finalize values should be [0.2...0.8]\n if (phase === ProgressPhase.FINALIZE) {\n return (value * (ProgressPhase.FINALIZE - ProgressPhase.HANDLE_EVENT)) + ProgressPhase.HANDLE_EVENT;\n }\n return value * phase;\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.HandlerData|null = null;\n #insights: Insights.Types.TraceInsightSets|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys = new Set<Handlers.Types.HandlerName>();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.HandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n\n if (typeof options.isCPUProfile === 'undefined' && options.metadata) {\n options.isCPUProfile = options.metadata.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;\n }\n\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n const percent = calculateProgress(i / traceEvents.length, ProgressPhase.HANDLE_EVENT);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n const finalizeOptions: Handlers.Types.FinalizeOptions = {\n ...options,\n allTraceEvents: traceEvents,\n };\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}:finalize`);\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize(finalizeOptions);\n options.logger?.end(`parse:${name}:finalize`);\n }\n const percent = calculateProgress(i / sortedHandlers.length, ProgressPhase.FINALIZE);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n }\n\n options.logger?.start('parse:handler.data()');\n const parsedTrace = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n Object.assign(parsedTrace, {[name]: handler.data()});\n }\n options.logger?.end('parse:handler.data()');\n\n this.dispatchEvent(new TraceParseProgressEvent({percent: ProgressPhase.CLONE}));\n\n this.#data = parsedTrace as Handlers.Types.HandlerData;\n }\n\n get data(): Handlers.Types.HandlerData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightSets|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[], frameId: string,\n navigationId: string, options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {\n return;\n }\n if (!data.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n const navStarts = data.Meta.navigationsByFrameId.get(frameId);\n const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);\n if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {\n throw new Lantern.Core.LanternError('Could not find navigation start');\n }\n\n const startTime = navStarts[navStartIndex].ts;\n const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;\n const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);\n\n // Lantern.Types.TraceEvent and Types.Events.Event represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: boundedTraceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);\n const graph = LanternComputationData.createGraph(requests, trace, data);\n const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigationId);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\n // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture\n // that? Do we need to set 'devtools' throttlingMethod?\n networkAnalysis,\n throttlingMethod: 'provided',\n ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(insightSet).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(insightSet)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, model] of Object.entries(insightSet.model)) {\n const lcp = model.metricSavings?.LCP ?? 0;\n const inp = model.metricSavings?.INP ?? 0;\n const cls = model.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(data: Handlers.Types.HandlerData, context: Insights.Types.InsightSetContext): void {\n const logger = context.options.logger;\n\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get('') ?? data.Meta.mainFrameURL;\n }\n\n const insightSetModel = {} as Insights.Types.InsightSet['model'];\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n let model: Insights.Types.InsightModel|Error;\n try {\n logger?.start(`insights:${name}`);\n model = insight.generateInsight(data, context);\n model.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n model.navigationId = navId;\n }\n model.createOverlays = () => {\n // @ts-expect-error: model is a union of all possible insight model types.\n return insight.createOverlays(model);\n };\n } catch (err) {\n model = err;\n } finally {\n logger?.end(`insights:${name}`);\n }\n Object.assign(insightSetModel, {[name]: model});\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses = Object.values(insightSetModel)\n .filter(model => !(model instanceof Error))\n .every(model => model.state === 'pass');\n\n const noLcp = !insightSetModel.LCPBreakdown.lcpEvent;\n const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;\n const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\n }\n\n let url;\n try {\n url = new URL(urlString);\n } catch {\n // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't\n // happen for real traces.\n return;\n }\n\n const insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model: insightSetModel,\n };\n if (!this.#insights) {\n this.#insights = new Map();\n }\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, context.options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = data.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(data, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n data: Handlers.Types.HandlerData, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(data.Meta.traceBounds.min, navigations[0].ts) :\n data.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId: data.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(data, context);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro, data: Handlers.Types.HandlerData,\n traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\n const navigationId = navigation.args.data?.navigationId as string;\n\n // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n let lantern: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(data, traceEvents, frameId, navigationId, options);\n } catch (e) {\n // Handle Lantern errors gracefully\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(data, context);\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<Handlers.Types.HandlerName, Handlers.Types.Handler>>):\n Map<Handlers.Types.HandlerName, Handlers.Types.Handler> {\n const sortedMap = new Map<Handlers.Types.HandlerName, Handlers.Types.Handler>();\n const visited = new Set<Handlers.Types.HandlerName>();\n const visitHandler = (handlerName: Handlers.Types.HandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.HandlerName);\n }\n return sortedMap;\n}\n"]}
|