@paulirish/trace_engine 0.0.10 → 0.0.11

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 (205) hide show
  1. package/analyze-trace.mjs +1 -1
  2. package/core/platform/DevToolsPath.d.ts +4 -13
  3. package/core/platform/DevToolsPath.js +7 -4
  4. package/core/platform/DevToolsPath.js.map +1 -7
  5. package/core/platform/MimeType.d.ts +27 -0
  6. package/core/platform/MimeType.js +119 -86
  7. package/core/platform/MimeType.js.map +1 -7
  8. package/core/platform/Timing.d.ts +7 -0
  9. package/core/platform/Timing.js +7 -4
  10. package/core/platform/Timing.js.map +1 -7
  11. package/core/platform/UIString.d.ts +2 -5
  12. package/core/platform/UIString.js +5 -2
  13. package/core/platform/UIString.js.map +1 -7
  14. package/core/platform/UserVisibleError.js +19 -10
  15. package/core/platform/UserVisibleError.js.map +1 -7
  16. package/core/platform/array-utilities.d.ts +48 -10
  17. package/core/platform/array-utilities.js +160 -124
  18. package/core/platform/array-utilities.js.map +1 -7
  19. package/core/platform/brand.d.ts +14 -0
  20. package/core/platform/brand.js +5 -1
  21. package/core/platform/brand.js.map +1 -7
  22. package/core/platform/date-utilities.js +10 -6
  23. package/core/platform/date-utilities.js.map +1 -7
  24. package/core/platform/dom-utilities.d.ts +3 -1
  25. package/core/platform/dom-utilities.js +94 -83
  26. package/core/platform/dom-utilities.js.map +1 -7
  27. package/core/platform/keyboard-utilities.d.ts +2 -0
  28. package/core/platform/keyboard-utilities.js +15 -24
  29. package/core/platform/keyboard-utilities.js.map +1 -7
  30. package/core/platform/map-utilities.d.ts +4 -0
  31. package/core/platform/map-utilities.js +66 -60
  32. package/core/platform/map-utilities.js.map +1 -7
  33. package/core/platform/number-utilities.js +66 -55
  34. package/core/platform/number-utilities.js.map +1 -7
  35. package/core/platform/platform.d.ts +5 -1
  36. package/core/platform/platform.js +54 -37
  37. package/core/platform/platform.js.map +1 -7
  38. package/core/platform/promise-utilities.d.ts +10 -0
  39. package/core/platform/promise-utilities.js +16 -8
  40. package/core/platform/promise-utilities.js.map +1 -7
  41. package/core/platform/set-utilities.js +20 -17
  42. package/core/platform/set-utilities.js.map +1 -7
  43. package/core/platform/string-utilities.d.ts +32 -1
  44. package/core/platform/string-utilities.js +453 -379
  45. package/core/platform/string-utilities.js.map +1 -7
  46. package/core/platform/typescript-utilities.d.ts +5 -5
  47. package/core/platform/typescript-utilities.js +19 -7
  48. package/core/platform/typescript-utilities.js.map +1 -7
  49. package/generated/protocol.d.ts +2081 -347
  50. package/generated/protocol.js +5 -2230
  51. package/models/cpu_profile/CPUProfileDataModel.d.ts +77 -0
  52. package/models/cpu_profile/CPUProfileDataModel.js +492 -359
  53. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -7
  54. package/models/cpu_profile/ProfileTreeModel.d.ts +29 -0
  55. package/models/cpu_profile/ProfileTreeModel.js +87 -82
  56. package/models/cpu_profile/ProfileTreeModel.js.map +1 -7
  57. package/models/cpu_profile/cpu_profile.d.ts +3 -0
  58. package/models/cpu_profile/cpu_profile.js +7 -7
  59. package/models/cpu_profile/cpu_profile.js.map +1 -7
  60. package/models/trace/EntriesFilter.d.ts +55 -0
  61. package/models/trace/EntriesFilter.js +227 -166
  62. package/models/trace/EntriesFilter.js.map +1 -7
  63. package/models/trace/LegacyTracingModel.js.map +1 -7
  64. package/models/trace/ModelImpl.d.ts +110 -0
  65. package/models/trace/ModelImpl.js +161 -102
  66. package/models/trace/ModelImpl.js.map +1 -7
  67. package/models/trace/Processor.d.ts +36 -0
  68. package/models/trace/Processor.js +197 -163
  69. package/models/trace/Processor.js.map +1 -7
  70. package/models/trace/TracingManager.js.map +1 -7
  71. package/models/trace/extras/FetchNodes.d.ts +46 -0
  72. package/models/trace/extras/FetchNodes.js +132 -91
  73. package/models/trace/extras/FetchNodes.js.map +1 -7
  74. package/models/trace/extras/FilmStrip.d.ts +19 -0
  75. package/models/trace/extras/FilmStrip.js +38 -31
  76. package/models/trace/extras/FilmStrip.js.map +1 -7
  77. package/models/trace/extras/MainThreadActivity.d.ts +2 -0
  78. package/models/trace/extras/MainThreadActivity.js +72 -56
  79. package/models/trace/extras/MainThreadActivity.js.map +1 -7
  80. package/models/trace/extras/Metadata.d.ts +2 -0
  81. package/models/trace/extras/Metadata.js +42 -26
  82. package/models/trace/extras/Metadata.js.map +1 -7
  83. package/models/trace/extras/extras.js.map +1 -7
  84. package/models/trace/handlers/AnimationHandler.d.ts +8 -0
  85. package/models/trace/handlers/AnimationHandler.js +22 -20
  86. package/models/trace/handlers/AnimationHandler.js.map +1 -7
  87. package/models/trace/handlers/AuctionWorkletsHandler.d.ts +8 -0
  88. package/models/trace/handlers/AuctionWorkletsHandler.js +143 -89
  89. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -7
  90. package/models/trace/handlers/FramesHandler.d.ts +76 -0
  91. package/models/trace/handlers/FramesHandler.js +424 -355
  92. package/models/trace/handlers/FramesHandler.js.map +1 -7
  93. package/models/trace/handlers/GPUHandler.d.ts +11 -0
  94. package/models/trace/handlers/GPUHandler.js +41 -37
  95. package/models/trace/handlers/GPUHandler.js.map +1 -7
  96. package/models/trace/handlers/InitiatorsHandler.d.ts +10 -0
  97. package/models/trace/handlers/InitiatorsHandler.js +164 -113
  98. package/models/trace/handlers/InitiatorsHandler.js.map +1 -7
  99. package/models/trace/handlers/InvalidationsHandler.d.ts +10 -0
  100. package/models/trace/handlers/InvalidationsHandler.js +101 -79
  101. package/models/trace/handlers/InvalidationsHandler.js.map +1 -7
  102. package/models/trace/handlers/LargestImagePaintHandler.d.ts +5 -0
  103. package/models/trace/handlers/LargestImagePaintHandler.js +32 -12
  104. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -7
  105. package/models/trace/handlers/LargestTextPaintHandler.d.ts +5 -0
  106. package/models/trace/handlers/LargestTextPaintHandler.js +20 -12
  107. package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -7
  108. package/models/trace/handlers/LayerTreeHandler.d.ts +13 -0
  109. package/models/trace/handlers/LayerTreeHandler.js +96 -70
  110. package/models/trace/handlers/LayerTreeHandler.js.map +1 -7
  111. package/models/trace/handlers/LayoutShiftsHandler.d.ts +44 -0
  112. package/models/trace/handlers/LayoutShiftsHandler.js +304 -227
  113. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -7
  114. package/models/trace/handlers/MemoryHandler.d.ts +7 -0
  115. package/models/trace/handlers/MemoryHandler.js +14 -11
  116. package/models/trace/handlers/MemoryHandler.js.map +1 -7
  117. package/models/trace/handlers/MetaHandler.d.ts +37 -0
  118. package/models/trace/handlers/MetaHandler.js +314 -226
  119. package/models/trace/handlers/MetaHandler.js.map +1 -7
  120. package/models/trace/handlers/ModelHandlers.d.ts +21 -0
  121. package/models/trace/handlers/ModelHandlers.js +25 -22
  122. package/models/trace/handlers/ModelHandlers.js.map +1 -7
  123. package/models/trace/handlers/NetworkRequestsHandler.d.ts +17 -0
  124. package/models/trace/handlers/NetworkRequestsHandler.js +342 -218
  125. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -7
  126. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +67 -0
  127. package/models/trace/handlers/PageLoadMetricsHandler.js +357 -284
  128. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -7
  129. package/models/trace/handlers/RendererHandler.d.ts +101 -0
  130. package/models/trace/handlers/RendererHandler.js +295 -191
  131. package/models/trace/handlers/RendererHandler.js.map +1 -7
  132. package/models/trace/handlers/SamplesHandler.d.ts +46 -0
  133. package/models/trace/handlers/SamplesHandler.js +195 -158
  134. package/models/trace/handlers/SamplesHandler.js.map +1 -7
  135. package/models/trace/handlers/ScreenshotsHandler.d.ts +7 -0
  136. package/models/trace/handlers/ScreenshotsHandler.js +63 -41
  137. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -7
  138. package/models/trace/handlers/Threads.d.ts +33 -0
  139. package/models/trace/handlers/Threads.js +85 -67
  140. package/models/trace/handlers/Threads.js.map +1 -7
  141. package/models/trace/handlers/UserInteractionsHandler.d.ts +57 -0
  142. package/models/trace/handlers/UserInteractionsHandler.js +240 -141
  143. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -7
  144. package/models/trace/handlers/UserTimingsHandler.d.ts +28 -0
  145. package/models/trace/handlers/UserTimingsHandler.js +91 -80
  146. package/models/trace/handlers/UserTimingsHandler.js.map +1 -7
  147. package/models/trace/handlers/WarningsHandler.d.ts +14 -0
  148. package/models/trace/handlers/WarningsHandler.js +100 -62
  149. package/models/trace/handlers/WarningsHandler.js.map +1 -7
  150. package/models/trace/handlers/WorkersHandler.d.ts +11 -0
  151. package/models/trace/handlers/WorkersHandler.js +40 -38
  152. package/models/trace/handlers/WorkersHandler.js.map +1 -7
  153. package/models/trace/handlers/handlers.d.ts +3 -0
  154. package/models/trace/handlers/handlers.js +7 -4
  155. package/models/trace/handlers/handlers.js.map +1 -7
  156. package/models/trace/handlers/types.d.ts +45 -0
  157. package/models/trace/handlers/types.js +15 -15
  158. package/models/trace/handlers/types.js.map +1 -7
  159. package/models/trace/helpers/SamplesIntegrator.d.ts +49 -0
  160. package/models/trace/helpers/SamplesIntegrator.js +381 -204
  161. package/models/trace/helpers/SamplesIntegrator.js.map +1 -7
  162. package/models/trace/helpers/Timing.d.ts +26 -0
  163. package/models/trace/helpers/Timing.js +131 -110
  164. package/models/trace/helpers/Timing.js.map +1 -7
  165. package/models/trace/helpers/Trace.d.ts +37 -0
  166. package/models/trace/helpers/Trace.js +200 -166
  167. package/models/trace/helpers/Trace.js.map +1 -7
  168. package/models/trace/helpers/TreeHelpers.d.ts +90 -0
  169. package/models/trace/helpers/TreeHelpers.js +203 -100
  170. package/models/trace/helpers/TreeHelpers.js.map +1 -7
  171. package/models/trace/helpers/helpers.d.ts +4 -0
  172. package/models/trace/helpers/helpers.js +8 -5
  173. package/models/trace/helpers/helpers.js.map +1 -7
  174. package/models/trace/root-causes/LayoutShift.d.ts +119 -0
  175. package/models/trace/root-causes/LayoutShift.js +470 -323
  176. package/models/trace/root-causes/LayoutShift.js.map +1 -7
  177. package/models/trace/root-causes/RootCauses.d.ts +14 -0
  178. package/models/trace/root-causes/RootCauses.js +9 -6
  179. package/models/trace/root-causes/RootCauses.js.map +1 -7
  180. package/models/trace/root-causes/root-causes.d.ts +1 -0
  181. package/models/trace/root-causes/root-causes.js +5 -2
  182. package/models/trace/root-causes/root-causes.js.map +1 -7
  183. package/models/trace/trace.d.ts +11 -0
  184. package/models/trace/trace.js +17 -23
  185. package/models/trace/trace.js.map +1 -7
  186. package/models/trace/types/Configuration.d.ts +33 -0
  187. package/models/trace/types/Configuration.js +25 -14
  188. package/models/trace/types/Configuration.js.map +1 -7
  189. package/models/trace/types/File.d.ts +23 -0
  190. package/models/trace/types/File.js +5 -6
  191. package/models/trace/types/File.js.map +1 -7
  192. package/models/trace/types/Timing.d.ts +25 -0
  193. package/models/trace/types/Timing.js +10 -11
  194. package/models/trace/types/Timing.js.map +1 -7
  195. package/models/trace/types/TraceEvents.d.ts +1571 -0
  196. package/models/trace/types/TraceEvents.js +174 -381
  197. package/models/trace/types/TraceEvents.js.map +1 -7
  198. package/models/trace/types/types.d.ts +4 -0
  199. package/models/trace/types/types.js +8 -5
  200. package/models/trace/types/types.js.map +1 -7
  201. package/package.json +1 -1
  202. package/TracingManager.js +0 -0
  203. package/extras/extras.js +0 -0
  204. package/trace.mjs +0 -6980
  205. package/trace.mjs.map +0 -8
@@ -0,0 +1,46 @@
1
+ import type * as Protocol from '../../../generated/protocol.js';
2
+ import * as SDK from '../../../core/sdk/sdk.js';
3
+ import type * as Handlers from '../handlers/handlers.js';
4
+ import type * as Types from '../types/types.js';
5
+ export declare function _TEST_clearCache(): void;
6
+ /**
7
+ * Looks up the DOM Node on the page for the given BackendNodeId. Uses the
8
+ * provided TraceParseData as the cache and will cache the result after the
9
+ * first lookup.
10
+ */
11
+ export declare function domNodeForBackendNodeID(modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode | null>;
12
+ /**
13
+ * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.
14
+ * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.
15
+ */
16
+ export declare function domNodesForMultipleBackendNodeIds(modelData: Handlers.Types.TraceParseData, nodeIds: Set<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null>>;
17
+ export interface LayoutShiftSource {
18
+ previousRect: DOMRect;
19
+ currentRect: DOMRect;
20
+ node: SDK.DOMModel.DOMNode;
21
+ }
22
+ /**
23
+ * Calculates and returns a list of sources for a LayoutShift.
24
+ * Here, a source is considered as a node that moved and contributed to the
25
+ * given LayoutShift existing and the score it was given. Each source returned
26
+ * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both
27
+ * before and now, so we can see how this node changed and how that impacted the
28
+ * layout shift.
29
+ *
30
+ * This data is cached based on the provided model data and the given layout
31
+ * shift, so it is is safe to call multiple times with the same input.
32
+ */
33
+ export declare function sourcesForLayoutShift(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]>;
34
+ /**
35
+ * Takes a LayoutShift and normalizes its node dimensions based on the device
36
+ * pixel ratio (DPR) of the user's display.
37
+ * This is required because the Layout Instability API is not based on CSS
38
+ * pixels, but physical pixels. Therefore we need to map these to normalized CSS
39
+ * pixels if we can. For example, if the user is on a device with a DPR of 2,
40
+ * the values of the node dimensions reported by the Instability API need to be
41
+ * divided by 2 to be accurate.
42
+ * This function is safe to call multiple times as results are cached based on
43
+ * the provided model data.
44
+ * See https://crbug.com/1300309 for details.
45
+ */
46
+ export declare function normalizedImpactedNodesForLayoutShift(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]>;
@@ -1,104 +1,145 @@
1
- import * as SDK from "../../../core/sdk/sdk.js";
2
- const domLookUpSingleNodeCache = /* @__PURE__ */ new Map();
3
- const domLookUpBatchNodesCache = /* @__PURE__ */ new Map();
1
+ // Copyright 2023 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 SDK from '../../../core/sdk/sdk.js';
5
+ const domLookUpSingleNodeCache = new Map();
6
+ const domLookUpBatchNodesCache = new Map();
7
+ // eslint-disable-next-line @typescript-eslint/naming-convention
4
8
  export function _TEST_clearCache() {
5
- domLookUpSingleNodeCache.clear();
6
- domLookUpBatchNodesCache.clear();
7
- layoutShiftSourcesCache.clear();
8
- normalizedLayoutShiftNodesCache.clear();
9
+ domLookUpSingleNodeCache.clear();
10
+ domLookUpBatchNodesCache.clear();
11
+ layoutShiftSourcesCache.clear();
12
+ normalizedLayoutShiftNodesCache.clear();
9
13
  }
14
+ /**
15
+ * Looks up the DOM Node on the page for the given BackendNodeId. Uses the
16
+ * provided TraceParseData as the cache and will cache the result after the
17
+ * first lookup.
18
+ */
10
19
  export async function domNodeForBackendNodeID(modelData, nodeId) {
11
- const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);
12
- if (fromCache !== void 0) {
13
- return fromCache;
14
- }
15
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
16
- const domModel = target?.model(SDK.DOMModel.DOMModel);
17
- if (!domModel) {
18
- return null;
19
- }
20
- const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(/* @__PURE__ */ new Set([nodeId]));
21
- const result = domNodesMap?.get(nodeId) || null;
22
- const cacheForModel = domLookUpSingleNodeCache.get(modelData) || /* @__PURE__ */ new Map();
23
- cacheForModel.set(nodeId, result);
24
- domLookUpSingleNodeCache.set(modelData, cacheForModel);
25
- return result;
20
+ const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);
21
+ if (fromCache !== undefined) {
22
+ return fromCache;
23
+ }
24
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
25
+ const domModel = target?.model(SDK.DOMModel.DOMModel);
26
+ if (!domModel) {
27
+ return null;
28
+ }
29
+ const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));
30
+ const result = domNodesMap?.get(nodeId) || null;
31
+ const cacheForModel = domLookUpSingleNodeCache.get(modelData) || new Map();
32
+ cacheForModel.set(nodeId, result);
33
+ domLookUpSingleNodeCache.set(modelData, cacheForModel);
34
+ return result;
26
35
  }
36
+ /**
37
+ * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.
38
+ * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.
39
+ */
27
40
  export async function domNodesForMultipleBackendNodeIds(modelData, nodeIds) {
28
- const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);
29
- if (fromCache) {
30
- return fromCache;
31
- }
32
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
33
- const domModel = target?.model(SDK.DOMModel.DOMModel);
34
- if (!domModel) {
35
- return /* @__PURE__ */ new Map();
36
- }
37
- const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIds) || /* @__PURE__ */ new Map();
38
- const cacheForModel = domLookUpBatchNodesCache.get(modelData) || /* @__PURE__ */ new Map();
39
- cacheForModel.set(nodeIds, domNodesMap);
40
- domLookUpBatchNodesCache.set(modelData, cacheForModel);
41
- return domNodesMap;
41
+ const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);
42
+ if (fromCache) {
43
+ return fromCache;
44
+ }
45
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
46
+ const domModel = target?.model(SDK.DOMModel.DOMModel);
47
+ if (!domModel) {
48
+ return new Map();
49
+ }
50
+ const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIds) || new Map();
51
+ const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||
52
+ new Map();
53
+ cacheForModel.set(nodeIds, domNodesMap);
54
+ domLookUpBatchNodesCache.set(modelData, cacheForModel);
55
+ return domNodesMap;
42
56
  }
43
- const layoutShiftSourcesCache = /* @__PURE__ */ new Map();
44
- const normalizedLayoutShiftNodesCache = /* @__PURE__ */ new Map();
57
+ const layoutShiftSourcesCache = new Map();
58
+ const normalizedLayoutShiftNodesCache = new Map();
59
+ /**
60
+ * Calculates and returns a list of sources for a LayoutShift.
61
+ * Here, a source is considered as a node that moved and contributed to the
62
+ * given LayoutShift existing and the score it was given. Each source returned
63
+ * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both
64
+ * before and now, so we can see how this node changed and how that impacted the
65
+ * layout shift.
66
+ *
67
+ * This data is cached based on the provided model data and the given layout
68
+ * shift, so it is is safe to call multiple times with the same input.
69
+ */
45
70
  export async function sourcesForLayoutShift(modelData, event) {
46
- const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);
47
- if (fromCache) {
48
- return fromCache;
49
- }
50
- const impactedNodes = event.args.data?.impacted_nodes;
51
- if (!impactedNodes) {
52
- return [];
53
- }
54
- const sources = [];
55
- await Promise.all(impactedNodes.map(async (node) => {
56
- const domNode = await domNodeForBackendNodeID(modelData, node.node_id);
57
- if (domNode) {
58
- sources.push({
59
- previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),
60
- currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),
61
- node: domNode
62
- });
71
+ const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);
72
+ if (fromCache) {
73
+ return fromCache;
63
74
  }
64
- }));
65
- const cacheForModel = layoutShiftSourcesCache.get(modelData) || /* @__PURE__ */ new Map();
66
- cacheForModel.set(event, sources);
67
- layoutShiftSourcesCache.set(modelData, cacheForModel);
68
- return sources;
75
+ const impactedNodes = event.args.data?.impacted_nodes;
76
+ if (!impactedNodes) {
77
+ return [];
78
+ }
79
+ const sources = [];
80
+ await Promise.all(impactedNodes.map(async (node) => {
81
+ const domNode = await domNodeForBackendNodeID(modelData, node.node_id);
82
+ if (domNode) {
83
+ sources.push({
84
+ previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),
85
+ currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),
86
+ node: domNode,
87
+ });
88
+ }
89
+ }));
90
+ const cacheForModel = layoutShiftSourcesCache.get(modelData) || new Map();
91
+ cacheForModel.set(event, sources);
92
+ layoutShiftSourcesCache.set(modelData, cacheForModel);
93
+ return sources;
69
94
  }
95
+ /**
96
+ * Takes a LayoutShift and normalizes its node dimensions based on the device
97
+ * pixel ratio (DPR) of the user's display.
98
+ * This is required because the Layout Instability API is not based on CSS
99
+ * pixels, but physical pixels. Therefore we need to map these to normalized CSS
100
+ * pixels if we can. For example, if the user is on a device with a DPR of 2,
101
+ * the values of the node dimensions reported by the Instability API need to be
102
+ * divided by 2 to be accurate.
103
+ * This function is safe to call multiple times as results are cached based on
104
+ * the provided model data.
105
+ * See https://crbug.com/1300309 for details.
106
+ */
70
107
  export async function normalizedImpactedNodesForLayoutShift(modelData, event) {
71
- const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);
72
- if (fromCache) {
73
- return fromCache;
74
- }
75
- const impactedNodes = event.args?.data?.impacted_nodes;
76
- if (!impactedNodes) {
77
- return [];
78
- }
79
- let viewportScale = null;
80
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
81
- const evaluateResult = await target?.runtimeAgent().invoke_evaluate({ expression: "window.devicePixelRatio" });
82
- if (evaluateResult?.result.type === "number") {
83
- viewportScale = evaluateResult?.result.value ?? null;
84
- }
85
- if (!viewportScale) {
86
- return impactedNodes;
87
- }
88
- const normalizedNodes = [];
89
- for (const impactedNode of impactedNodes) {
90
- const newNode = { ...impactedNode };
91
- for (let i = 0; i < impactedNode.old_rect.length; i++) {
92
- newNode.old_rect[i] /= viewportScale;
108
+ const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);
109
+ if (fromCache) {
110
+ return fromCache;
111
+ }
112
+ const impactedNodes = event.args?.data?.impacted_nodes;
113
+ if (!impactedNodes) {
114
+ return [];
115
+ }
116
+ let viewportScale = null;
117
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
118
+ // Get the CSS-to-physical pixel ratio of the device the inspected
119
+ // target is running at.
120
+ const evaluateResult = await target?.runtimeAgent().invoke_evaluate({ expression: 'window.devicePixelRatio' });
121
+ if (evaluateResult?.result.type === 'number') {
122
+ viewportScale = evaluateResult?.result.value ?? null;
123
+ }
124
+ if (!viewportScale) {
125
+ // Bail and return the nodes as is.
126
+ return impactedNodes;
93
127
  }
94
- for (let i = 0; i < impactedNode.new_rect.length; i++) {
95
- newNode.new_rect[i] /= viewportScale;
128
+ const normalizedNodes = [];
129
+ for (const impactedNode of impactedNodes) {
130
+ const newNode = { ...impactedNode };
131
+ for (let i = 0; i < impactedNode.old_rect.length; i++) {
132
+ newNode.old_rect[i] /= viewportScale;
133
+ }
134
+ for (let i = 0; i < impactedNode.new_rect.length; i++) {
135
+ newNode.new_rect[i] /= viewportScale;
136
+ }
137
+ normalizedNodes.push(newNode);
96
138
  }
97
- normalizedNodes.push(newNode);
98
- }
99
- const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) || /* @__PURE__ */ new Map();
100
- cacheForModel.set(event, normalizedNodes);
101
- normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);
102
- return normalizedNodes;
139
+ const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||
140
+ new Map();
141
+ cacheForModel.set(event, normalizedNodes);
142
+ normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);
143
+ return normalizedNodes;
103
144
  }
104
- //# sourceMappingURL=FetchNodes.js.map
145
+ //# sourceMappingURL=FetchNodes.js.map
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../../../front_end/models/trace/extras/FetchNodes.ts"],
4
- "sourcesContent": ["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Types from '../types/types.js';\n\nconst domLookUpSingleNodeCache =\n new Map<Handlers.Types.TraceParseData, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\nconst domLookUpBatchNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Set<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>>();\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function _TEST_clearCache(): void {\n domLookUpSingleNodeCache.clear();\n domLookUpBatchNodesCache.clear();\n layoutShiftSourcesCache.clear();\n normalizedLayoutShiftNodesCache.clear();\n}\n\n/**\n * Looks up the DOM Node on the page for the given BackendNodeId. Uses the\n * provided TraceParseData as the cache and will cache the result after the\n * first lookup.\n */\nexport async function domNodeForBackendNodeID(\n modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode|null> {\n const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);\n if (fromCache !== undefined) {\n return fromCache;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return null;\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));\n const result = domNodesMap?.get(nodeId) || null;\n\n const cacheForModel =\n domLookUpSingleNodeCache.get(modelData) || new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>();\n cacheForModel.set(nodeId, result);\n domLookUpSingleNodeCache.set(modelData, cacheForModel);\n\n return result;\n}\n\n/**\n * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.\n * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.\n */\nexport async function domNodesForMultipleBackendNodeIds(\n modelData: Handlers.Types.TraceParseData,\n nodeIds: Set<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>> {\n const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);\n if (fromCache) {\n return fromCache;\n }\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return new Map();\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIds) || new Map();\n\n const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||\n new Map<Set<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\n cacheForModel.set(nodeIds, domNodesMap);\n domLookUpBatchNodesCache.set(modelData, cacheForModel);\n\n return domNodesMap;\n}\n\nconst layoutShiftSourcesCache = new Map<\n Handlers.Types.TraceParseData, Map<Types.TraceEvents.TraceEventLayoutShift, readonly LayoutShiftSource[]>>();\n\nconst normalizedLayoutShiftNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>>();\n\nexport interface LayoutShiftSource {\n previousRect: DOMRect;\n currentRect: DOMRect;\n node: SDK.DOMModel.DOMNode;\n}\n\n/**\n * Calculates and returns a list of sources for a LayoutShift.\n * Here, a source is considered as a node that moved and contributed to the\n * given LayoutShift existing and the score it was given. Each source returned\n * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both\n * before and now, so we can see how this node changed and how that impacted the\n * layout shift.\n *\n * This data is cached based on the provided model data and the given layout\n * shift, so it is is safe to call multiple times with the same input.\n */\nexport async function sourcesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]> {\n const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n const sources: LayoutShiftSource[] = [];\n await Promise.all(impactedNodes.map(async node => {\n const domNode = await domNodeForBackendNodeID(modelData, node.node_id);\n if (domNode) {\n sources.push({\n previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),\n currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),\n node: domNode,\n });\n }\n }));\n const cacheForModel =\n layoutShiftSourcesCache.get(modelData) || new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftSource[]>();\n cacheForModel.set(event, sources);\n layoutShiftSourcesCache.set(modelData, cacheForModel);\n return sources;\n}\n\n/**\n * Takes a LayoutShift and normalizes its node dimensions based on the device\n * pixel ratio (DPR) of the user's display.\n * This is required because the Layout Instability API is not based on CSS\n * pixels, but physical pixels. Therefore we need to map these to normalized CSS\n * pixels if we can. For example, if the user is on a device with a DPR of 2,\n * the values of the node dimensions reported by the Instability API need to be\n * divided by 2 to be accurate.\n * This function is safe to call multiple times as results are cached based on\n * the provided model data.\n * See https://crbug.com/1300309 for details.\n */\nexport async function normalizedImpactedNodesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]> {\n const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args?.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n\n let viewportScale: number|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Get the CSS-to-physical pixel ratio of the device the inspected\n // target is running at.\n const evaluateResult = await target?.runtimeAgent().invoke_evaluate({expression: 'window.devicePixelRatio'});\n if (evaluateResult?.result.type === 'number') {\n viewportScale = evaluateResult?.result.value as number ?? null;\n }\n\n if (!viewportScale) {\n // Bail and return the nodes as is.\n return impactedNodes;\n }\n\n const normalizedNodes: Types.TraceEvents.TraceImpactedNode[] = [];\n for (const impactedNode of impactedNodes) {\n const newNode = {...impactedNode};\n for (let i = 0; i < impactedNode.old_rect.length; i++) {\n newNode.old_rect[i] /= viewportScale;\n }\n for (let i = 0; i < impactedNode.new_rect.length; i++) {\n newNode.new_rect[i] /= viewportScale;\n }\n normalizedNodes.push(newNode);\n }\n\n const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||\n new Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>();\n cacheForModel.set(event, normalizedNodes);\n normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);\n\n return normalizedNodes;\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
1
+ {"version":3,"file":"FetchNodes.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/FetchNodes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Types from '../types/types.js';\n\nconst domLookUpSingleNodeCache =\n new Map<Handlers.Types.TraceParseData, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\nconst domLookUpBatchNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Set<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>>();\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function _TEST_clearCache(): void {\n domLookUpSingleNodeCache.clear();\n domLookUpBatchNodesCache.clear();\n layoutShiftSourcesCache.clear();\n normalizedLayoutShiftNodesCache.clear();\n}\n\n/**\n * Looks up the DOM Node on the page for the given BackendNodeId. Uses the\n * provided TraceParseData as the cache and will cache the result after the\n * first lookup.\n */\nexport async function domNodeForBackendNodeID(\n modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode|null> {\n const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);\n if (fromCache !== undefined) {\n return fromCache;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return null;\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));\n const result = domNodesMap?.get(nodeId) || null;\n\n const cacheForModel =\n domLookUpSingleNodeCache.get(modelData) || new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>();\n cacheForModel.set(nodeId, result);\n domLookUpSingleNodeCache.set(modelData, cacheForModel);\n\n return result;\n}\n\n/**\n * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.\n * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.\n */\nexport async function domNodesForMultipleBackendNodeIds(\n modelData: Handlers.Types.TraceParseData,\n nodeIds: Set<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>> {\n const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);\n if (fromCache) {\n return fromCache;\n }\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return new Map();\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIds) || new Map();\n\n const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||\n new Map<Set<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\n cacheForModel.set(nodeIds, domNodesMap);\n domLookUpBatchNodesCache.set(modelData, cacheForModel);\n\n return domNodesMap;\n}\n\nconst layoutShiftSourcesCache = new Map<\n Handlers.Types.TraceParseData, Map<Types.TraceEvents.TraceEventLayoutShift, readonly LayoutShiftSource[]>>();\n\nconst normalizedLayoutShiftNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>>();\n\nexport interface LayoutShiftSource {\n previousRect: DOMRect;\n currentRect: DOMRect;\n node: SDK.DOMModel.DOMNode;\n}\n\n/**\n * Calculates and returns a list of sources for a LayoutShift.\n * Here, a source is considered as a node that moved and contributed to the\n * given LayoutShift existing and the score it was given. Each source returned\n * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both\n * before and now, so we can see how this node changed and how that impacted the\n * layout shift.\n *\n * This data is cached based on the provided model data and the given layout\n * shift, so it is is safe to call multiple times with the same input.\n */\nexport async function sourcesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]> {\n const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n const sources: LayoutShiftSource[] = [];\n await Promise.all(impactedNodes.map(async node => {\n const domNode = await domNodeForBackendNodeID(modelData, node.node_id);\n if (domNode) {\n sources.push({\n previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),\n currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),\n node: domNode,\n });\n }\n }));\n const cacheForModel =\n layoutShiftSourcesCache.get(modelData) || new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftSource[]>();\n cacheForModel.set(event, sources);\n layoutShiftSourcesCache.set(modelData, cacheForModel);\n return sources;\n}\n\n/**\n * Takes a LayoutShift and normalizes its node dimensions based on the device\n * pixel ratio (DPR) of the user's display.\n * This is required because the Layout Instability API is not based on CSS\n * pixels, but physical pixels. Therefore we need to map these to normalized CSS\n * pixels if we can. For example, if the user is on a device with a DPR of 2,\n * the values of the node dimensions reported by the Instability API need to be\n * divided by 2 to be accurate.\n * This function is safe to call multiple times as results are cached based on\n * the provided model data.\n * See https://crbug.com/1300309 for details.\n */\nexport async function normalizedImpactedNodesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]> {\n const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args?.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n\n let viewportScale: number|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Get the CSS-to-physical pixel ratio of the device the inspected\n // target is running at.\n const evaluateResult = await target?.runtimeAgent().invoke_evaluate({expression: 'window.devicePixelRatio'});\n if (evaluateResult?.result.type === 'number') {\n viewportScale = evaluateResult?.result.value as number ?? null;\n }\n\n if (!viewportScale) {\n // Bail and return the nodes as is.\n return impactedNodes;\n }\n\n const normalizedNodes: Types.TraceEvents.TraceImpactedNode[] = [];\n for (const impactedNode of impactedNodes) {\n const newNode = {...impactedNode};\n for (let i = 0; i < impactedNode.old_rect.length; i++) {\n newNode.old_rect[i] /= viewportScale;\n }\n for (let i = 0; i < impactedNode.new_rect.length; i++) {\n newNode.new_rect[i] /= viewportScale;\n }\n normalizedNodes.push(newNode);\n }\n\n const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||\n new Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>();\n cacheForModel.set(event, normalizedNodes);\n normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);\n\n return normalizedNodes;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type * as Handlers from '../handlers/handlers.js';
2
+ import type * as Types from '../types/types.js';
3
+ export interface Data {
4
+ zeroTime: Types.Timing.MicroSeconds;
5
+ spanTime: Types.Timing.MicroSeconds;
6
+ frames: readonly Frame[];
7
+ }
8
+ export interface Frame {
9
+ screenshotEvent: Types.TraceEvents.SyntheticScreenshot;
10
+ index: number;
11
+ }
12
+ export type HandlersWithFilmStrip = Handlers.Types.HandlersWithMeta<{
13
+ Screenshots: typeof Handlers.ModelHandlers.Screenshots;
14
+ }>;
15
+ export type HandlerDataWithScreenshots = Handlers.Types.EnabledHandlerDataWithMeta<{
16
+ Screenshots: typeof Handlers.ModelHandlers.Screenshots;
17
+ }>;
18
+ export declare function fromTraceData(traceData: HandlerDataWithScreenshots, customZeroTime?: Types.Timing.MicroSeconds): Data;
19
+ export declare function frameClosestToTimestamp(filmStrip: Data, searchTimestamp: Types.Timing.MicroSeconds): Frame | null;
@@ -1,37 +1,44 @@
1
- import * as Platform from "../../../core/platform/platform.js";
2
- const filmStripCache = /* @__PURE__ */ new Map();
1
+ // Copyright 2023 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
+ //
5
+ import * as Platform from '../../../core/platform/platform.js';
6
+ // Cache film strips based on:
7
+ // 1. The trace parsed data object
8
+ // 2. The start time.
9
+ const filmStripCache = new Map();
3
10
  export function fromTraceData(traceData, customZeroTime) {
4
- const frames = [];
5
- const zeroTime = typeof customZeroTime !== "undefined" ? customZeroTime : traceData.Meta.traceBounds.min;
6
- const spanTime = traceData.Meta.traceBounds.range;
7
- const fromCache = filmStripCache.get(traceData)?.get(zeroTime);
8
- if (fromCache) {
9
- return fromCache;
10
- }
11
- for (const screenshotEvent of traceData.Screenshots) {
12
- if (screenshotEvent.ts < zeroTime) {
13
- continue;
11
+ const frames = [];
12
+ const zeroTime = typeof customZeroTime !== 'undefined' ? customZeroTime : traceData.Meta.traceBounds.min;
13
+ const spanTime = traceData.Meta.traceBounds.range;
14
+ const fromCache = filmStripCache.get(traceData)?.get(zeroTime);
15
+ if (fromCache) {
16
+ return fromCache;
14
17
  }
15
- const frame = {
16
- index: frames.length,
17
- screenshotEvent
18
+ for (const screenshotEvent of traceData.Screenshots) {
19
+ if (screenshotEvent.ts < zeroTime) {
20
+ continue;
21
+ }
22
+ const frame = {
23
+ index: frames.length,
24
+ screenshotEvent: screenshotEvent,
25
+ };
26
+ frames.push(frame);
27
+ }
28
+ const result = {
29
+ zeroTime,
30
+ spanTime,
31
+ frames: Array.from(frames),
18
32
  };
19
- frames.push(frame);
20
- }
21
- const result = {
22
- zeroTime,
23
- spanTime,
24
- frames: Array.from(frames)
25
- };
26
- const cachedForData = Platform.MapUtilities.getWithDefault(filmStripCache, traceData, () => /* @__PURE__ */ new Map());
27
- cachedForData.set(zeroTime, result);
28
- return result;
33
+ const cachedForData = Platform.MapUtilities.getWithDefault(filmStripCache, traceData, () => new Map());
34
+ cachedForData.set(zeroTime, result);
35
+ return result;
29
36
  }
30
37
  export function frameClosestToTimestamp(filmStrip, searchTimestamp) {
31
- const closestFrameIndexBeforeTimestamp = Platform.ArrayUtilities.nearestIndexFromEnd(filmStrip.frames, (frame) => frame.screenshotEvent.ts < searchTimestamp);
32
- if (closestFrameIndexBeforeTimestamp === null) {
33
- return null;
34
- }
35
- return filmStrip.frames[closestFrameIndexBeforeTimestamp];
38
+ const closestFrameIndexBeforeTimestamp = Platform.ArrayUtilities.nearestIndexFromEnd(filmStrip.frames, frame => frame.screenshotEvent.ts < searchTimestamp);
39
+ if (closestFrameIndexBeforeTimestamp === null) {
40
+ return null;
41
+ }
42
+ return filmStrip.frames[closestFrameIndexBeforeTimestamp];
36
43
  }
37
- //# sourceMappingURL=FilmStrip.js.map
44
+ //# sourceMappingURL=FilmStrip.js.map
@@ -1,7 +1 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../../../front_end/models/trace/extras/FilmStrip.ts"],
4
- "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 Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Types from '../types/types.js';\n\nexport interface Data {\n zeroTime: Types.Timing.MicroSeconds;\n spanTime: Types.Timing.MicroSeconds;\n frames: readonly Frame[];\n}\n\nexport interface Frame {\n screenshotEvent: Types.TraceEvents.SyntheticScreenshot;\n index: number;\n}\n\nexport type HandlersWithFilmStrip = Handlers.Types.HandlersWithMeta<{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Screenshots: typeof Handlers.ModelHandlers.Screenshots,\n}>;\n\nexport type HandlerDataWithScreenshots = Handlers.Types.EnabledHandlerDataWithMeta<{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Screenshots: typeof Handlers.ModelHandlers.Screenshots,\n}>;\n\n// Cache film strips based on:\n// 1. The trace parsed data object\n// 2. The start time.\nconst filmStripCache = new Map<HandlerDataWithScreenshots, Map<Types.Timing.MicroSeconds, Data>>();\n\nexport function fromTraceData(traceData: HandlerDataWithScreenshots, customZeroTime?: Types.Timing.MicroSeconds): Data {\n const frames: Frame[] = [];\n\n const zeroTime = typeof customZeroTime !== 'undefined' ? customZeroTime : traceData.Meta.traceBounds.min;\n const spanTime = traceData.Meta.traceBounds.range;\n const fromCache = filmStripCache.get(traceData)?.get(zeroTime);\n if (fromCache) {\n return fromCache;\n }\n\n for (const screenshotEvent of traceData.Screenshots) {\n if (screenshotEvent.ts < zeroTime) {\n continue;\n }\n const frame: Frame = {\n index: frames.length,\n screenshotEvent: screenshotEvent,\n };\n frames.push(frame);\n }\n\n const result: Data = {\n zeroTime,\n spanTime,\n frames: Array.from(frames),\n };\n\n const cachedForData =\n Platform.MapUtilities.getWithDefault(filmStripCache, traceData, () => new Map<Types.Timing.MicroSeconds, Data>());\n cachedForData.set(zeroTime, result);\n\n return result;\n}\n\nexport function frameClosestToTimestamp(filmStrip: Data, searchTimestamp: Types.Timing.MicroSeconds): Frame|null {\n const closestFrameIndexBeforeTimestamp = Platform.ArrayUtilities.nearestIndexFromEnd(\n filmStrip.frames, frame => frame.screenshotEvent.ts < searchTimestamp);\n if (closestFrameIndexBeforeTimestamp === null) {\n return null;\n }\n return filmStrip.frames[closestFrameIndexBeforeTimestamp];\n}\n"],
5
- "mappings": "AAIA;AA4BA,MAAM,iBAAiB,oBAAI;AAEpB,8BAAuB,WAAuC,gBAAkD;AACrH,QAAM,SAAkB;AAExB,QAAM,WAAW,OAAO,mBAAmB,cAAc,iBAAiB,UAAU,KAAK,YAAY;AACrG,QAAM,WAAW,UAAU,KAAK,YAAY;AAC5C,QAAM,YAAY,eAAe,IAAI,YAAY,IAAI;AACrD,MAAI,WAAW;AACb,WAAO;AAAA;AAGT,aAAW,mBAAmB,UAAU,aAAa;AACnD,QAAI,gBAAgB,KAAK,UAAU;AACjC;AAAA;AAEF,UAAM,QAAe;AAAA,MACnB,OAAO,OAAO;AAAA,MACd;AAAA;AAEF,WAAO,KAAK;AAAA;AAGd,QAAM,SAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA,QAAQ,MAAM,KAAK;AAAA;AAGrB,QAAM,gBACF,SAAS,aAAa,eAAe,gBAAgB,WAAW,MAAM,oBAAI;AAC9E,gBAAc,IAAI,UAAU;AAE5B,SAAO;AAAA;AAGF,wCAAiC,WAAiB,iBAAwD;AAC/G,QAAM,mCAAmC,SAAS,eAAe,oBAC7D,UAAU,QAAQ,WAAS,MAAM,gBAAgB,KAAK;AAC1D,MAAI,qCAAqC,MAAM;AAC7C,WAAO;AAAA;AAET,SAAO,UAAU,OAAO;AAAA;",
6
- "names": []
7
- }
1
+ {"version":3,"file":"FilmStrip.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/FilmStrip.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,EAAE;AACF,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAyB/D,8BAA8B;AAC9B,kCAAkC;AAClC,qBAAqB;AACrB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAoE,CAAC;AAEnG,MAAM,UAAU,aAAa,CAAC,SAAqC,EAAE,cAA0C;IAC7G,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,MAAM,QAAQ,GAAG,OAAO,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;IACzG,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;IAClD,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/D,IAAI,SAAS,EAAE;QACb,OAAO,SAAS,CAAC;KAClB;IAED,KAAK,MAAM,eAAe,IAAI,SAAS,CAAC,WAAW,EAAE;QACnD,IAAI,eAAe,CAAC,EAAE,GAAG,QAAQ,EAAE;YACjC,SAAS;SACV;QACD,MAAM,KAAK,GAAU;YACnB,KAAK,EAAE,MAAM,CAAC,MAAM;YACpB,eAAe,EAAE,eAAe;SACjC,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACpB;IAED,MAAM,MAAM,GAAS;QACnB,QAAQ;QACR,QAAQ;QACR,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;KAC3B,CAAC;IAEF,MAAM,aAAa,GACf,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,cAAc,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAmC,CAAC,CAAC;IACtH,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,SAAe,EAAE,eAA0C;IACjG,MAAM,gCAAgC,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAChF,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC;IAC3E,IAAI,gCAAgC,KAAK,IAAI,EAAE;QAC7C,OAAO,IAAI,CAAC;KACb;IACD,OAAO,SAAS,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAC5D,CAAC","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 Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Types from '../types/types.js';\n\nexport interface Data {\n zeroTime: Types.Timing.MicroSeconds;\n spanTime: Types.Timing.MicroSeconds;\n frames: readonly Frame[];\n}\n\nexport interface Frame {\n screenshotEvent: Types.TraceEvents.SyntheticScreenshot;\n index: number;\n}\n\nexport type HandlersWithFilmStrip = Handlers.Types.HandlersWithMeta<{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Screenshots: typeof Handlers.ModelHandlers.Screenshots,\n}>;\n\nexport type HandlerDataWithScreenshots = Handlers.Types.EnabledHandlerDataWithMeta<{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Screenshots: typeof Handlers.ModelHandlers.Screenshots,\n}>;\n\n// Cache film strips based on:\n// 1. The trace parsed data object\n// 2. The start time.\nconst filmStripCache = new Map<HandlerDataWithScreenshots, Map<Types.Timing.MicroSeconds, Data>>();\n\nexport function fromTraceData(traceData: HandlerDataWithScreenshots, customZeroTime?: Types.Timing.MicroSeconds): Data {\n const frames: Frame[] = [];\n\n const zeroTime = typeof customZeroTime !== 'undefined' ? customZeroTime : traceData.Meta.traceBounds.min;\n const spanTime = traceData.Meta.traceBounds.range;\n const fromCache = filmStripCache.get(traceData)?.get(zeroTime);\n if (fromCache) {\n return fromCache;\n }\n\n for (const screenshotEvent of traceData.Screenshots) {\n if (screenshotEvent.ts < zeroTime) {\n continue;\n }\n const frame: Frame = {\n index: frames.length,\n screenshotEvent: screenshotEvent,\n };\n frames.push(frame);\n }\n\n const result: Data = {\n zeroTime,\n spanTime,\n frames: Array.from(frames),\n };\n\n const cachedForData =\n Platform.MapUtilities.getWithDefault(filmStripCache, traceData, () => new Map<Types.Timing.MicroSeconds, Data>());\n cachedForData.set(zeroTime, result);\n\n return result;\n}\n\nexport function frameClosestToTimestamp(filmStrip: Data, searchTimestamp: Types.Timing.MicroSeconds): Frame|null {\n const closestFrameIndexBeforeTimestamp = Platform.ArrayUtilities.nearestIndexFromEnd(\n filmStrip.frames, frame => frame.screenshotEvent.ts < searchTimestamp);\n if (closestFrameIndexBeforeTimestamp === null) {\n return null;\n }\n return filmStrip.frames[closestFrameIndexBeforeTimestamp];\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import * as Types from '../types/types.js';
2
+ export declare function calculateWindow(traceBounds: Types.Timing.TraceWindowMicroSeconds, mainThreadEntries: readonly Types.TraceEvents.SyntheticTraceEntry[]): Types.Timing.TraceWindowMicroSeconds;
@@ -1,61 +1,77 @@
1
- import * as Helpers from "../helpers/helpers.js";
2
- import * as Types from "../types/types.js";
3
- const IDLE_FUNCTION_CALL_NAMES = /* @__PURE__ */ new Set([
4
- "(program)",
5
- "(idle)",
6
- "(root)"
1
+ // Copyright 2023 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 Helpers from '../helpers/helpers.js';
5
+ import * as Types from '../types/types.js';
6
+ const IDLE_FUNCTION_CALL_NAMES = new Set([
7
+ '(program)',
8
+ '(idle)',
9
+ '(root)',
7
10
  ]);
8
11
  export function calculateWindow(traceBounds, mainThreadEntries) {
9
- if (!mainThreadEntries.length) {
10
- return traceBounds;
11
- }
12
- const entriesWithIdleRemoved = mainThreadEntries.filter((entry) => {
13
- if (Types.TraceEvents.isProfileCall(entry) && (IDLE_FUNCTION_CALL_NAMES.has(entry.callFrame.functionName) || !entry.callFrame.functionName)) {
14
- return false;
12
+ if (!mainThreadEntries.length) {
13
+ return traceBounds;
15
14
  }
16
- return true;
17
- });
18
- if (entriesWithIdleRemoved.length === 0) {
19
- return traceBounds;
20
- }
21
- function findLowUtilizationRegion(startIndex, stopIndex) {
22
- const threshold = 0.1;
23
- let cutIndex = startIndex;
24
- const entryAtCut = entriesWithIdleRemoved[cutIndex];
25
- const timings = Helpers.Timing.eventTimingsMicroSeconds(entryAtCut);
26
- let cutTime = (timings.startTime + timings.endTime) / 2;
27
- let usedTime = 0;
28
- const step = Math.sign(stopIndex - startIndex);
29
- for (let i = startIndex; i !== stopIndex; i += step) {
30
- const task = entriesWithIdleRemoved[i];
31
- const taskTimings = Helpers.Timing.eventTimingsMicroSeconds(task);
32
- const taskTime = (taskTimings.startTime + taskTimings.endTime) / 2;
33
- const interval = Math.abs(cutTime - taskTime);
34
- if (usedTime < threshold * interval) {
35
- cutIndex = i;
36
- cutTime = taskTime;
37
- usedTime = 0;
38
- }
39
- usedTime += taskTimings.duration;
15
+ const entriesWithIdleRemoved = mainThreadEntries.filter(entry => {
16
+ if (Types.TraceEvents.isProfileCall(entry) &&
17
+ (IDLE_FUNCTION_CALL_NAMES.has(entry.callFrame.functionName) || !entry.callFrame.functionName)) {
18
+ return false;
19
+ }
20
+ return true;
21
+ });
22
+ if (entriesWithIdleRemoved.length === 0) {
23
+ return traceBounds;
40
24
  }
41
- return cutIndex;
42
- }
43
- const rightIndex = findLowUtilizationRegion(entriesWithIdleRemoved.length - 1, 0);
44
- const leftIndex = findLowUtilizationRegion(0, rightIndex);
45
- const leftTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[leftIndex]);
46
- const rightTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[rightIndex]);
47
- let leftTime = leftTimings.startTime;
48
- let rightTime = rightTimings.endTime;
49
- const zoomedInSpan = rightTime - leftTime;
50
- if (zoomedInSpan < traceBounds.range * 0.1) {
51
- return traceBounds;
52
- }
53
- leftTime = Types.Timing.MicroSeconds(Math.max(leftTime - 0.05 * zoomedInSpan, traceBounds.min));
54
- rightTime = Types.Timing.MicroSeconds(Math.min(rightTime + 0.05 * zoomedInSpan, traceBounds.max));
55
- return {
56
- min: leftTime,
57
- max: rightTime,
58
- range: Types.Timing.MicroSeconds(rightTime - leftTime)
59
- };
25
+ /**
26
+ * Calculates regions of low utilization and returns the index of the event
27
+ * that is the first event that should be included.
28
+ **/
29
+ function findLowUtilizationRegion(startIndex, stopIndex) {
30
+ const threshold = 0.1;
31
+ let cutIndex = startIndex;
32
+ const entryAtCut = entriesWithIdleRemoved[cutIndex];
33
+ const timings = Helpers.Timing.eventTimingsMicroSeconds(entryAtCut);
34
+ let cutTime = (timings.startTime + timings.endTime) / 2;
35
+ let usedTime = 0;
36
+ const step = Math.sign(stopIndex - startIndex);
37
+ for (let i = startIndex; i !== stopIndex; i += step) {
38
+ const task = entriesWithIdleRemoved[i];
39
+ const taskTimings = Helpers.Timing.eventTimingsMicroSeconds(task);
40
+ const taskTime = (taskTimings.startTime + taskTimings.endTime) / 2;
41
+ const interval = Math.abs(cutTime - taskTime);
42
+ if (usedTime < threshold * interval) {
43
+ cutIndex = i;
44
+ cutTime = taskTime;
45
+ usedTime = 0;
46
+ }
47
+ usedTime += taskTimings.duration;
48
+ }
49
+ return cutIndex;
50
+ }
51
+ const rightIndex = findLowUtilizationRegion(entriesWithIdleRemoved.length - 1, 0);
52
+ const leftIndex = findLowUtilizationRegion(0, rightIndex);
53
+ const leftTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[leftIndex]);
54
+ const rightTimings = Helpers.Timing.eventTimingsMicroSeconds(entriesWithIdleRemoved[rightIndex]);
55
+ let leftTime = leftTimings.startTime;
56
+ let rightTime = rightTimings.endTime;
57
+ const zoomedInSpan = rightTime - leftTime;
58
+ if (zoomedInSpan < traceBounds.range * 0.1) {
59
+ // If the area we have chosen to zoom into is less than 10% of the entire
60
+ // span, we bail and show the entire trace. It would not be so useful to
61
+ // the user to zoom in on such a small area; we assume they have
62
+ // purposefully recorded a trace that contains empty periods of time.
63
+ return traceBounds;
64
+ }
65
+ // Adjust the left time down by 5%, and the right time up by 5%, so that
66
+ // we give the range we want to zoom a bit of breathing space. At the
67
+ // same time, ensure that we do not stray beyond the bounds of the
68
+ // min/max time of the entire trace.
69
+ leftTime = Types.Timing.MicroSeconds(Math.max(leftTime - 0.05 * zoomedInSpan, traceBounds.min));
70
+ rightTime = Types.Timing.MicroSeconds(Math.min(rightTime + 0.05 * zoomedInSpan, traceBounds.max));
71
+ return {
72
+ min: leftTime,
73
+ max: rightTime,
74
+ range: Types.Timing.MicroSeconds(rightTime - leftTime),
75
+ };
60
76
  }
61
- //# sourceMappingURL=MainThreadActivity.js.map
77
+ //# sourceMappingURL=MainThreadActivity.js.map