@paulirish/trace_engine 0.0.9 → 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 (292) hide show
  1. package/analyze-trace.mjs +1 -1
  2. package/core/platform/DevToolsPath.d.ts +23 -0
  3. package/core/platform/DevToolsPath.js +7 -0
  4. package/core/platform/DevToolsPath.js.map +1 -0
  5. package/core/platform/MimeType.d.ts +27 -0
  6. package/core/platform/MimeType.js +137 -0
  7. package/core/platform/MimeType.js.map +1 -0
  8. package/core/platform/Timing.d.ts +7 -0
  9. package/core/platform/Timing.js +13 -0
  10. package/core/platform/Timing.js.map +1 -0
  11. package/core/platform/UIString.d.ts +3 -0
  12. package/core/platform/UIString.js +5 -0
  13. package/core/platform/UIString.js.map +1 -0
  14. package/core/platform/UserVisibleError.d.ts +12 -0
  15. package/core/platform/UserVisibleError.js +23 -0
  16. package/core/platform/UserVisibleError.js.map +1 -0
  17. package/core/platform/array-utilities.d.ts +66 -0
  18. package/core/platform/array-utilities.js +199 -0
  19. package/core/platform/array-utilities.js.map +1 -0
  20. package/core/platform/brand.d.ts +14 -0
  21. package/core/platform/brand.js +5 -0
  22. package/core/platform/brand.js.map +1 -0
  23. package/core/platform/bundle-tsconfig.json +1 -0
  24. package/core/platform/date-utilities.d.ts +2 -0
  25. package/core/platform/date-utilities.js +14 -0
  26. package/core/platform/date-utilities.js.map +1 -0
  27. package/core/platform/dcheck-tsconfig.json +8 -0
  28. package/core/platform/dcheck.d.ts +4 -0
  29. package/core/platform/dcheck.js +5 -0
  30. package/core/platform/devtools_entrypoint-bundle-tsconfig-tsconfig.json +40 -0
  31. package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  32. package/core/platform/dom-utilities.d.ts +8 -0
  33. package/core/platform/dom-utilities.js +109 -0
  34. package/core/platform/dom-utilities.js.map +1 -0
  35. package/core/platform/keyboard-utilities.d.ts +17 -0
  36. package/core/platform/keyboard-utilities.js +22 -0
  37. package/core/platform/keyboard-utilities.js.map +1 -0
  38. package/core/platform/map-utilities.d.ts +18 -0
  39. package/core/platform/map-utilities.js +76 -0
  40. package/core/platform/map-utilities.js.map +1 -0
  41. package/core/platform/number-utilities.d.ts +15 -0
  42. package/core/platform/number-utilities.js +82 -0
  43. package/core/platform/number-utilities.js.map +1 -0
  44. package/core/platform/platform-tsconfig.json +59 -0
  45. package/core/platform/platform.d.ts +19 -0
  46. package/core/platform/platform.js +54 -0
  47. package/core/platform/platform.js.compressed +0 -0
  48. package/core/platform/platform.js.hash +1 -0
  49. package/core/platform/platform.js.map +1 -0
  50. package/core/platform/platform.prebundle.d.ts +15 -0
  51. package/core/platform/platform.prebundle.js +50 -0
  52. package/core/platform/platform.prebundle.js.map +1 -0
  53. package/core/platform/platform.prebundle.ts +64 -0
  54. package/core/platform/promise-utilities.d.ts +10 -0
  55. package/core/platform/promise-utilities.js +18 -0
  56. package/core/platform/promise-utilities.js.map +1 -0
  57. package/core/platform/set-utilities.d.ts +2 -0
  58. package/core/platform/set-utilities.js +23 -0
  59. package/core/platform/set-utilities.js.map +1 -0
  60. package/core/platform/string-utilities.d.ts +71 -0
  61. package/core/platform/string-utilities.js +513 -0
  62. package/core/platform/string-utilities.js.map +1 -0
  63. package/core/platform/typescript-utilities.d.ts +56 -0
  64. package/core/platform/typescript-utilities.js +25 -0
  65. package/core/platform/typescript-utilities.js.map +1 -0
  66. package/generated/protocol.d.ts +17923 -0
  67. package/generated/protocol.js +5 -0
  68. package/models/cpu_profile/CPUProfileDataModel.d.ts +77 -0
  69. package/models/cpu_profile/CPUProfileDataModel.js +508 -0
  70. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -0
  71. package/models/cpu_profile/ProfileTreeModel.d.ts +29 -0
  72. package/models/cpu_profile/ProfileTreeModel.js +95 -0
  73. package/models/cpu_profile/ProfileTreeModel.js.map +1 -0
  74. package/models/cpu_profile/bundle-tsconfig.json +1 -0
  75. package/models/cpu_profile/cpu_profile-tsconfig.json +51 -0
  76. package/models/cpu_profile/cpu_profile.d.ts +3 -0
  77. package/models/cpu_profile/cpu_profile.js +7 -0
  78. package/models/cpu_profile/cpu_profile.js.map +1 -0
  79. package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  80. package/models/trace/EntriesFilter.d.ts +55 -0
  81. package/models/trace/EntriesFilter.js +243 -0
  82. package/models/trace/EntriesFilter.js.map +1 -0
  83. package/models/trace/LegacyTracingModel.d.ts +1 -0
  84. package/models/trace/LegacyTracingModel.js +1 -0
  85. package/models/trace/LegacyTracingModel.js.map +1 -0
  86. package/models/trace/ModelImpl.d.ts +110 -0
  87. package/models/trace/ModelImpl.js +175 -0
  88. package/models/trace/ModelImpl.js.map +1 -0
  89. package/models/trace/Processor.d.ts +36 -0
  90. package/models/trace/Processor.js +213 -0
  91. package/models/trace/Processor.js.map +1 -0
  92. package/models/trace/SDKServices.js +104 -0
  93. package/models/trace/SDKServices.js.map +7 -0
  94. package/models/trace/TraceProcessor.js +133 -0
  95. package/models/trace/TraceProcessor.js.map +7 -0
  96. package/models/trace/TracingManager.d.ts +1 -0
  97. package/models/trace/TracingManager.js +1 -0
  98. package/models/trace/TracingManager.js.map +1 -0
  99. package/models/trace/TreeManipulator.js +85 -0
  100. package/models/trace/TreeManipulator.js.map +7 -0
  101. package/models/trace/bundle-tsconfig.json +1 -0
  102. package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  103. package/models/trace/devtools_entrypoint-legacy-typescript-tsconfig.json +43 -0
  104. package/models/trace/extras/FetchNodes.d.ts +46 -0
  105. package/models/trace/extras/FetchNodes.js +145 -0
  106. package/models/trace/extras/FetchNodes.js.map +1 -0
  107. package/models/trace/extras/FilmStrip.d.ts +19 -0
  108. package/models/trace/extras/FilmStrip.js +44 -0
  109. package/models/trace/extras/FilmStrip.js.map +1 -0
  110. package/models/trace/extras/MainThreadActivity.d.ts +2 -0
  111. package/models/trace/extras/MainThreadActivity.js +77 -0
  112. package/models/trace/extras/MainThreadActivity.js.map +1 -0
  113. package/models/trace/extras/Metadata.d.ts +2 -0
  114. package/models/trace/extras/Metadata.js +44 -0
  115. package/models/trace/extras/Metadata.js.map +1 -0
  116. package/models/trace/extras/bundle-tsconfig.json +1 -0
  117. package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  118. package/models/trace/extras/extras-tsconfig.json +59 -0
  119. package/models/trace/extras/extras.d.ts +1 -0
  120. package/models/trace/extras/extras.js +1 -0
  121. package/models/trace/extras/extras.js.map +1 -0
  122. package/models/trace/frames/TimelineFrameModel.js +392 -0
  123. package/models/trace/frames/TimelineFrameModel.js.map +7 -0
  124. package/models/trace/frames/bundle-tsconfig.json +1 -0
  125. package/models/trace/frames/devtools_entrypoint-bundle-typescript-tsconfig.json +43 -0
  126. package/models/trace/frames/frames-tsconfig.json +58 -0
  127. package/models/trace/frames/frames.js +5 -0
  128. package/models/trace/frames/frames.js.map +7 -0
  129. package/models/trace/handlers/AnimationHandler.d.ts +8 -0
  130. package/models/trace/handlers/AnimationHandler.js +32 -0
  131. package/models/trace/handlers/AnimationHandler.js.map +1 -0
  132. package/models/trace/handlers/AuctionWorkletsHandler.d.ts +8 -0
  133. package/models/trace/handlers/AuctionWorkletsHandler.js +160 -0
  134. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -0
  135. package/models/trace/handlers/FramesHandler.d.ts +76 -0
  136. package/models/trace/handlers/FramesHandler.js +457 -0
  137. package/models/trace/handlers/FramesHandler.js.map +1 -0
  138. package/models/trace/handlers/GPUHandler.d.ts +11 -0
  139. package/models/trace/handlers/GPUHandler.js +54 -0
  140. package/models/trace/handlers/GPUHandler.js.map +1 -0
  141. package/models/trace/handlers/InitiatorsHandler.d.ts +10 -0
  142. package/models/trace/handlers/InitiatorsHandler.js +184 -0
  143. package/models/trace/handlers/InitiatorsHandler.js.map +1 -0
  144. package/models/trace/handlers/InvalidationsHandler.d.ts +10 -0
  145. package/models/trace/handlers/InvalidationsHandler.js +120 -0
  146. package/models/trace/handlers/InvalidationsHandler.js.map +1 -0
  147. package/models/trace/handlers/LargestImagePaintHandler.d.ts +5 -0
  148. package/models/trace/handlers/LargestImagePaintHandler.js +38 -0
  149. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -0
  150. package/models/trace/handlers/LargestTextPaintHandler.d.ts +5 -0
  151. package/models/trace/handlers/LargestTextPaintHandler.js +26 -0
  152. package/models/trace/handlers/LargestTextPaintHandler.js.map +1 -0
  153. package/models/trace/handlers/LayerTreeHandler.d.ts +13 -0
  154. package/models/trace/handlers/LayerTreeHandler.js +116 -0
  155. package/models/trace/handlers/LayerTreeHandler.js.map +1 -0
  156. package/models/trace/handlers/LayoutShiftsHandler.d.ts +44 -0
  157. package/models/trace/handlers/LayoutShiftsHandler.js +347 -0
  158. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -0
  159. package/models/trace/handlers/MemoryHandler.d.ts +7 -0
  160. package/models/trace/handlers/MemoryHandler.js +20 -0
  161. package/models/trace/handlers/MemoryHandler.js.map +1 -0
  162. package/models/trace/handlers/MetaHandler.d.ts +37 -0
  163. package/models/trace/handlers/MetaHandler.js +338 -0
  164. package/models/trace/handlers/MetaHandler.js.map +1 -0
  165. package/models/trace/handlers/Migration.js +27 -0
  166. package/models/trace/handlers/Migration.js.map +7 -0
  167. package/models/trace/handlers/ModelHandlers.d.ts +21 -0
  168. package/models/trace/handlers/ModelHandlers.js +25 -0
  169. package/models/trace/handlers/ModelHandlers.js.map +1 -0
  170. package/models/trace/handlers/NetworkRequestsHandler.d.ts +17 -0
  171. package/models/trace/handlers/NetworkRequestsHandler.js +361 -0
  172. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -0
  173. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +67 -0
  174. package/models/trace/handlers/PageLoadMetricsHandler.js +407 -0
  175. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -0
  176. package/models/trace/handlers/RendererHandler.d.ts +101 -0
  177. package/models/trace/handlers/RendererHandler.js +325 -0
  178. package/models/trace/handlers/RendererHandler.js.map +1 -0
  179. package/models/trace/handlers/SamplesHandler.d.ts +46 -0
  180. package/models/trace/handlers/SamplesHandler.js +215 -0
  181. package/models/trace/handlers/SamplesHandler.js.map +1 -0
  182. package/models/trace/handlers/ScreenshotsHandler.d.ts +7 -0
  183. package/models/trace/handlers/ScreenshotsHandler.js +79 -0
  184. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -0
  185. package/models/trace/handlers/Threads.d.ts +33 -0
  186. package/models/trace/handlers/Threads.js +95 -0
  187. package/models/trace/handlers/Threads.js.map +1 -0
  188. package/models/trace/handlers/UberFramesHandler.js +293 -0
  189. package/models/trace/handlers/UberFramesHandler.js.map +7 -0
  190. package/models/trace/handlers/UserInteractionsHandler.d.ts +57 -0
  191. package/models/trace/handlers/UserInteractionsHandler.js +267 -0
  192. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -0
  193. package/models/trace/handlers/UserTimingsHandler.d.ts +28 -0
  194. package/models/trace/handlers/UserTimingsHandler.js +108 -0
  195. package/models/trace/handlers/UserTimingsHandler.js.map +1 -0
  196. package/models/trace/handlers/WarningsHandler.d.ts +14 -0
  197. package/models/trace/handlers/WarningsHandler.js +125 -0
  198. package/models/trace/handlers/WarningsHandler.js.map +1 -0
  199. package/models/trace/handlers/WorkersHandler.d.ts +11 -0
  200. package/models/trace/handlers/WorkersHandler.js +52 -0
  201. package/models/trace/handlers/WorkersHandler.js.map +1 -0
  202. package/models/trace/handlers/bundle-tsconfig.json +1 -0
  203. package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  204. package/models/trace/handlers/handlers-tsconfig.json +79 -0
  205. package/models/trace/handlers/handlers.d.ts +3 -0
  206. package/models/trace/handlers/handlers.js +7 -0
  207. package/models/trace/handlers/handlers.js.map +1 -0
  208. package/models/trace/handlers/types.d.ts +45 -0
  209. package/models/trace/handlers/types.js +18 -0
  210. package/models/trace/handlers/types.js.map +1 -0
  211. package/models/trace/helpers/SamplesIntegrator.d.ts +49 -0
  212. package/models/trace/helpers/SamplesIntegrator.js +397 -0
  213. package/models/trace/helpers/SamplesIntegrator.js.map +1 -0
  214. package/models/trace/helpers/Timing.d.ts +26 -0
  215. package/models/trace/helpers/Timing.js +162 -0
  216. package/models/trace/helpers/Timing.js.map +1 -0
  217. package/models/trace/helpers/Trace.d.ts +37 -0
  218. package/models/trace/helpers/Trace.js +230 -0
  219. package/models/trace/helpers/Trace.js.map +1 -0
  220. package/models/trace/helpers/TreeHelpers.d.ts +90 -0
  221. package/models/trace/helpers/TreeHelpers.js +222 -0
  222. package/models/trace/helpers/TreeHelpers.js.map +1 -0
  223. package/models/trace/helpers/bundle-tsconfig.json +1 -0
  224. package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  225. package/models/trace/helpers/helpers-tsconfig.json +59 -0
  226. package/models/trace/helpers/helpers.d.ts +4 -0
  227. package/models/trace/helpers/helpers.js +8 -0
  228. package/models/trace/helpers/helpers.js.map +1 -0
  229. package/models/trace/legacy-tsconfig.json +1 -0
  230. package/models/trace/root-causes/LayoutShift.d.ts +119 -0
  231. package/models/trace/root-causes/LayoutShift.js +517 -0
  232. package/models/trace/root-causes/LayoutShift.js.map +1 -0
  233. package/models/trace/root-causes/RootCauses.d.ts +14 -0
  234. package/models/trace/root-causes/RootCauses.js +11 -0
  235. package/models/trace/root-causes/RootCauses.js.map +1 -0
  236. package/models/trace/root-causes/bundle-tsconfig.json +1 -0
  237. package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  238. package/models/trace/root-causes/root-causes-tsconfig.json +57 -0
  239. package/models/trace/root-causes/root-causes.d.ts +1 -0
  240. package/models/trace/root-causes/root-causes.js +5 -0
  241. package/models/trace/root-causes/root-causes.js.map +1 -0
  242. package/models/trace/sdk_services/DOMNodeLookup.js +41 -0
  243. package/models/trace/sdk_services/DOMNodeLookup.js.map +7 -0
  244. package/models/trace/sdk_services/LayoutShifts.js +68 -0
  245. package/models/trace/sdk_services/LayoutShifts.js.map +7 -0
  246. package/models/trace/sdk_services/bundle-tsconfig.json +1 -0
  247. package/models/trace/sdk_services/devtools_entrypoint-bundle-typescript-tsconfig.json +41 -0
  248. package/models/trace/sdk_services/sdk_services-tsconfig.json +57 -0
  249. package/models/trace/sdk_services/sdk_services.js +7 -0
  250. package/models/trace/sdk_services/sdk_services.js.map +7 -0
  251. package/models/trace/trace-legacy.js +16 -0
  252. package/models/trace/trace-legacy.js.map +7 -0
  253. package/models/trace/trace-tsconfig.json +69 -0
  254. package/models/trace/trace.d.ts +11 -0
  255. package/models/trace/trace.js +17 -0
  256. package/models/trace/trace.js.map +1 -0
  257. package/models/trace/types/Configuration.d.ts +33 -0
  258. package/models/trace/types/Configuration.js +29 -0
  259. package/models/trace/types/Configuration.js.map +1 -0
  260. package/models/trace/types/File.d.ts +23 -0
  261. package/models/trace/types/File.js +5 -0
  262. package/models/trace/types/File.js.map +1 -0
  263. package/models/trace/types/Timing.d.ts +25 -0
  264. package/models/trace/types/Timing.js +16 -0
  265. package/models/trace/types/Timing.js.map +1 -0
  266. package/models/trace/types/TraceEvents.d.ts +1571 -0
  267. package/models/trace/types/TraceEvents.js +388 -0
  268. package/models/trace/types/TraceEvents.js.map +1 -0
  269. package/models/trace/types/bundle-tsconfig.json +1 -0
  270. package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +44 -0
  271. package/models/trace/types/types-tsconfig.json +47 -0
  272. package/models/trace/types/types.d.ts +4 -0
  273. package/models/trace/types/types.js +8 -0
  274. package/models/trace/types/types.js.map +1 -0
  275. package/models/trace/worker/Processor.js +143 -0
  276. package/models/trace/worker/Processor.js.map +7 -0
  277. package/models/trace/worker/Types.js +1 -0
  278. package/models/trace/worker/Types.js.map +7 -0
  279. package/models/trace/worker/bundle-tsconfig.json +1 -0
  280. package/models/trace/worker/devtools_entrypoint-bundle-typescript-tsconfig.json +41 -0
  281. package/models/trace/worker/devtools_entrypoint-worker_entrypoint-typescript-tsconfig.json +41 -0
  282. package/models/trace/worker/processor-tsconfig.json +45 -0
  283. package/models/trace/worker/worker.js +7 -0
  284. package/models/trace/worker/worker.js.map +7 -0
  285. package/models/trace/worker/worker_entrypoint-tsconfig.json +1 -0
  286. package/models/trace/worker/worker_entrypoint.js +36 -0
  287. package/models/trace/worker/worker_entrypoint.js.map +7 -0
  288. package/package.json +2 -2
  289. package/TracingManager.js +0 -0
  290. package/extras/extras.js +0 -0
  291. package/trace.mjs +0 -6980
  292. package/trace.mjs.map +0 -8
@@ -0,0 +1,213 @@
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 Handlers from './handlers/handlers.js';
5
+ import * as Types from './types/types.js';
6
+ export class TraceParseProgressEvent extends Event {
7
+ data;
8
+ static eventName = 'traceparseprogress';
9
+ constructor(data, init = { bubbles: true }) {
10
+ super(TraceParseProgressEvent.eventName, init);
11
+ this.data = data;
12
+ }
13
+ }
14
+ export class TraceProcessor extends EventTarget {
15
+ // We force the Meta handler to be enabled, so the TraceHandlers type here is
16
+ // the model handlers the user passes in and the Meta handler.
17
+ // eslint-disable-next-line @typescript-eslint/naming-convention
18
+ #traceHandlers;
19
+ #status = "IDLE" /* Status.IDLE */;
20
+ #modelConfiguration = Types.Configuration.DEFAULT;
21
+ static createWithAllHandlers() {
22
+ return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.DEFAULT);
23
+ }
24
+ constructor(traceHandlers, modelConfiguration) {
25
+ super();
26
+ this.#verifyHandlers(traceHandlers);
27
+ this.#traceHandlers = {
28
+ Meta: Handlers.ModelHandlers.Meta,
29
+ ...traceHandlers,
30
+ };
31
+ if (modelConfiguration) {
32
+ this.#modelConfiguration = modelConfiguration;
33
+ }
34
+ this.#passConfigToHandlers();
35
+ }
36
+ updateConfiguration(config) {
37
+ this.#modelConfiguration = config;
38
+ this.#passConfigToHandlers();
39
+ }
40
+ #passConfigToHandlers() {
41
+ for (const handler of Object.values(this.#traceHandlers)) {
42
+ // Bit of an odd double check, but without this TypeScript refuses to let
43
+ // you call the function as it thinks it might be undefined.
44
+ if ('handleUserConfig' in handler && handler.handleUserConfig) {
45
+ handler.handleUserConfig(this.#modelConfiguration);
46
+ }
47
+ }
48
+ }
49
+ /**
50
+ * When the user passes in a set of handlers, we want to ensure that we have all
51
+ * the required handlers. Handlers can depend on other handlers, so if the user
52
+ * passes in FooHandler which depends on BarHandler, they must also pass in
53
+ * BarHandler too. This method verifies that all dependencies are met, and
54
+ * throws if not.
55
+ **/
56
+ #verifyHandlers(providedHandlers) {
57
+ // Tiny optimisation: if the amount of provided handlers matches the amount
58
+ // of handlers in the Handlers.ModelHandlers object, that means that the
59
+ // user has passed in every handler we have. So therefore they cannot have
60
+ // missed any, and there is no need to iterate through the handlers and
61
+ // check the dependencies.
62
+ if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {
63
+ return;
64
+ }
65
+ const requiredHandlerKeys = new Set();
66
+ for (const [handlerName, handler] of Object.entries(providedHandlers)) {
67
+ requiredHandlerKeys.add(handlerName);
68
+ for (const depName of (handler.deps?.() || [])) {
69
+ requiredHandlerKeys.add(depName);
70
+ }
71
+ }
72
+ const providedHandlerKeys = new Set(Object.keys(providedHandlers));
73
+ // We always force the Meta handler to be enabled when creating the
74
+ // Processor, so if it is missing from the set the user gave us that is OK,
75
+ // as we will have enabled it anyway.
76
+ requiredHandlerKeys.delete('Meta');
77
+ for (const requiredKey of requiredHandlerKeys) {
78
+ if (!providedHandlerKeys.has(requiredKey)) {
79
+ throw new Error(`Required handler ${requiredKey} not provided.`);
80
+ }
81
+ }
82
+ }
83
+ reset() {
84
+ if (this.#status === "PARSING" /* Status.PARSING */) {
85
+ throw new Error('Trace processor can\'t reset while parsing.');
86
+ }
87
+ const handlers = Object.values(this.#traceHandlers);
88
+ for (const handler of handlers) {
89
+ handler.reset();
90
+ }
91
+ this.#status = "IDLE" /* Status.IDLE */;
92
+ }
93
+ async parse(traceEvents, freshRecording = false) {
94
+ if (this.#status !== "IDLE" /* Status.IDLE */) {
95
+ throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);
96
+ }
97
+ try {
98
+ this.#status = "PARSING" /* Status.PARSING */;
99
+ await this.#parse(traceEvents, freshRecording);
100
+ this.#status = "FINISHED_PARSING" /* Status.FINISHED_PARSING */;
101
+ }
102
+ catch (e) {
103
+ this.#status = "ERRORED_WHILE_PARSING" /* Status.ERRORED_WHILE_PARSING */;
104
+ throw e;
105
+ }
106
+ }
107
+ async #parse(traceEvents, freshRecording) {
108
+ // This iterator steps through all events, periodically yielding back to the
109
+ // main thread to avoid blocking execution. It uses `dispatchEvent` to
110
+ // provide status update events, and other various bits of config like the
111
+ // pause duration and frequency.
112
+ const { pauseDuration, eventsPerChunk } = this.#modelConfiguration.processing;
113
+ const traceEventIterator = new TraceEventIterator(traceEvents, pauseDuration, eventsPerChunk);
114
+ // Convert to array so that we are able to iterate all handlers multiple times.
115
+ const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];
116
+ // Reset.
117
+ for (const handler of sortedHandlers) {
118
+ handler.reset();
119
+ }
120
+ // Initialize.
121
+ for (const handler of sortedHandlers) {
122
+ handler.initialize?.(freshRecording);
123
+ }
124
+ // Handle each event.
125
+ for await (const item of traceEventIterator) {
126
+ if (item.kind === 2 /* IteratorItemType.STATUS_UPDATE */) {
127
+ this.dispatchEvent(new TraceParseProgressEvent(item.data));
128
+ continue;
129
+ }
130
+ for (const handler of sortedHandlers) {
131
+ handler.handleEvent(item.data);
132
+ }
133
+ }
134
+ // Finalize.
135
+ for (const handler of sortedHandlers) {
136
+ await handler.finalize?.();
137
+ }
138
+ }
139
+ get data() {
140
+ if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
141
+ return null;
142
+ }
143
+ const data = {};
144
+ for (const [name, handler] of Object.entries(this.#traceHandlers)) {
145
+ Object.assign(data, { [name]: handler.data() });
146
+ }
147
+ return data;
148
+ }
149
+ }
150
+ /**
151
+ * Some Handlers need data provided by others. Dependencies of a handler handler are
152
+ * declared in the `deps` field.
153
+ * @returns A map from trace event handler name to trace event hander whose entries
154
+ * iterate in such a way that each handler is visited after its dependencies.
155
+ */
156
+ export function sortHandlers(traceHandlers) {
157
+ const sortedMap = new Map();
158
+ const visited = new Set();
159
+ const visitHandler = (handlerName) => {
160
+ if (sortedMap.has(handlerName)) {
161
+ return;
162
+ }
163
+ if (visited.has(handlerName)) {
164
+ let stackPath = '';
165
+ for (const handler of visited) {
166
+ if (stackPath || handler === handlerName) {
167
+ stackPath += `${handler}->`;
168
+ }
169
+ }
170
+ stackPath += handlerName;
171
+ throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);
172
+ }
173
+ visited.add(handlerName);
174
+ const handler = traceHandlers[handlerName];
175
+ if (!handler) {
176
+ return;
177
+ }
178
+ const deps = handler.deps?.();
179
+ if (deps) {
180
+ deps.forEach(visitHandler);
181
+ }
182
+ sortedMap.set(handlerName, handler);
183
+ };
184
+ for (const handlerName of Object.keys(traceHandlers)) {
185
+ visitHandler(handlerName);
186
+ }
187
+ return sortedMap;
188
+ }
189
+ class TraceEventIterator {
190
+ traceEvents;
191
+ pauseDuration;
192
+ eventsPerChunk;
193
+ #eventCount;
194
+ constructor(traceEvents, pauseDuration, eventsPerChunk) {
195
+ this.traceEvents = traceEvents;
196
+ this.pauseDuration = pauseDuration;
197
+ this.eventsPerChunk = eventsPerChunk;
198
+ this.#eventCount = 0;
199
+ }
200
+ async *[Symbol.asyncIterator]() {
201
+ for (let i = 0, length = this.traceEvents.length; i < length; i++) {
202
+ // Every so often we take a break just to render.
203
+ if (++this.#eventCount % this.eventsPerChunk === 0) {
204
+ // Take the opportunity to provide status update events.
205
+ yield { kind: 2 /* IteratorItemType.STATUS_UPDATE */, data: { index: i, total: length } };
206
+ // Wait for rendering before resuming.
207
+ await new Promise(resolve => setTimeout(resolve, this.pauseDuration));
208
+ }
209
+ yield { kind: 1 /* IteratorItemType.TRACE_EVENT */, data: this.traceEvents[i] };
210
+ }
211
+ }
212
+ }
213
+ //# sourceMappingURL=Processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor<EnabledModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler}> extends\n EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n readonly #traceHandlers: Handlers.Types.HandlersWithMeta<EnabledModelHandlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.DEFAULT;\n\n static createWithAllHandlers(): TraceProcessor<typeof Handlers.ModelHandlers> {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.DEFAULT);\n }\n\n constructor(traceHandlers: EnabledModelHandlers, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n updateConfiguration(config: Types.Configuration.Configuration): void {\n this.#modelConfiguration = config;\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: EnabledModelHandlers): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n for (const depName of (handler.deps?.() || [])) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#parse(traceEvents, freshRecording);\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n async #parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean): Promise<void> {\n // This iterator steps through all events, periodically yielding back to the\n // main thread to avoid blocking execution. It uses `dispatchEvent` to\n // provide status update events, and other various bits of config like the\n // pause duration and frequency.\n const {pauseDuration, eventsPerChunk} = this.#modelConfiguration.processing;\n const traceEventIterator = new TraceEventIterator(traceEvents, pauseDuration, eventsPerChunk);\n\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for await (const item of traceEventIterator) {\n if (item.kind === IteratorItemType.STATUS_UPDATE) {\n this.dispatchEvent(new TraceParseProgressEvent(item.data));\n continue;\n }\n for (const handler of sortedHandlers) {\n handler.handleEvent(item.data);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n await handler.finalize?.();\n }\n }\n\n get data(): Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n const data = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n Object.assign(data, {[name]: handler.data()});\n }\n\n return data as Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>;\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n\nconst enum IteratorItemType {\n TRACE_EVENT = 1,\n STATUS_UPDATE = 2,\n}\n\ntype IteratorItem = IteratorTraceEventItem|IteratorStatusUpdateItem;\n\ntype IteratorTraceEventItem = {\n kind: IteratorItemType.TRACE_EVENT,\n data: Types.TraceEvents.TraceEventData,\n};\n\ntype IteratorStatusUpdateItem = {\n kind: IteratorItemType.STATUS_UPDATE,\n data: TraceParseEventProgressData,\n};\n\nclass TraceEventIterator {\n #eventCount: number;\n\n constructor(\n private traceEvents: readonly Types.TraceEvents.TraceEventData[], private pauseDuration: number,\n private eventsPerChunk: number) {\n this.#eventCount = 0;\n }\n\n async * [Symbol.asyncIterator](): AsyncGenerator<IteratorItem, void, void> {\n for (let i = 0, length = this.traceEvents.length; i < length; i++) {\n // Every so often we take a break just to render.\n if (++this.#eventCount % this.eventsPerChunk === 0) {\n // Take the opportunity to provide status update events.\n yield {kind: IteratorItemType.STATUS_UPDATE, data: {index: i, total: length}};\n // Wait for rendering before resuming.\n await new Promise(resolve => setTimeout(resolve, this.pauseDuration));\n }\n\n yield {kind: IteratorItemType.TRACE_EVENT, data: this.traceEvents[i]};\n }\n }\n}\n"]}
@@ -0,0 +1,104 @@
1
+ import * as SDK from "../../core/sdk/sdk.js";
2
+ const domLookUpSingleNodeCache = /* @__PURE__ */ new Map();
3
+ const domLookUpBatchNodesCache = /* @__PURE__ */ new Map();
4
+ export function _TEST_clearCache() {
5
+ domLookUpSingleNodeCache.clear();
6
+ domLookUpBatchNodesCache.clear();
7
+ layoutShiftSourcesCache.clear();
8
+ normalizedLayoutShiftNodesCache.clear();
9
+ }
10
+ 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;
26
+ }
27
+ 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;
42
+ }
43
+ const layoutShiftSourcesCache = /* @__PURE__ */ new Map();
44
+ const normalizedLayoutShiftNodesCache = /* @__PURE__ */ new Map();
45
+ 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
+ });
63
+ }
64
+ }));
65
+ const cacheForModel = layoutShiftSourcesCache.get(modelData) || /* @__PURE__ */ new Map();
66
+ cacheForModel.set(event, sources);
67
+ layoutShiftSourcesCache.set(modelData, cacheForModel);
68
+ return sources;
69
+ }
70
+ 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;
93
+ }
94
+ for (let i = 0; i < impactedNode.new_rect.length; i++) {
95
+ newNode.new_rect[i] /= viewportScale;
96
+ }
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;
103
+ }
104
+ //# sourceMappingURL=SDKServices.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../front_end/models/trace/SDKServices.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
+ }
@@ -0,0 +1,133 @@
1
+ import { TraceParseEvent } from "./ModelImpl.js";
2
+ var Status = /* @__PURE__ */ ((Status2) => {
3
+ Status2[Status2["IDLE"] = 0] = "IDLE";
4
+ Status2[Status2["PARSING"] = 1] = "PARSING";
5
+ Status2[Status2["FINISHED_PARSING"] = 2] = "FINISHED_PARSING";
6
+ Status2[Status2["ERRORED_WHILE_PARSING"] = 3] = "ERRORED_WHILE_PARSING";
7
+ return Status2;
8
+ })(Status || {});
9
+ export class TraceProcessor extends EventTarget {
10
+ #traceHandlers;
11
+ #pauseDuration;
12
+ #pauseFrequencyMs;
13
+ #status = 0 /* IDLE */;
14
+ constructor(traceHandlers, { pauseDuration = 20, pauseFrequencyMs = 100 } = {}) {
15
+ super();
16
+ this.#traceHandlers = traceHandlers;
17
+ this.#pauseDuration = pauseDuration;
18
+ this.#pauseFrequencyMs = pauseFrequencyMs;
19
+ }
20
+ reset() {
21
+ if (this.#status === 1 /* PARSING */) {
22
+ throw new Error("Trace processor can't reset while parsing.");
23
+ }
24
+ const handlers = Object.values(this.#traceHandlers);
25
+ for (const handler of handlers) {
26
+ handler.reset();
27
+ }
28
+ this.#status = 0 /* IDLE */;
29
+ }
30
+ async parse(traceEvents, freshRecording = false) {
31
+ if (this.#status !== 0 /* IDLE */) {
32
+ throw new Error("Trace processor can't start parsing when not idle.");
33
+ }
34
+ try {
35
+ this.#status = 1 /* PARSING */;
36
+ await this.#parse(traceEvents, freshRecording);
37
+ this.#status = 2 /* FINISHED_PARSING */;
38
+ } catch (e) {
39
+ this.#status = 3 /* ERRORED_WHILE_PARSING */;
40
+ throw e;
41
+ }
42
+ }
43
+ async #parse(traceEvents, freshRecording) {
44
+ const traceEventIterator = new TraceEventIterator(traceEvents, this.#pauseDuration, this.#pauseFrequencyMs);
45
+ const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];
46
+ for (const handler of sortedHandlers) {
47
+ handler.reset();
48
+ }
49
+ for (const handler of sortedHandlers) {
50
+ handler.initialize?.(freshRecording);
51
+ }
52
+ for await (const item of traceEventIterator) {
53
+ if (item.kind === IteratorItemType.STATUS_UPDATE) {
54
+ this.dispatchEvent(new TraceParseEvent(item.data));
55
+ continue;
56
+ }
57
+ for (const handler of sortedHandlers) {
58
+ handler.handleEvent(item.data);
59
+ }
60
+ }
61
+ for (const handler of sortedHandlers) {
62
+ await handler.finalize?.();
63
+ }
64
+ }
65
+ get data() {
66
+ if (this.#status !== 2 /* FINISHED_PARSING */) {
67
+ return null;
68
+ }
69
+ const data = {};
70
+ for (const [name, handler] of Object.entries(this.#traceHandlers)) {
71
+ Object.assign(data, { [name]: handler.data() });
72
+ }
73
+ return data;
74
+ }
75
+ }
76
+ export function sortHandlers(traceHandlers) {
77
+ const sortedMap = /* @__PURE__ */ new Map();
78
+ const visited = /* @__PURE__ */ new Set();
79
+ const visitHandler = (handlerName) => {
80
+ if (sortedMap.has(handlerName)) {
81
+ return;
82
+ }
83
+ if (visited.has(handlerName)) {
84
+ let stackPath = "";
85
+ for (const handler2 of visited) {
86
+ if (stackPath || handler2 === handlerName) {
87
+ stackPath += `${handler2}->`;
88
+ }
89
+ }
90
+ stackPath += handlerName;
91
+ throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);
92
+ }
93
+ visited.add(handlerName);
94
+ const handler = traceHandlers[handlerName];
95
+ if (!handler) {
96
+ return;
97
+ }
98
+ const deps = handler.deps?.();
99
+ if (deps) {
100
+ deps.forEach(visitHandler);
101
+ }
102
+ sortedMap.set(handlerName, handler);
103
+ };
104
+ for (const handlerName of Object.keys(traceHandlers)) {
105
+ visitHandler(handlerName);
106
+ }
107
+ return sortedMap;
108
+ }
109
+ var IteratorItemType = /* @__PURE__ */ ((IteratorItemType2) => {
110
+ IteratorItemType2[IteratorItemType2["TRACE_EVENT"] = 1] = "TRACE_EVENT";
111
+ IteratorItemType2[IteratorItemType2["STATUS_UPDATE"] = 2] = "STATUS_UPDATE";
112
+ return IteratorItemType2;
113
+ })(IteratorItemType || {});
114
+ class TraceEventIterator {
115
+ constructor(traceEvents, pauseDuration, pauseFrequencyMs) {
116
+ this.traceEvents = traceEvents;
117
+ this.pauseDuration = pauseDuration;
118
+ this.pauseFrequencyMs = pauseFrequencyMs;
119
+ this.#time = performance.now();
120
+ }
121
+ #time;
122
+ async *[Symbol.asyncIterator]() {
123
+ for (let i = 0, length = this.traceEvents.length; i < length; i++) {
124
+ if (performance.now() - this.#time > this.pauseFrequencyMs) {
125
+ this.#time = performance.now();
126
+ yield { kind: 2 /* STATUS_UPDATE */, data: { index: i, total: length } };
127
+ await new Promise((resolve) => setTimeout(resolve, this.pauseDuration));
128
+ }
129
+ yield { kind: 1 /* TRACE_EVENT */, data: this.traceEvents[i] };
130
+ }
131
+ }
132
+ }
133
+ //# sourceMappingURL=TraceProcessor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../front_end/models/trace/TraceProcessor.ts"],
4
+ "sourcesContent": ["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from './handlers/handlers.js';\nimport type * as Types from './types/types.js';\n\nimport {type TraceParseEventProgressData, TraceParseEvent} from './ModelImpl.js';\nconst enum Status {\n IDLE = 0,\n PARSING = 1,\n FINISHED_PARSING = 2,\n ERRORED_WHILE_PARSING = 3,\n}\n\nexport class TraceProcessor<ModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler}> extends\n EventTarget {\n readonly #traceHandlers: {[key: string]: Handlers.Types.TraceEventHandler};\n #pauseDuration: number;\n #pauseFrequencyMs: number;\n #status = Status.IDLE;\n\n constructor(traceHandlers: ModelHandlers, {pauseDuration = 20, pauseFrequencyMs = 100} = {}) {\n super();\n\n this.#traceHandlers = traceHandlers;\n this.#pauseDuration = pauseDuration;\n this.#pauseFrequencyMs = pauseFrequencyMs;\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error('Trace processor can\\'t start parsing when not idle.');\n }\n try {\n this.#status = Status.PARSING;\n await this.#parse(traceEvents, freshRecording);\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n async #parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean): Promise<void> {\n // This iterator steps through all events, periodically yielding back to the\n // main thread to avoid blocking execution. It uses `dispatchEvent` to\n // provide status update events, and other various bits of config like the\n // pause duration and frequency.\n const traceEventIterator = new TraceEventIterator(traceEvents, this.#pauseDuration, this.#pauseFrequencyMs);\n\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for await (const item of traceEventIterator) {\n if (item.kind === IteratorItemType.STATUS_UPDATE) {\n this.dispatchEvent(new TraceParseEvent(item.data));\n continue;\n }\n for (const handler of sortedHandlers) {\n handler.handleEvent(item.data);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n await handler.finalize?.();\n }\n }\n\n get data(): Handlers.Types.HandlerData<ModelHandlers>|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n const data = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n Object.assign(data, {[name]: handler.data()});\n }\n\n return data as Handlers.Types.HandlerData<ModelHandlers>;\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n\nconst enum IteratorItemType {\n TRACE_EVENT = 1,\n STATUS_UPDATE = 2,\n}\n\ntype IteratorItem = IteratorTraceEventItem|IteratorStatusUpdateItem;\n\ntype IteratorTraceEventItem = {\n kind: IteratorItemType.TRACE_EVENT,\n data: Types.TraceEvents.TraceEventData,\n};\n\ntype IteratorStatusUpdateItem = {\n kind: IteratorItemType.STATUS_UPDATE,\n data: TraceParseEventProgressData,\n};\n\nclass TraceEventIterator {\n #time: number;\n\n constructor(\n private traceEvents: readonly Types.TraceEvents.TraceEventData[], private pauseDuration: number,\n private pauseFrequencyMs: number) {\n this.#time = performance.now();\n }\n\n async * [Symbol.asyncIterator](): AsyncGenerator<IteratorItem, void, void> {\n for (let i = 0, length = this.traceEvents.length; i < length; i++) {\n // Every so often we take a break just to render.\n if (performance.now() - this.#time > this.pauseFrequencyMs) {\n this.#time = performance.now();\n // Take the opportunity to provide status update events.\n yield {kind: IteratorItemType.STATUS_UPDATE, data: {index: i, total: length}};\n // Wait for rendering before resuming.\n await new Promise(resolve => setTimeout(resolve, this.pauseDuration));\n }\n\n yield {kind: IteratorItemType.TRACE_EVENT, data: this.traceEvents[i]};\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TracingManager.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/TracingManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2014 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 ProtocolProxyApi from '../../generated/protocol-proxy-api.js';\nimport * as Protocol from '../../generated/protocol.js';\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport {type ObjectSnapshot} from './LegacyTracingModel.js';\nimport type * as Types from './types/types.js';\n\nexport class TracingManager extends SDK.SDKModel.SDKModel<void> {\n readonly #tracingAgent: ProtocolProxyApi.TracingApi;\n #activeClient: TracingManagerClient|null;\n #eventBufferSize: number|null;\n #eventsRetrieved: number;\n #finishing?: boolean;\n constructor(target: SDK.Target.Target) {\n super(target);\n this.#tracingAgent = target.tracingAgent();\n target.registerTracingDispatcher(new TracingDispatcher(this));\n\n this.#activeClient = null;\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n }\n\n bufferUsage(usage?: number, eventCount?: number, percentFull?: number): void {\n this.#eventBufferSize = eventCount === undefined ? null : eventCount;\n if (this.#activeClient) {\n this.#activeClient.tracingBufferUsage(usage || percentFull || 0);\n }\n }\n\n eventsCollected(events: EventPayload[]): void {\n if (!this.#activeClient) {\n return;\n }\n this.#activeClient.traceEventsCollected(events);\n this.#eventsRetrieved += events.length;\n if (!this.#eventBufferSize) {\n this.#activeClient.eventsRetrievalProgress(0);\n return;\n }\n\n if (this.#eventsRetrieved > this.#eventBufferSize) {\n this.#eventsRetrieved = this.#eventBufferSize;\n }\n this.#activeClient.eventsRetrievalProgress(this.#eventsRetrieved / this.#eventBufferSize);\n }\n\n tracingComplete(): void {\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n if (this.#activeClient) {\n this.#activeClient.tracingComplete();\n this.#activeClient = null;\n }\n this.#finishing = false;\n }\n\n async reset(): Promise<void> {\n // If we have an active client, we should try to stop\n // it before resetting it, else we will leave the\n // backend in a broken state where it thinks we are in\n // the middle of tracing, but we think we are not.\n // Then, any subsequent attempts to record will fail\n // because the backend will not let us start a second\n // tracing session.\n if (this.#activeClient) {\n await this.#tracingAgent.invoke_end();\n }\n this.#eventBufferSize = 0;\n this.#eventsRetrieved = 0;\n this.#activeClient = null;\n this.#finishing = false;\n }\n\n // TODO(petermarshall): Use the traceConfig argument instead of deprecated\n // categories + options.\n async start(client: TracingManagerClient, categoryFilter: string, options: string):\n Promise<Protocol.ProtocolResponseWithError> {\n if (this.#activeClient) {\n throw new Error('Tracing is already started');\n }\n const bufferUsageReportingIntervalMs = 500;\n this.#activeClient = client;\n const args = {\n bufferUsageReportingInterval: bufferUsageReportingIntervalMs,\n categories: categoryFilter,\n options: options,\n transferMode: Protocol.Tracing.StartRequestTransferMode.ReportEvents,\n };\n const response = await this.#tracingAgent.invoke_start(args);\n if (response.getError()) {\n this.#activeClient = null;\n }\n await this.warmupJsProfiler();\n return response;\n }\n\n // CPUProfiler::StartProfiling has a non-trivial cost and we'd prefer it not happen within an\n // interaction as that complicates debugging interaction latency.\n // To trigger the StartProfiling interrupt and get the warmup cost out of the way, we send a\n // very soft invocation to V8.\n // https://crbug.com/1358602\n async warmupJsProfiler(): Promise<void> {\n const runtimeModel = this.target().model(SDK.RuntimeModel.RuntimeModel);\n if (!runtimeModel) {\n return;\n }\n await runtimeModel.checkSideEffectSupport();\n }\n\n stop(): void {\n if (!this.#activeClient) {\n throw new Error('Tracing is not started');\n }\n if (this.#finishing) {\n throw new Error('Tracing is already being stopped');\n }\n this.#finishing = true;\n void this.#tracingAgent.invoke_end();\n }\n}\n\nexport interface TracingManagerClient {\n traceEventsCollected(events: EventPayload[]): void;\n\n tracingComplete(): void;\n tracingBufferUsage(usage: number): void;\n eventsRetrievalProgress(progress: number): void;\n}\n\nclass TracingDispatcher implements ProtocolProxyApi.TracingDispatcher {\n readonly #tracingManager: TracingManager;\n constructor(tracingManager: TracingManager) {\n this.#tracingManager = tracingManager;\n }\n\n bufferUsage({value, eventCount, percentFull}: Protocol.Tracing.BufferUsageEvent): void {\n this.#tracingManager.bufferUsage(value, eventCount, percentFull);\n }\n\n dataCollected({value}: Protocol.Tracing.DataCollectedEvent): void {\n this.#tracingManager.eventsCollected(value);\n }\n\n tracingComplete(): void {\n this.#tracingManager.tracingComplete();\n }\n}\n\nSDK.SDKModel.SDKModel.register(TracingManager, {capabilities: SDK.Target.Capability.Tracing, autostart: false});\nexport interface EventPayload {\n cat?: string;\n pid: number;\n tid: number;\n ts: number;\n ph: Types.TraceEvents.Phase;\n name: string;\n args: {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/naming-convention\n sort_index: number,\n name: string,\n snapshot: ObjectSnapshot,\n data: Object|null,\n };\n dur: number;\n id?: string;\n id2?: {\n global: (string|undefined),\n local: (string|undefined),\n };\n scope: string;\n}\n"]}
@@ -0,0 +1,85 @@
1
+ import * as Platform from "../../core/platform/platform.js";
2
+ export var TreeAction = /* @__PURE__ */ ((TreeAction2) => {
3
+ TreeAction2["MERGE_FUNCTION"] = "MERGE_FUNCTION";
4
+ TreeAction2["COLLAPSE_FUNCTION"] = "COLLAPSE_FUNCTION";
5
+ return TreeAction2;
6
+ })(TreeAction || {});
7
+ export class TreeManipulator {
8
+ #entryToNode;
9
+ #lastInvisibleEntries = null;
10
+ #activeActions = [];
11
+ constructor(entryToNode) {
12
+ this.#entryToNode = entryToNode;
13
+ }
14
+ applyAction(action) {
15
+ if (this.#actionIsActive(action)) {
16
+ return;
17
+ }
18
+ this.#activeActions.push(action);
19
+ this.#lastInvisibleEntries = null;
20
+ }
21
+ removeActiveAction(action) {
22
+ let removedAction = false;
23
+ this.#activeActions = this.#activeActions.filter((activeAction) => {
24
+ if (activeAction.type === action.type && activeAction.entry === action.entry) {
25
+ removedAction = true;
26
+ return false;
27
+ }
28
+ return true;
29
+ });
30
+ if (removedAction) {
31
+ this.#lastInvisibleEntries = null;
32
+ }
33
+ }
34
+ #actionIsActive(action) {
35
+ return this.#activeActions.some((activeAction) => {
36
+ return action.entry === activeAction.entry && action.type === activeAction.type;
37
+ });
38
+ }
39
+ invisibleEntries() {
40
+ if (this.#activeActions.length === 0) {
41
+ return [];
42
+ }
43
+ return this.#calculateInvisibleEntries();
44
+ }
45
+ #calculateInvisibleEntries() {
46
+ if (this.#lastInvisibleEntries) {
47
+ return this.#lastInvisibleEntries;
48
+ }
49
+ const entriesToHide = /* @__PURE__ */ new Set();
50
+ for (const action of this.#activeActions) {
51
+ switch (action.type) {
52
+ case "MERGE_FUNCTION" /* MERGE_FUNCTION */: {
53
+ entriesToHide.add(action.entry);
54
+ break;
55
+ }
56
+ case "COLLAPSE_FUNCTION" /* COLLAPSE_FUNCTION */: {
57
+ const entryNode = this.#entryToNode.get(action.entry);
58
+ if (!entryNode) {
59
+ continue;
60
+ }
61
+ const allAncestors = this.#findAllAncestorsOfNode(entryNode);
62
+ allAncestors.forEach((ancestor) => entriesToHide.add(ancestor));
63
+ break;
64
+ }
65
+ default:
66
+ Platform.assertNever(action.type, `Unknown TreeManipulator action: ${action.type}`);
67
+ }
68
+ }
69
+ this.#lastInvisibleEntries = [...entriesToHide];
70
+ return this.#lastInvisibleEntries;
71
+ }
72
+ #findAllAncestorsOfNode(root) {
73
+ const ancestors = [];
74
+ const children = [...root.children];
75
+ while (children.length > 0) {
76
+ const childNode = children.shift();
77
+ if (childNode) {
78
+ ancestors.push(childNode.entry);
79
+ children.push(...childNode.children);
80
+ }
81
+ }
82
+ return ancestors;
83
+ }
84
+ }
85
+ //# sourceMappingURL=TreeManipulator.js.map