@paulirish/trace_engine 0.0.41 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/generated/protocol.d.ts +79 -3
  3. package/locales/en-US.json +210 -0
  4. package/locales/en-XL.json +210 -0
  5. package/models/cpu_profile/CPUProfileDataModel.d.ts +7 -0
  6. package/models/cpu_profile/CPUProfileDataModel.js +9 -2
  7. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
  8. package/models/cpu_profile/ProfileTreeModel.d.ts +1 -1
  9. package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
  10. package/models/trace/LanternComputationData.d.ts +1 -1
  11. package/models/trace/LanternComputationData.js +8 -6
  12. package/models/trace/LanternComputationData.js.map +1 -1
  13. package/models/trace/Processor.d.ts +2 -16
  14. package/models/trace/Processor.js +6 -4
  15. package/models/trace/Processor.js.map +1 -1
  16. package/models/trace/extras/FilmStrip.d.ts +5 -5
  17. package/models/trace/extras/FilmStrip.js +2 -1
  18. package/models/trace/extras/FilmStrip.js.map +1 -1
  19. package/models/trace/extras/MainThreadActivity.d.ts +1 -1
  20. package/models/trace/extras/MainThreadActivity.js +3 -3
  21. package/models/trace/extras/MainThreadActivity.js.map +1 -1
  22. package/models/trace/extras/ThirdParties.d.ts +14 -13
  23. package/models/trace/extras/ThirdParties.js +51 -61
  24. package/models/trace/extras/ThirdParties.js.map +1 -1
  25. package/models/trace/extras/TimelineJSProfile.d.ts +1 -1
  26. package/models/trace/extras/TimelineJSProfile.js +9 -4
  27. package/models/trace/extras/TimelineJSProfile.js.map +1 -1
  28. package/models/trace/extras/TraceTree.d.ts +19 -6
  29. package/models/trace/extras/TraceTree.js +6 -3
  30. package/models/trace/extras/TraceTree.js.map +1 -1
  31. package/models/trace/extras/extras.d.ts +0 -1
  32. package/models/trace/extras/extras.js +0 -1
  33. package/models/trace/handlers/AnimationFramesHandler.js +1 -1
  34. package/models/trace/handlers/AnimationFramesHandler.js.map +1 -1
  35. package/models/trace/handlers/ExtensionTraceDataHandler.js +8 -2
  36. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  37. package/models/trace/handlers/FlowsHandler.js.map +1 -1
  38. package/models/trace/handlers/FramesHandler.d.ts +12 -12
  39. package/models/trace/handlers/FramesHandler.js +3 -3
  40. package/models/trace/handlers/FramesHandler.js.map +1 -1
  41. package/models/trace/handlers/LayoutShiftsHandler.d.ts +2 -2
  42. package/models/trace/handlers/LayoutShiftsHandler.js +25 -16
  43. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  44. package/models/trace/handlers/MetaHandler.d.ts +2 -2
  45. package/models/trace/handlers/MetaHandler.js +21 -21
  46. package/models/trace/handlers/MetaHandler.js.map +1 -1
  47. package/models/trace/handlers/NetworkRequestsHandler.js +37 -38
  48. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  49. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +6 -6
  50. package/models/trace/handlers/PageLoadMetricsHandler.js +9 -9
  51. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  52. package/models/trace/handlers/RendererHandler.d.ts +1 -1
  53. package/models/trace/handlers/RendererHandler.js +4 -4
  54. package/models/trace/handlers/RendererHandler.js.map +1 -1
  55. package/models/trace/handlers/SamplesHandler.d.ts +1 -1
  56. package/models/trace/handlers/SamplesHandler.js +50 -42
  57. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  58. package/models/trace/handlers/ScreenshotsHandler.d.ts +6 -3
  59. package/models/trace/handlers/ScreenshotsHandler.js +22 -8
  60. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  61. package/models/trace/handlers/ServerTimingsHandler.js +4 -4
  62. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -1
  63. package/models/trace/handlers/Threads.js +3 -4
  64. package/models/trace/handlers/Threads.js.map +1 -1
  65. package/models/trace/handlers/UserInteractionsHandler.d.ts +2 -2
  66. package/models/trace/handlers/UserInteractionsHandler.js +12 -12
  67. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  68. package/models/trace/handlers/WarningsHandler.d.ts +2 -2
  69. package/models/trace/handlers/WarningsHandler.js +2 -2
  70. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  71. package/models/trace/handlers/helpers.d.ts +3 -3
  72. package/models/trace/handlers/helpers.js +16 -19
  73. package/models/trace/handlers/helpers.js.map +1 -1
  74. package/models/trace/handlers/types.d.ts +1 -1
  75. package/models/trace/handlers/types.js.map +1 -1
  76. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
  77. package/models/trace/helpers/SamplesIntegrator.js +54 -15
  78. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  79. package/models/trace/helpers/Timing.d.ts +23 -23
  80. package/models/trace/helpers/Timing.js +11 -11
  81. package/models/trace/helpers/Timing.js.map +1 -1
  82. package/models/trace/helpers/Trace.d.ts +15 -14
  83. package/models/trace/helpers/Trace.js +11 -5
  84. package/models/trace/helpers/Trace.js.map +1 -1
  85. package/models/trace/helpers/TreeHelpers.d.ts +2 -2
  86. package/models/trace/helpers/TreeHelpers.js +5 -5
  87. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  88. package/models/trace/insights/CLSCulprits.d.ts +46 -1
  89. package/models/trace/insights/CLSCulprits.js +85 -10
  90. package/models/trace/insights/CLSCulprits.js.map +1 -1
  91. package/models/trace/insights/Common.d.ts +11 -7
  92. package/models/trace/insights/Common.js +85 -26
  93. package/models/trace/insights/Common.js.map +1 -1
  94. package/models/trace/insights/DOMSize.d.ts +26 -1
  95. package/models/trace/insights/DOMSize.js +44 -7
  96. package/models/trace/insights/DOMSize.js.map +1 -1
  97. package/models/trace/insights/DocumentLatency.d.ts +42 -5
  98. package/models/trace/insights/DocumentLatency.js +64 -8
  99. package/models/trace/insights/DocumentLatency.js.map +1 -1
  100. package/models/trace/insights/FontDisplay.d.ts +8 -2
  101. package/models/trace/insights/FontDisplay.js +10 -4
  102. package/models/trace/insights/FontDisplay.js.map +1 -1
  103. package/models/trace/insights/ForcedReflow.d.ts +30 -0
  104. package/models/trace/insights/ForcedReflow.js +181 -0
  105. package/models/trace/insights/ForcedReflow.js.map +1 -0
  106. package/models/trace/insights/ImageDelivery.d.ts +15 -1
  107. package/models/trace/insights/ImageDelivery.js +21 -1
  108. package/models/trace/insights/ImageDelivery.js.map +1 -1
  109. package/models/trace/insights/InteractionToNextPaint.d.ts +26 -1
  110. package/models/trace/insights/InteractionToNextPaint.js +27 -1
  111. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  112. package/models/trace/insights/LCPDiscovery.d.ts +30 -6
  113. package/models/trace/insights/LCPDiscovery.js +36 -8
  114. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  115. package/models/trace/insights/LCPPhases.d.ts +36 -7
  116. package/models/trace/insights/LCPPhases.js +37 -8
  117. package/models/trace/insights/LCPPhases.js.map +1 -1
  118. package/models/trace/insights/LongCriticalNetworkTree.d.ts +22 -0
  119. package/models/trace/insights/LongCriticalNetworkTree.js +40 -0
  120. package/models/trace/insights/LongCriticalNetworkTree.js.map +1 -0
  121. package/models/trace/insights/Models.d.ts +2 -0
  122. package/models/trace/insights/Models.js +2 -0
  123. package/models/trace/insights/Models.js.map +1 -1
  124. package/models/trace/insights/RenderBlocking.d.ts +14 -1
  125. package/models/trace/insights/RenderBlocking.js +14 -1
  126. package/models/trace/insights/RenderBlocking.js.map +1 -1
  127. package/models/trace/insights/SlowCSSSelector.d.ts +27 -2
  128. package/models/trace/insights/SlowCSSSelector.js +27 -2
  129. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  130. package/models/trace/insights/ThirdParties.d.ts +13 -4
  131. package/models/trace/insights/ThirdParties.js +21 -12
  132. package/models/trace/insights/ThirdParties.js.map +1 -1
  133. package/models/trace/insights/Viewport.d.ts +2 -1
  134. package/models/trace/insights/Viewport.js +2 -1
  135. package/models/trace/insights/Viewport.js.map +1 -1
  136. package/models/trace/insights/insights-tsconfig.json +2 -0
  137. package/models/trace/insights/types.d.ts +27 -8
  138. package/models/trace/insights/types.js.map +1 -1
  139. package/models/trace/lantern/graph/BaseNode.d.ts +1 -1
  140. package/models/trace/lantern/graph/BaseNode.js +1 -1
  141. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  142. package/models/trace/lantern/graph/CPUNode.d.ts +1 -1
  143. package/models/trace/lantern/graph/CPUNode.js.map +1 -1
  144. package/models/trace/lantern/graph/NetworkNode.d.ts +1 -1
  145. package/models/trace/lantern/graph/NetworkNode.js.map +1 -1
  146. package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +1 -1
  147. package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
  148. package/models/trace/lantern/simulation/ConnectionPool.js +1 -1
  149. package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
  150. package/models/trace/lantern/simulation/Simulator.d.ts +2 -2
  151. package/models/trace/lantern/simulation/Simulator.js +3 -3
  152. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  153. package/models/trace/lantern/types/Lantern.d.ts +2 -2
  154. package/models/trace/lantern/types/Lantern.js.map +1 -1
  155. package/models/trace/root-causes/LayoutShift.d.ts +1 -1
  156. package/models/trace/root-causes/LayoutShift.js +4 -4
  157. package/models/trace/root-causes/LayoutShift.js.map +1 -1
  158. package/models/trace/types/Configuration.d.ts +15 -0
  159. package/models/trace/types/Configuration.js.map +1 -1
  160. package/models/trace/types/File.d.ts +4 -4
  161. package/models/trace/types/File.js.map +1 -1
  162. package/models/trace/types/Timing.d.ts +7 -13
  163. package/models/trace/types/Timing.js +5 -2
  164. package/models/trace/types/Timing.js.map +1 -1
  165. package/models/trace/types/TraceEvents.d.ts +145 -110
  166. package/models/trace/types/TraceEvents.js +9 -7
  167. package/models/trace/types/TraceEvents.js.map +1 -1
  168. package/package.json +1 -1
  169. package/test/test-trace-engine.mjs +18 -14
  170. package/core/platform/PromiseUtilities.d.ts +0 -10
  171. package/core/platform/PromiseUtilities.js +0 -18
  172. package/core/platform/PromiseUtilities.js.map +0 -1
  173. package/core/platform/SetUtilities.d.ts +0 -2
  174. package/core/platform/SetUtilities.js +0 -23
  175. package/core/platform/SetUtilities.js.map +0 -1
  176. package/models/trace/EntriesFilter.d.ts +0 -72
  177. package/models/trace/EntriesFilter.js +0 -296
  178. package/models/trace/EntriesFilter.js.map +0 -1
  179. package/models/trace/LegacyTracingModel.js.map +0 -1
  180. package/models/trace/extras/URLForEntry.d.ts +0 -13
  181. package/models/trace/extras/URLForEntry.js +0 -44
  182. package/models/trace/extras/URLForEntry.js.map +0 -1
  183. package/models/trace/handlers/EnhancedTracesHandler.d.ts +0 -48
  184. package/models/trace/handlers/EnhancedTracesHandler.js +0 -165
  185. package/models/trace/handlers/EnhancedTracesHandler.js.map +0 -1
  186. package/models/trace/insights/CumulativeLayoutShift.d.ts +0 -34
  187. package/models/trace/insights/CumulativeLayoutShift.js +0 -209
  188. package/models/trace/insights/CumulativeLayoutShift.js.map +0 -1
  189. package/models/trace/insights/InsightRunners.d.ts +0 -6
  190. package/models/trace/insights/InsightRunners.js +0 -10
  191. package/models/trace/insights/InsightRunners.js.map +0 -1
  192. package/models/trace/insights/LargestContentfulPaint.d.ts +0 -25
  193. package/models/trace/insights/LargestContentfulPaint.js +0 -93
  194. package/models/trace/insights/LargestContentfulPaint.js.map +0 -1
  195. package/models/trace/lantern/BaseNode.d.ts +0 -91
  196. package/models/trace/lantern/BaseNode.js +0 -268
  197. package/models/trace/lantern/BaseNode.js.map +0 -1
  198. package/models/trace/lantern/CPUNode.d.ts +0 -24
  199. package/models/trace/lantern/CPUNode.js +0 -64
  200. package/models/trace/lantern/CPUNode.js.map +0 -1
  201. package/models/trace/lantern/LanternError.d.ts +0 -3
  202. package/models/trace/lantern/LanternError.js +0 -7
  203. package/models/trace/lantern/LanternError.js.map +0 -1
  204. package/models/trace/lantern/MetricsModule.d.ts +0 -11
  205. package/models/trace/lantern/MetricsModule.js +0 -14
  206. package/models/trace/lantern/MetricsModule.js.map +0 -1
  207. package/models/trace/lantern/NetworkNode.d.ts +0 -22
  208. package/models/trace/lantern/NetworkNode.js +0 -83
  209. package/models/trace/lantern/NetworkNode.js.map +0 -1
  210. package/models/trace/lantern/PageDependencyGraph.d.ts +0 -43
  211. package/models/trace/lantern/PageDependencyGraph.js +0 -509
  212. package/models/trace/lantern/PageDependencyGraph.js.map +0 -1
  213. package/models/trace/lantern/SimulationModule.d.ts +0 -17
  214. package/models/trace/lantern/SimulationModule.js +0 -13
  215. package/models/trace/lantern/SimulationModule.js.map +0 -1
  216. package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +0 -112
  217. package/models/trace/lantern/simulation/NetworkAnalyzer.js +0 -486
  218. package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +0 -1
@@ -1,209 +0,0 @@
1
- // Copyright 2024 The Chromium Authors. All rights reserved.
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
- import * as Platform from '../../../core/platform/platform.js';
5
- import * as Helpers from '../helpers/helpers.js';
6
- import * as Types from '../types/types.js';
7
- export function deps() {
8
- return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];
9
- }
10
- /**
11
- * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define
12
- * which bit corresponds to each failure reason.
13
- * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22
14
- * @type {{flag: number, failure: AnimationFailureReasons}[]}
15
- */
16
- const ACTIONABLE_FAILURE_REASONS = [
17
- {
18
- flag: 1 << 13,
19
- failure: "UNSUPPORTED_CSS_PROPERTY" /* AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */,
20
- },
21
- {
22
- flag: 1 << 11,
23
- failure: "TRANSFROM_BOX_SIZE_DEPENDENT" /* AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT */,
24
- },
25
- {
26
- flag: 1 << 12,
27
- failure: "FILTER_MAY_MOVE_PIXELS" /* AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS */,
28
- },
29
- {
30
- flag: 1 << 4,
31
- failure: "NON_REPLACE_COMPOSITE_MODE" /* AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE */,
32
- },
33
- {
34
- flag: 1 << 6,
35
- failure: "INCOMPATIBLE_ANIMATIONS" /* AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS */,
36
- },
37
- {
38
- flag: 1 << 3,
39
- failure: "UNSUPPORTED_TIMING_PARAMS" /* AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS */,
40
- },
41
- ];
42
- // 500ms window.
43
- // Use this window to consider events and requests that may have caused a layout shift.
44
- const INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));
45
- function isInInvalidationWindow(event, targetEvent) {
46
- const eventEnd = event.dur ? event.ts + event.dur : event.ts;
47
- return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;
48
- }
49
- /**
50
- * Returns a list of NoncompositedAnimationFailures.
51
- */
52
- function getNonCompositedAnimations(animations) {
53
- const failures = [];
54
- for (const event of animations) {
55
- const beginEvent = event.args.data.beginEvent;
56
- const instantEvents = event.args.data.instantEvents || [];
57
- /**
58
- * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').
59
- * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.
60
- */
61
- for (const event of instantEvents) {
62
- const failureMask = event.args.data.compositeFailed;
63
- const unsupportedProperties = event.args.data.unsupportedProperties;
64
- if (!failureMask || !unsupportedProperties) {
65
- continue;
66
- }
67
- const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => {
68
- return reason.failure;
69
- });
70
- const failure = {
71
- name: beginEvent.args.data.displayName,
72
- failureReasons,
73
- unsupportedProperties,
74
- };
75
- failures.push(failure);
76
- }
77
- }
78
- return failures;
79
- }
80
- /**
81
- * Given an array of layout shift and PrePaint events, returns a mapping from
82
- * PrePaint events to layout shifts dispatched within it.
83
- */
84
- function getShiftsByPrePaintEvents(layoutShifts, prePaintEvents) {
85
- // Maps from PrePaint events to LayoutShifts that occured in each one.
86
- const shiftsByPrePaint = new Map();
87
- // Associate all shifts to their corresponding PrePaint.
88
- for (const prePaintEvent of prePaintEvents) {
89
- const firstShiftIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);
90
- if (firstShiftIndex === null) {
91
- // No layout shifts registered after this PrePaint start. Continue.
92
- continue;
93
- }
94
- for (let i = firstShiftIndex; i < layoutShifts.length; i++) {
95
- const shift = layoutShifts[i];
96
- if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {
97
- const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);
98
- shiftsInPrePaint.push(shift);
99
- }
100
- if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {
101
- // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.
102
- break;
103
- }
104
- }
105
- }
106
- return shiftsByPrePaint;
107
- }
108
- /**
109
- * This gets the first prePaint event that follows the provided event and returns it.
110
- */
111
- function getNextPrePaintEvent(prePaintEvents, targetEvent) {
112
- // Get the first PrePaint event that happened after the targetEvent.
113
- const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));
114
- // No PrePaint event registered after this event
115
- if (nextPrePaintIndex === null) {
116
- return undefined;
117
- }
118
- return prePaintEvents[nextPrePaintIndex];
119
- }
120
- /**
121
- * An Iframe is considered a root cause if the iframe event occurs before a prePaint event
122
- * and within this prePaint event a layout shift(s) occurs.
123
- */
124
- function getIframeRootCauses(iframeCreatedEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
125
- for (const iframeEvent of iframeCreatedEvents) {
126
- const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);
127
- // If no following prePaint, this is not a root cause.
128
- if (!nextPrePaint) {
129
- continue;
130
- }
131
- const shifts = shiftsByPrePaint.get(nextPrePaint);
132
- // if no layout shift(s), this is not a root cause.
133
- if (!shifts) {
134
- continue;
135
- }
136
- for (const shift of shifts) {
137
- const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {
138
- return {
139
- iframes: [],
140
- fontRequests: [],
141
- };
142
- });
143
- rootCausesForShift.iframes.push(iframeEvent);
144
- }
145
- }
146
- return rootCausesByShift;
147
- }
148
- /**
149
- * A font request is considered a root cause if the request occurs before a prePaint event
150
- * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should
151
- * happen within the INVALIDATION_WINDOW of the prePaint event.
152
- */
153
- function getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
154
- const fontRequests = networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));
155
- for (const req of fontRequests) {
156
- const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);
157
- if (!nextPrePaint) {
158
- continue;
159
- }
160
- // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.
161
- if (!isInInvalidationWindow(req, nextPrePaint)) {
162
- continue;
163
- }
164
- // Get the shifts that belong to this prepaint
165
- const shifts = shiftsByPrePaint.get(nextPrePaint);
166
- // if no layout shift(s) in this prePaint, the request is not a root cause.
167
- if (!shifts) {
168
- continue;
169
- }
170
- // Include the root cause to the shifts in this prePaint.
171
- for (const shift of shifts) {
172
- const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {
173
- return {
174
- iframes: [],
175
- fontRequests: [],
176
- };
177
- });
178
- rootCausesForShift.fontRequests.push(req);
179
- }
180
- }
181
- return rootCausesByShift;
182
- }
183
- export function generateInsight(traceParsedData, context) {
184
- const isWithinSameNavigation = ((event) => {
185
- const nav = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);
186
- return nav?.args.data?.navigationId === context.navigationId;
187
- });
188
- const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation);
189
- const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);
190
- const iframeEvents = traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);
191
- const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation);
192
- const layoutShifts = traceParsedData.LayoutShifts.clusters.flatMap(cluster =>
193
- // Use one of the events in the cluster to determine if within the same navigation.
194
- isWithinSameNavigation(cluster.events[0]) ? cluster.events : []);
195
- const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);
196
- // Get root causes.
197
- const rootCausesByShift = new Map();
198
- const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);
199
- for (const shift of layoutShifts) {
200
- rootCausesByShift.set(shift, { iframes: [], fontRequests: [] });
201
- }
202
- getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
203
- getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
204
- return {
205
- animationFailures,
206
- shifts: rootCausesByShift,
207
- };
208
- }
209
- //# sourceMappingURL=CumulativeLayoutShift.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CumulativeLayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type InsightResult,\n type NavigationInsightContext,\n type RequiredData,\n} from './types.js';\n\nexport function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'] {\n return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];\n}\n\nexport const enum AnimationFailureReasons {\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_MAY_MOVE_PIXELS = 'FILTER_MAY_MOVE_PIXELS',\n NON_REPLACE_COMPOSITE_MODE = 'NON_REPLACE_COMPOSITE_MODE',\n INCOMPATIBLE_ANIMATIONS = 'INCOMPATIBLE_ANIMATIONS',\n UNSUPPORTED_TIMING_PARAMS = 'UNSUPPORTED_TIMING_PARAMS',\n}\n\nexport interface NoncompositedAnimationFailure {\n /**\n * Animation name.\n */\n name?: string;\n /**\n * Failure reason based on mask number defined in\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22.\n */\n failureReasons: AnimationFailureReasons[];\n /**\n * Unsupported properties.\n */\n unsupportedProperties?: Types.TraceEvents.TraceEventAnimation['args']['data']['unsupportedProperties'];\n}\n\n/**\n * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define\n * which bit corresponds to each failure reason.\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22\n * @type {{flag: number, failure: AnimationFailureReasons}[]}\n */\nconst ACTIONABLE_FAILURE_REASONS = [\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS,\n },\n];\n\n// 500ms window.\n// Use this window to consider events and requests that may have caused a layout shift.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\nexport interface LayoutShiftRootCausesData {\n iframes: Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[];\n fontRequests: Types.TraceEvents.SyntheticNetworkRequest[];\n}\n\nfunction isInInvalidationWindow(\n event: Types.TraceEvents.TraceEventData, targetEvent: Types.TraceEvents.TraceEventData): boolean {\n const eventEnd = event.dur ? event.ts + event.dur : event.ts;\n return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;\n}\n\n/**\n * Returns a list of NoncompositedAnimationFailures.\n */\nfunction getNonCompositedAnimations(animations: readonly Types.TraceEvents.SyntheticAnimationPair[]):\n NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n for (const event of animations) {\n const beginEvent = event.args.data.beginEvent;\n const instantEvents = event.args.data.instantEvents || [];\n /**\n * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').\n * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.\n */\n for (const event of instantEvents) {\n const failureMask = event.args.data.compositeFailed;\n const unsupportedProperties = event.args.data.unsupportedProperties;\n if (!failureMask || !unsupportedProperties) {\n continue;\n }\n const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => {\n return reason.failure;\n });\n const failure: NoncompositedAnimationFailure = {\n name: beginEvent.args.data.displayName,\n failureReasons,\n unsupportedProperties,\n };\n failures.push(failure);\n }\n }\n return failures;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n\n/**\n * This gets the first prePaint event that follows the provided event and returns it.\n */\nfunction getNextPrePaintEvent(\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n targetEvent: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventPrePaint|undefined {\n // Get the first PrePaint event that happened after the targetEvent.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));\n // No PrePaint event registered after this event\n if (nextPrePaintIndex === null) {\n return undefined;\n }\n\n return prePaintEvents[nextPrePaintIndex];\n}\n\n/**\n * An Iframe is considered a root cause if the iframe event occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs.\n */\nfunction getIframeRootCauses(\n iframeCreatedEvents: readonly Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>,\n rootCausesByShift: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>):\n Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData> {\n for (const iframeEvent of iframeCreatedEvents) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);\n // If no following prePaint, this is not a root cause.\n if (!nextPrePaint) {\n continue;\n }\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n // if no layout shift(s), this is not a root cause.\n if (!shifts) {\n continue;\n }\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframes: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.iframes.push(iframeEvent);\n }\n }\n return rootCausesByShift;\n}\n\n/**\n * A font request is considered a root cause if the request occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should\n * happen within the INVALIDATION_WINDOW of the prePaint event.\n */\nfunction getFontRootCauses(\n networkRequests: Types.TraceEvents.SyntheticNetworkRequest[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>,\n rootCausesByShift: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>):\n Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData> {\n const fontRequests =\n networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));\n\n for (const req of fontRequests) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);\n if (!nextPrePaint) {\n continue;\n }\n\n // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.\n if (!isInInvalidationWindow(req, nextPrePaint)) {\n continue;\n }\n\n // Get the shifts that belong to this prepaint\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n\n // if no layout shift(s) in this prePaint, the request is not a root cause.\n if (!shifts) {\n continue;\n }\n // Include the root cause to the shifts in this prePaint.\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframes: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.fontRequests.push(req);\n }\n }\n return rootCausesByShift;\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext): InsightResult<{\n animationFailures?: readonly NoncompositedAnimationFailure[],\n shifts?: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>,\n}> {\n const isWithinSameNavigation = ((event: Types.TraceEvents.TraceEventData): boolean => {\n const nav =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return nav?.args.data?.navigationId === context.navigationId;\n });\n\n const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation);\n const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);\n\n const iframeEvents =\n traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);\n const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation);\n\n const layoutShifts = traceParsedData.LayoutShifts.clusters.flatMap(\n cluster =>\n // Use one of the events in the cluster to determine if within the same navigation.\n isWithinSameNavigation(cluster.events[0]) ? cluster.events : [],\n );\n const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);\n\n // Get root causes.\n const rootCausesByShift = new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>();\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n for (const shift of layoutShifts) {\n rootCausesByShift.set(shift, {iframes: [], fontRequests: []});\n }\n\n getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n\n return {\n animationFailures,\n shifts: rootCausesByShift,\n };\n}\n"]}
@@ -1,6 +0,0 @@
1
- export * as CumulativeLayoutShift from './CumulativeLayoutShift.js';
2
- export * as DocumentLatency from './DocumentLatency.js';
3
- export * as InteractionToNextPaint from './InteractionToNextPaint.js';
4
- export * as LargestContentfulPaint from './LargestContentfulPaint.js';
5
- export * as RenderBlocking from './RenderBlocking.js';
6
- export * as Viewport from './Viewport.js';
@@ -1,10 +0,0 @@
1
- // Copyright 2024 The Chromium Authors. All rights reserved.
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
- export * as CumulativeLayoutShift from './CumulativeLayoutShift.js';
5
- export * as DocumentLatency from './DocumentLatency.js';
6
- export * as InteractionToNextPaint from './InteractionToNextPaint.js';
7
- export * as LargestContentfulPaint from './LargestContentfulPaint.js';
8
- export * as RenderBlocking from './RenderBlocking.js';
9
- export * as Viewport from './Viewport.js';
10
- //# sourceMappingURL=InsightRunners.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"InsightRunners.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InsightRunners.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as CumulativeLayoutShift from './CumulativeLayoutShift.js';\nexport * as DocumentLatency from './DocumentLatency.js';\nexport * as InteractionToNextPaint from './InteractionToNextPaint.js';\nexport * as LargestContentfulPaint from './LargestContentfulPaint.js';\nexport * as RenderBlocking from './RenderBlocking.js';\nexport * as Viewport from './Viewport.js';\n"]}
@@ -1,25 +0,0 @@
1
- import * as Types from '../types/types.js';
2
- import { type LCPInsightResult, type NavigationInsightContext, type RequiredData } from './types.js';
3
- export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];
4
- export interface LCPPhases {
5
- /**
6
- * The time between when the user initiates loading the page until when
7
- * the browser receives the first byte of the html response.
8
- */
9
- ttfb: Types.Timing.MilliSeconds;
10
- /**
11
- * The time between ttfb and the LCP resource request being started.
12
- * For a text LCP, this is undefined given no resource is loaded.
13
- */
14
- loadDelay?: Types.Timing.MilliSeconds;
15
- /**
16
- * The time it takes to load the LCP resource.
17
- */
18
- loadTime?: Types.Timing.MilliSeconds;
19
- /**
20
- * The time between when the LCP resource finishes loading and when
21
- * the LCP element is rendered.
22
- */
23
- renderDelay: Types.Timing.MilliSeconds;
24
- }
25
- export declare function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext): LCPInsightResult;
@@ -1,93 +0,0 @@
1
- // Copyright 2024 The Chromium Authors. All rights reserved.
2
- // Use of this source code is governed by a BSD-style license that can be
3
- // found in the LICENSE file.
4
- import * as Handlers from '../handlers/handlers.js';
5
- import * as Helpers from '../helpers/helpers.js';
6
- import * as Types from '../types/types.js';
7
- import { findLCPRequest } from './Common.js';
8
- import { InsightWarning } from './types.js';
9
- export function deps() {
10
- return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];
11
- }
12
- function breakdownPhases(nav, mainRequest, lcpMs, lcpRequest) {
13
- const mainReqTiming = mainRequest.args.data.timing;
14
- if (!mainReqTiming) {
15
- throw new Error('no timing for main resource');
16
- }
17
- const firstDocByteTs = Helpers.Timing.secondsToMicroseconds(mainReqTiming.requestTime) +
18
- Helpers.Timing.millisecondsToMicroseconds(mainReqTiming.receiveHeadersStart);
19
- const firstDocByteTiming = Types.Timing.MicroSeconds(firstDocByteTs - nav.ts);
20
- const ttfb = Helpers.Timing.microSecondsToMilliseconds(firstDocByteTiming);
21
- let renderDelay = Types.Timing.MilliSeconds(lcpMs - ttfb);
22
- if (!lcpRequest) {
23
- return { ttfb, renderDelay };
24
- }
25
- const lcpStartTs = Types.Timing.MicroSeconds(lcpRequest.ts - nav.ts);
26
- const resourceStart = Helpers.Timing.microSecondsToMilliseconds(lcpStartTs);
27
- const lcpReqEndTs = Types.Timing.MicroSeconds(lcpRequest.args.data.syntheticData.finishTime - nav.ts);
28
- const resourceEnd = Helpers.Timing.microSecondsToMilliseconds(lcpReqEndTs);
29
- const loadDelay = Types.Timing.MilliSeconds(resourceStart - ttfb);
30
- const loadTime = Types.Timing.MilliSeconds(resourceEnd - resourceStart);
31
- renderDelay = Types.Timing.MilliSeconds(lcpMs - resourceEnd);
32
- return {
33
- ttfb,
34
- loadDelay,
35
- loadTime,
36
- renderDelay,
37
- };
38
- }
39
- export function generateInsight(traceParsedData, context) {
40
- const networkRequests = traceParsedData.NetworkRequests;
41
- const nav = traceParsedData.Meta.navigationsByNavigationId.get(context.navigationId);
42
- if (!nav) {
43
- throw new Error('no trace navigation');
44
- }
45
- const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);
46
- if (!frameMetrics) {
47
- throw new Error('no frame metrics');
48
- }
49
- const navMetrics = frameMetrics.get(context.navigationId);
50
- if (!navMetrics) {
51
- throw new Error('no navigation metrics');
52
- }
53
- const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */);
54
- const lcpEvent = metricScore?.event;
55
- if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) {
56
- return { warnings: [InsightWarning.NO_LCP] };
57
- }
58
- // This helps calculate the phases.
59
- const lcpMs = Helpers.Timing.microSecondsToMilliseconds(metricScore.timing);
60
- // This helps position things on the timeline's UI accurately for a trace.
61
- const lcpTs = metricScore.event?.ts ? Helpers.Timing.microSecondsToMilliseconds(metricScore.event?.ts) : undefined;
62
- const lcpResource = findLCPRequest(traceParsedData, context, lcpEvent);
63
- const mainReq = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);
64
- if (!mainReq) {
65
- return { lcpMs, lcpTs, warnings: [InsightWarning.NO_DOCUMENT_REQUEST] };
66
- }
67
- if (!lcpResource) {
68
- return {
69
- lcpMs: lcpMs,
70
- lcpTs: lcpTs,
71
- phases: breakdownPhases(nav, mainReq, lcpMs, lcpResource),
72
- };
73
- }
74
- const imageLoadingAttr = lcpEvent.args.data?.loadingAttr;
75
- const imagePreloaded = lcpResource?.args.data.isLinkPreload || lcpResource?.args.data.initiator?.type === 'preload';
76
- const imageFetchPriorityHint = lcpResource?.args.data.fetchPriorityHint;
77
- // This is the earliest discovery time an LCP resource could have - it's TTFB.
78
- const earliestDiscoveryTime = mainReq && mainReq.args.data.timing ?
79
- Helpers.Timing.secondsToMicroseconds(mainReq.args.data.timing.requestTime) +
80
- Helpers.Timing.millisecondsToMicroseconds(mainReq.args.data.timing.receiveHeadersStart) :
81
- undefined;
82
- return {
83
- lcpMs: lcpMs,
84
- lcpTs: lcpTs,
85
- phases: breakdownPhases(nav, mainReq, lcpMs, lcpResource),
86
- shouldRemoveLazyLoading: imageLoadingAttr === 'lazy',
87
- shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high',
88
- shouldPreloadImage: !imagePreloaded,
89
- lcpResource,
90
- earliestDiscoveryTimeTs: earliestDiscoveryTime ? Types.Timing.MicroSeconds(earliestDiscoveryTime) : undefined,
91
- };
92
- }
93
- //# sourceMappingURL=LargestContentfulPaint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LargestContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {findLCPRequest} from './Common.js';\nimport {InsightWarning, type LCPInsightResult, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];\n}\n\nexport interface LCPPhases {\n /**\n * The time between when the user initiates loading the page until when\n * the browser receives the first byte of the html response.\n */\n ttfb: Types.Timing.MilliSeconds;\n /**\n * The time between ttfb and the LCP resource request being started.\n * For a text LCP, this is undefined given no resource is loaded.\n */\n loadDelay?: Types.Timing.MilliSeconds;\n /**\n * The time it takes to load the LCP resource.\n */\n loadTime?: Types.Timing.MilliSeconds;\n /**\n * The time between when the LCP resource finishes loading and when\n * the LCP element is rendered.\n */\n renderDelay: Types.Timing.MilliSeconds;\n}\n\nfunction breakdownPhases(\n nav: Types.TraceEvents.TraceEventNavigationStart, mainRequest: Types.TraceEvents.SyntheticNetworkRequest,\n lcpMs: Types.Timing.MilliSeconds, lcpRequest: Types.TraceEvents.SyntheticNetworkRequest|null): LCPPhases {\n const mainReqTiming = mainRequest.args.data.timing;\n if (!mainReqTiming) {\n throw new Error('no timing for main resource');\n }\n const firstDocByteTs = Helpers.Timing.secondsToMicroseconds(mainReqTiming.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(mainReqTiming.receiveHeadersStart);\n\n const firstDocByteTiming = Types.Timing.MicroSeconds(firstDocByteTs - nav.ts);\n const ttfb = Helpers.Timing.microSecondsToMilliseconds(firstDocByteTiming);\n let renderDelay = Types.Timing.MilliSeconds(lcpMs - ttfb);\n\n if (!lcpRequest) {\n return {ttfb, renderDelay};\n }\n\n const lcpStartTs = Types.Timing.MicroSeconds(lcpRequest.ts - nav.ts);\n const resourceStart = Helpers.Timing.microSecondsToMilliseconds(lcpStartTs);\n\n const lcpReqEndTs = Types.Timing.MicroSeconds(lcpRequest.args.data.syntheticData.finishTime - nav.ts);\n const resourceEnd = Helpers.Timing.microSecondsToMilliseconds(lcpReqEndTs);\n\n const loadDelay = Types.Timing.MilliSeconds(resourceStart - ttfb);\n const loadTime = Types.Timing.MilliSeconds(resourceEnd - resourceStart);\n renderDelay = Types.Timing.MilliSeconds(lcpMs - resourceEnd);\n\n return {\n ttfb,\n loadDelay,\n loadTime,\n renderDelay,\n };\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext): LCPInsightResult {\n const networkRequests = traceParsedData.NetworkRequests;\n\n const nav = traceParsedData.Meta.navigationsByNavigationId.get(context.navigationId);\n if (!nav) {\n throw new Error('no trace navigation');\n }\n\n const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);\n if (!frameMetrics) {\n throw new Error('no frame metrics');\n }\n\n const navMetrics = frameMetrics.get(context.navigationId);\n if (!navMetrics) {\n throw new Error('no navigation metrics');\n }\n const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n const lcpEvent = metricScore?.event;\n if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) {\n return {warnings: [InsightWarning.NO_LCP]};\n }\n\n // This helps calculate the phases.\n const lcpMs = Helpers.Timing.microSecondsToMilliseconds(metricScore.timing);\n // This helps position things on the timeline's UI accurately for a trace.\n const lcpTs = metricScore.event?.ts ? Helpers.Timing.microSecondsToMilliseconds(metricScore.event?.ts) : undefined;\n const lcpResource = findLCPRequest(traceParsedData, context, lcpEvent);\n const mainReq = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!mainReq) {\n return {lcpMs, lcpTs, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]};\n }\n\n if (!lcpResource) {\n return {\n lcpMs: lcpMs,\n lcpTs: lcpTs,\n phases: breakdownPhases(nav, mainReq, lcpMs, lcpResource),\n };\n }\n\n const imageLoadingAttr = lcpEvent.args.data?.loadingAttr;\n const imagePreloaded = lcpResource?.args.data.isLinkPreload || lcpResource?.args.data.initiator?.type === 'preload';\n const imageFetchPriorityHint = lcpResource?.args.data.fetchPriorityHint;\n\n // This is the earliest discovery time an LCP resource could have - it's TTFB.\n const earliestDiscoveryTime = mainReq && mainReq.args.data.timing ?\n Helpers.Timing.secondsToMicroseconds(mainReq.args.data.timing.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(mainReq.args.data.timing.receiveHeadersStart) :\n undefined;\n\n return {\n lcpMs: lcpMs,\n lcpTs: lcpTs,\n phases: breakdownPhases(nav, mainReq, lcpMs, lcpResource),\n shouldRemoveLazyLoading: imageLoadingAttr === 'lazy',\n shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high',\n shouldPreloadImage: !imagePreloaded,\n lcpResource,\n earliestDiscoveryTimeTs: earliestDiscoveryTime ? Types.Timing.MicroSeconds(earliestDiscoveryTime) : undefined,\n };\n}\n"]}
@@ -1,91 +0,0 @@
1
- import { type CPUNode } from './CPUNode.js';
2
- import { type NetworkNode } from './NetworkNode.js';
3
- import type * as Lantern from './types/lantern.js';
4
- /**
5
- * A union of all types derived from BaseNode, allowing type check discrimination
6
- * based on `node.type`. If a new node type is created, it should be added here.
7
- */
8
- export type Node<T = Lantern.AnyNetworkObject> = CPUNode<T> | NetworkNode<T>;
9
- /**
10
- * @fileoverview This class encapsulates logic for handling resources and tasks used to model the
11
- * execution dependency graph of the page. A node has a unique identifier and can depend on other
12
- * nodes/be depended on. The construction of the graph maintains some important invariants that are
13
- * inherent to the model:
14
- *
15
- * 1. The graph is a DAG, there are no cycles.
16
- * 2. There is always a root node upon which all other nodes eventually depend.
17
- *
18
- * This allows particular optimizations in this class so that we do no need to check for cycles as
19
- * these methods are called and we can always start traversal at the root node.
20
- */
21
- declare class BaseNode<T = Lantern.AnyNetworkObject> {
22
- static types: {
23
- readonly NETWORK: "network";
24
- readonly CPU: "cpu";
25
- };
26
- _id: string;
27
- _isMainDocument: boolean;
28
- _dependents: Node[];
29
- _dependencies: Node[];
30
- constructor(id: string);
31
- get id(): string;
32
- get type(): 'network' | 'cpu';
33
- /**
34
- * In microseconds
35
- */
36
- get startTime(): number;
37
- /**
38
- * In microseconds
39
- */
40
- get endTime(): number;
41
- setIsMainDocument(value: boolean): void;
42
- isMainDocument(): boolean;
43
- getDependents(): Node[];
44
- getNumberOfDependents(): number;
45
- getDependencies(): Node[];
46
- getNumberOfDependencies(): number;
47
- getRootNode(): Node<T>;
48
- addDependent(node: Node): void;
49
- addDependency(node: Node): void;
50
- removeDependent(node: Node): void;
51
- removeDependency(node: Node): void;
52
- removeAllDependencies(): void;
53
- /**
54
- * Computes whether the given node is anywhere in the dependency graph of this node.
55
- * While this method can prevent cycles, it walks the graph and should be used sparingly.
56
- * Nodes are always considered dependent on themselves for the purposes of cycle detection.
57
- */
58
- isDependentOn(node: BaseNode<T>): boolean;
59
- /**
60
- * Clones the node's information without adding any dependencies/dependents.
61
- */
62
- cloneWithoutRelationships(): Node<T>;
63
- /**
64
- * Clones the entire graph connected to this node filtered by the optional predicate. If a node is
65
- * included by the predicate, all nodes along the paths between the node and the root will be included. If the
66
- * node this was called on is not included in the resulting filtered graph, the method will throw.
67
- */
68
- cloneWithRelationships(predicate?: (arg0: Node) => boolean): Node;
69
- /**
70
- * Traverses all connected nodes in BFS order, calling `callback` exactly once
71
- * on each. `traversalPath` is the shortest (though not necessarily unique)
72
- * path from `node` to the root of the iteration.
73
- *
74
- * The `getNextNodes` function takes a visited node and returns which nodes to
75
- * visit next. It defaults to returning the node's dependents.
76
- */
77
- traverse(callback: (node: Node<T>, traversalPath: Node<T>[]) => void, getNextNodes?: (arg0: Node<T>) => Node<T>[]): void;
78
- /**
79
- * @see BaseNode.traverse
80
- */
81
- traverseGenerator(getNextNodes?: (arg0: Node) => Node[]): Generator<{
82
- node: Node;
83
- traversalPath: Node[];
84
- }, void, unknown>;
85
- /**
86
- * Returns whether the given node has a cycle in its dependent graph by performing a DFS.
87
- */
88
- static hasCycle(node: Node, direction?: 'dependents' | 'dependencies' | 'both'): boolean;
89
- canDependOn(node: Node): boolean;
90
- }
91
- export { BaseNode };