@paulirish/trace_engine 0.0.53 → 0.0.55

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 (241) hide show
  1. package/.tmp/tsbuildinfo/analyze-inspector-issues.d.mts +13 -0
  2. package/.tmp/tsbuildinfo/analyze-inspector-issues.d.mts.map +1 -0
  3. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  4. package/analyze-inspector-issues.mjs +60 -0
  5. package/core/common/common.d.ts +1 -0
  6. package/core/common/common.js +1 -0
  7. package/core/host/host.d.ts +1 -0
  8. package/core/host/host.js +1 -0
  9. package/core/platform/MimeType.d.ts +3 -2
  10. package/core/platform/MimeType.js +4 -3
  11. package/core/platform/MimeType.js.map +1 -1
  12. package/core/root/root.d.ts +1 -0
  13. package/core/root/root.js +1 -0
  14. package/core/sdk/sdk.d.ts +1 -0
  15. package/core/sdk/sdk.js +1 -0
  16. package/generated/protocol.d.ts +115 -16
  17. package/locales/af.json +52 -10
  18. package/locales/am.json +52 -10
  19. package/locales/ar.json +51 -9
  20. package/locales/as.json +52 -10
  21. package/locales/az.json +52 -10
  22. package/locales/be.json +52 -10
  23. package/locales/bg.json +52 -10
  24. package/locales/bn.json +52 -10
  25. package/locales/bs.json +52 -10
  26. package/locales/ca.json +52 -10
  27. package/locales/cs.json +52 -10
  28. package/locales/cy.json +52 -10
  29. package/locales/da.json +52 -10
  30. package/locales/de.json +52 -10
  31. package/locales/el.json +52 -10
  32. package/locales/en-GB.json +52 -10
  33. package/locales/en-US.json +12 -12
  34. package/locales/en-XL.json +12 -12
  35. package/locales/es-419.json +52 -10
  36. package/locales/es.json +50 -8
  37. package/locales/et.json +52 -10
  38. package/locales/eu.json +52 -10
  39. package/locales/fa.json +51 -9
  40. package/locales/fi.json +52 -10
  41. package/locales/fil.json +52 -10
  42. package/locales/fr-CA.json +52 -10
  43. package/locales/fr.json +52 -10
  44. package/locales/gl.json +52 -10
  45. package/locales/gu.json +52 -10
  46. package/locales/he.json +52 -10
  47. package/locales/hi.json +52 -10
  48. package/locales/hr.json +52 -10
  49. package/locales/hu.json +51 -9
  50. package/locales/hy.json +51 -9
  51. package/locales/id.json +52 -10
  52. package/locales/is.json +53 -11
  53. package/locales/it.json +51 -9
  54. package/locales/ja.json +52 -10
  55. package/locales/ka.json +53 -11
  56. package/locales/kk.json +51 -9
  57. package/locales/km.json +52 -10
  58. package/locales/kn.json +52 -10
  59. package/locales/ko.json +52 -10
  60. package/locales/ky.json +51 -9
  61. package/locales/lo.json +52 -10
  62. package/locales/lt.json +52 -10
  63. package/locales/lv.json +51 -9
  64. package/locales/mk.json +52 -10
  65. package/locales/ml.json +53 -11
  66. package/locales/mn.json +52 -10
  67. package/locales/mr.json +52 -10
  68. package/locales/ms.json +52 -10
  69. package/locales/my.json +51 -9
  70. package/locales/ne.json +52 -10
  71. package/locales/nl.json +52 -10
  72. package/locales/no.json +52 -10
  73. package/locales/or.json +53 -11
  74. package/locales/pa.json +53 -11
  75. package/locales/pl.json +51 -9
  76. package/locales/pt-PT.json +52 -10
  77. package/locales/pt.json +52 -10
  78. package/locales/ro.json +52 -10
  79. package/locales/ru.json +53 -11
  80. package/locales/si.json +52 -10
  81. package/locales/sk.json +51 -9
  82. package/locales/sl.json +51 -9
  83. package/locales/sq.json +52 -10
  84. package/locales/sr-Latn.json +52 -10
  85. package/locales/sr.json +52 -10
  86. package/locales/sv.json +52 -10
  87. package/locales/sw.json +51 -9
  88. package/locales/ta.json +52 -10
  89. package/locales/te.json +52 -10
  90. package/locales/th.json +51 -9
  91. package/locales/tr.json +52 -10
  92. package/locales/uk.json +52 -10
  93. package/locales/ur.json +52 -10
  94. package/locales/uz.json +51 -9
  95. package/locales/vi.json +52 -10
  96. package/locales/zh-HK.json +52 -10
  97. package/locales/zh-TW.json +51 -9
  98. package/locales/zh.json +52 -10
  99. package/locales/zu.json +52 -10
  100. package/models/cpu_profile/CPUProfileDataModel.d.ts +4 -2
  101. package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
  102. package/models/cpu_profile/ProfileTreeModel.d.ts +0 -1
  103. package/models/cpu_profile/ProfileTreeModel.js +0 -2
  104. package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
  105. package/models/issues_manager/CheckFormsIssuesTrigger.d.ts +1 -0
  106. package/models/issues_manager/CheckFormsIssuesTrigger.js +1 -0
  107. package/models/issues_manager/ContrastCheckTrigger.d.ts +1 -0
  108. package/models/issues_manager/ContrastCheckTrigger.js +1 -0
  109. package/models/issues_manager/DeprecationIssue.d.ts +1 -0
  110. package/models/issues_manager/DeprecationIssue.js +1 -0
  111. package/models/issues_manager/IssueResolver.d.ts +1 -0
  112. package/models/issues_manager/IssueResolver.js +1 -0
  113. package/models/issues_manager/RelatedIssue.d.ts +1 -0
  114. package/models/issues_manager/RelatedIssue.js +1 -0
  115. package/models/issues_manager/SourceFrameIssuesManager.d.ts +1 -0
  116. package/models/issues_manager/SourceFrameIssuesManager.js +1 -0
  117. package/models/trace/LanternComputationData.js +9 -8
  118. package/models/trace/LanternComputationData.js.map +1 -1
  119. package/models/trace/ModelImpl.js +1 -1
  120. package/models/trace/ModelImpl.js.map +1 -1
  121. package/models/trace/Processor.js +23 -16
  122. package/models/trace/Processor.js.map +1 -1
  123. package/models/trace/extras/ThirdParties.js +1 -1
  124. package/models/trace/extras/ThirdParties.js.map +1 -1
  125. package/models/trace/extras/TraceFilter.js +2 -2
  126. package/models/trace/extras/TraceFilter.js.map +1 -1
  127. package/models/trace/extras/extras-tsconfig.json +0 -2
  128. package/models/trace/extras/extras.d.ts +4 -1
  129. package/models/trace/extras/extras.js +4 -1
  130. package/models/trace/extras/extras.js.map +1 -1
  131. package/models/trace/handlers/AuctionWorkletsHandler.js +5 -5
  132. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
  133. package/models/trace/handlers/ExtensionTraceDataHandler.js +4 -4
  134. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  135. package/models/trace/handlers/FlowsHandler.js +3 -3
  136. package/models/trace/handlers/FlowsHandler.js.map +1 -1
  137. package/models/trace/handlers/FramesHandler.js +7 -7
  138. package/models/trace/handlers/FramesHandler.js.map +1 -1
  139. package/models/trace/handlers/LargestImagePaintHandler.js +2 -2
  140. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
  141. package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -1
  142. package/models/trace/handlers/LayoutShiftsHandler.js +18 -10
  143. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  144. package/models/trace/handlers/MetaHandler.js +9 -7
  145. package/models/trace/handlers/MetaHandler.js.map +1 -1
  146. package/models/trace/handlers/NetworkRequestsHandler.d.ts +0 -5
  147. package/models/trace/handlers/NetworkRequestsHandler.js +3 -22
  148. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  149. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -2
  150. package/models/trace/handlers/PageLoadMetricsHandler.js +54 -25
  151. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  152. package/models/trace/handlers/RendererHandler.js +1 -1
  153. package/models/trace/handlers/RendererHandler.js.map +1 -1
  154. package/models/trace/handlers/SamplesHandler.js +7 -2
  155. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  156. package/models/trace/handlers/ScriptsHandler.js.map +1 -1
  157. package/models/trace/handlers/Threads.d.ts +1 -1
  158. package/models/trace/handlers/Threads.js +17 -7
  159. package/models/trace/handlers/Threads.js.map +1 -1
  160. package/models/trace/handlers/UserInteractionsHandler.js +4 -3
  161. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  162. package/models/trace/handlers/WarningsHandler.js +2 -2
  163. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  164. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
  165. package/models/trace/helpers/SamplesIntegrator.js +23 -21
  166. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  167. package/models/trace/helpers/Trace.js +111 -118
  168. package/models/trace/helpers/Trace.js.map +1 -1
  169. package/models/trace/insights/CLSCulprits.d.ts +25 -5
  170. package/models/trace/insights/CLSCulprits.js +73 -33
  171. package/models/trace/insights/CLSCulprits.js.map +1 -1
  172. package/models/trace/insights/Common.js +4 -3
  173. package/models/trace/insights/Common.js.map +1 -1
  174. package/models/trace/insights/DOMSize.js +3 -3
  175. package/models/trace/insights/DOMSize.js.map +1 -1
  176. package/models/trace/insights/DocumentLatency.d.ts +2 -2
  177. package/models/trace/insights/DocumentLatency.js +4 -4
  178. package/models/trace/insights/DocumentLatency.js.map +1 -1
  179. package/models/trace/insights/DuplicatedJavaScript.js +2 -2
  180. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
  181. package/models/trace/insights/FontDisplay.js +2 -2
  182. package/models/trace/insights/FontDisplay.js.map +1 -1
  183. package/models/trace/insights/ForcedReflow.js +2 -2
  184. package/models/trace/insights/ForcedReflow.js.map +1 -1
  185. package/models/trace/insights/ImageDelivery.js +2 -2
  186. package/models/trace/insights/ImageDelivery.js.map +1 -1
  187. package/models/trace/insights/InteractionToNextPaint.js +3 -3
  188. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  189. package/models/trace/insights/LCPDiscovery.js +3 -3
  190. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  191. package/models/trace/insights/LCPPhases.js +3 -3
  192. package/models/trace/insights/LCPPhases.js.map +1 -1
  193. package/models/trace/insights/LegacyJavaScript.js +2 -2
  194. package/models/trace/insights/LegacyJavaScript.js.map +1 -1
  195. package/models/trace/insights/ModernHTTP.js +2 -2
  196. package/models/trace/insights/ModernHTTP.js.map +1 -1
  197. package/models/trace/insights/NetworkDependencyTree.d.ts +31 -5
  198. package/models/trace/insights/NetworkDependencyTree.js +137 -12
  199. package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
  200. package/models/trace/insights/RenderBlocking.js +3 -3
  201. package/models/trace/insights/RenderBlocking.js.map +1 -1
  202. package/models/trace/insights/SlowCSSSelector.js +2 -2
  203. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  204. package/models/trace/insights/ThirdParties.js +2 -2
  205. package/models/trace/insights/ThirdParties.js.map +1 -1
  206. package/models/trace/insights/Viewport.d.ts +8 -2
  207. package/models/trace/insights/Viewport.js +18 -3
  208. package/models/trace/insights/Viewport.js.map +1 -1
  209. package/models/trace/insights/types.d.ts +1 -1
  210. package/models/trace/insights/types.js +19 -0
  211. package/models/trace/insights/types.js.map +1 -1
  212. package/models/trace/lantern/graph/BaseNode.d.ts +5 -2
  213. package/models/trace/lantern/graph/BaseNode.js +8 -5
  214. package/models/trace/lantern/graph/BaseNode.js.map +1 -1
  215. package/models/trace/lantern/graph/PageDependencyGraph.js +46 -3
  216. package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
  217. package/models/trace/lantern/simulation/Simulator.js +1 -1
  218. package/models/trace/lantern/simulation/Simulator.js.map +1 -1
  219. package/models/trace/trace-tsconfig.json +0 -1
  220. package/models/trace/trace.d.ts +1 -2
  221. package/models/trace/trace.js +1 -2
  222. package/models/trace/trace.js.map +1 -1
  223. package/models/trace/types/Extensions.d.ts +6 -1
  224. package/models/trace/types/Extensions.js.map +1 -1
  225. package/models/trace/types/File.d.ts +18 -4
  226. package/models/trace/types/File.js +28 -4
  227. package/models/trace/types/File.js.map +1 -1
  228. package/models/trace/types/TraceEvents.d.ts +13 -10
  229. package/models/trace/types/TraceEvents.js +377 -108
  230. package/models/trace/types/TraceEvents.js.map +1 -1
  231. package/package.json +1 -1
  232. package/test/test-trace-engine.mjs +77 -0
  233. package/third_party/marked/marked.d.ts +1 -0
  234. package/third_party/marked/marked.js +1 -0
  235. package/models/trace/TracingManager.js.map +0 -1
  236. package/models/trace/extras/FetchNodes.d.ts +0 -61
  237. package/models/trace/extras/FetchNodes.js +0 -214
  238. package/models/trace/extras/FetchNodes.js.map +0 -1
  239. package/models/trace/extras/Metadata.d.ts +0 -3
  240. package/models/trace/extras/Metadata.js +0 -71
  241. package/models/trace/extras/Metadata.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paulirish/trace_engine",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "description": "",
5
5
  "main": "models/trace/trace.js",
6
6
  "scripts": {
@@ -3,9 +3,12 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import {strict as assert} from 'assert';
6
+ import fs from 'fs';
6
7
  import test from 'node:test';
7
8
 
8
9
  import {analyzeTrace} from '../analyze-trace.mjs';
10
+ // import {analyzeInspectorIssues} from '../analyze-inspector-issues.mjs';
11
+ import * as Trace from '../models/trace/trace.js';
9
12
 
10
13
  const filename = './test/invalid-animation-events.json.gz';
11
14
  const {parsedTrace: data, insights} = await analyzeTrace(filename);
@@ -114,3 +117,77 @@ test('insights look ok', t => {
114
117
  };
115
118
  assert.deepStrictEqual(simplified, expected);
116
119
  });
120
+
121
+ test('bottom-up summary is good', t => {
122
+ const parsedTrace = data;
123
+ const visibleEvents = Trace.Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();
124
+ const filter = new Trace.Extras.TraceFilter.VisibleEventsFilter(
125
+ visibleEvents.concat([Trace.Types.Events.Name.SYNTHETIC_NETWORK_REQUEST]));
126
+ const milliBounds = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds);
127
+
128
+
129
+ const mainThreadProbably =
130
+ Trace.Handlers.Threads.threadsInTrace(parsedTrace)
131
+ .filter(t => t.type === Trace.Handlers.Threads.ThreadType.MAIN_THREAD && t.processIsOnMainFrame)
132
+ .sort((a, b) => b.entries.length - a.entries.length)
133
+ .at(0);
134
+ if (!mainThreadProbably)
135
+ assert.fail('No main thread found in trace');
136
+
137
+ /** @param {Trace.Types.Events.Event} event */
138
+ const groupingFunction = event => event.name;
139
+
140
+ const node = new Trace.Extras.TraceTree.BottomUpRootNode([...mainThreadProbably.entries], {
141
+ textFilter: new Trace.Extras.TraceFilter.ExclusiveNameFilter([]),
142
+ filters: [filter],
143
+ startTime: milliBounds.min,
144
+ endTime: milliBounds.max,
145
+ eventGroupIdCallback: groupingFunction,
146
+ });
147
+
148
+ const bottomUpByName =
149
+ Array.from(node.children().values())
150
+ .map(c => [c.id.toString().padEnd(30), c.selfTime.toLocaleString().padStart(10) + 'ms'].join('\t'));
151
+
152
+ assert.deepStrictEqual(bottomUpByName.join('\n'), `
153
+ RunTask 105.929ms
154
+ V8.CompileCode 28.32ms
155
+ CpuProfiler::StartProfiling 20.116ms
156
+ FunctionCall 4.239ms
157
+ ProfileCall 25.086ms
158
+ EventDispatch 1.235ms
159
+ MinorGC 1.907ms
160
+ v8.compile 1.729ms
161
+ v8.produceCache 0.165ms
162
+ EvaluateScript 3.073ms
163
+ ParseHTML 9.719ms
164
+ UpdateLayoutTree 12.108ms
165
+ Layout 36.788ms
166
+ PrePaint 10.425ms
167
+ Paint 8.374ms
168
+ Layerize 2.419ms
169
+ Commit 4.394ms
170
+ RunMicrotasks 0.854ms
171
+ FireIdleCallback 0.129ms
172
+ HitTest 0.087ms
173
+ ParseAuthorStyleSheet 0.23ms
174
+ FireAnimationFrame 0.14ms
175
+ TimerFire 0.107ms
176
+ v8.evaluateModule 0.062ms
177
+ v8.produceModuleCache 0.005ms
178
+ Decode Image 0.043ms
179
+ `.trim());
180
+ });
181
+
182
+
183
+ // TODO: needs more work...
184
+ // test('inspector issues ok', t => {
185
+ // const artifactsPath = [
186
+ // '../lighthouse/core/test/results/artifacts/artifacts.json',
187
+ // '../../src/lighthouse/core/test/results/artifacts/artifacts.json',
188
+ // ].find(f => fs.existsSync(f));
189
+ // assert(artifactsPath);
190
+ // const issues = analyzeInspectorIssues(artifactsPath);
191
+ // assert.equal(issues.length, 4);
192
+ // console.log(issues[0].getDescription());
193
+ // });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +0,0 @@
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 * as SDK from '../../core/sdk/sdk.js';\nimport type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';\nimport * as Protocol from '../../generated/protocol.js';\n\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 #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.#eventsRetrieved = 0;\n }\n\n bufferUsage(usage?: number, percentFull?: number): void {\n if (this.#activeClient) {\n this.#activeClient.tracingBufferUsage(usage || percentFull || 0);\n }\n }\n\n eventsCollected(events: Types.Events.Event[]): void {\n if (!this.#activeClient) {\n return;\n }\n this.#activeClient.traceEventsCollected(events);\n this.#eventsRetrieved += events.length;\n\n // CDP no longer provides an approximate_event_count AKA eventCount. It's always 0.\n // To give some idea of progress we'll compare to a large (900k event) trace.\n // And we'll clamp both sides so the user sees some progress, and never maxed at 99%\n const progress = Math.min((this.#eventsRetrieved / 900_000) + 0.15, 0.90);\n this.#activeClient.eventsRetrievalProgress(progress);\n }\n\n tracingComplete(): void {\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.#eventsRetrieved = 0;\n this.#activeClient = null;\n this.#finishing = false;\n }\n\n async start(client: TracingManagerClient, categoryFilter: string): 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 transferMode: Protocol.Tracing.StartRequestTransferMode.ReportEvents,\n traceConfig: {\n recordMode: Protocol.Tracing.TraceConfigRecordMode.RecordUntilFull,\n traceBufferSizeInKb: 1200 * 1000,\n includedCategories: categoryFilter.split(','),\n },\n };\n const response = await this.#tracingAgent.invoke_start(args);\n if (response.getError()) {\n this.#activeClient = null;\n }\n return response;\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: Types.Events.Event[]): 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 // `eventCount` will always be 0 as perfetto no longer calculates `approximate_event_count`\n bufferUsage({value, percentFull}: Protocol.Tracing.BufferUsageEvent): void {\n this.#tracingManager.bufferUsage(value, 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});\n"]}
@@ -1,61 +0,0 @@
1
- import * as SDK from '../../../core/sdk/sdk.js';
2
- import type * as Protocol from '../../../generated/protocol.js';
3
- import type * as Handlers from '../handlers/handlers.js';
4
- import * as Types from '../types/types.js';
5
- export declare function clearCacheForTesting(): void;
6
- /**
7
- * Looks up the DOM Node on the page for the given BackendNodeId. Uses the
8
- * provided ParsedTrace as the cache and will cache the result after the
9
- * first lookup.
10
- */
11
- export declare function domNodeForBackendNodeID(modelData: Handlers.Types.ParsedTrace, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode | null>;
12
- /**
13
- * Extracts a set of NodeIds for a given event.
14
- * NOTE: you probably don't want to call this and instead use
15
- * `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.
16
- * This method is primarily exported so we can test the logic more easily
17
- * without having to mock the CDP layer.
18
- **/
19
- export declare function nodeIdsForEvent(modelData: Handlers.Types.ParsedTrace, event: Types.Events.Event): Set<Protocol.DOM.BackendNodeId>;
20
- /**
21
- * Looks up for backend node ids in different types of trace events
22
- * and resolves them into related DOM nodes.
23
- * This method should be progressively updated to support more events
24
- * containing node ids which we want to resolve.
25
- */
26
- export declare function extractRelatedDOMNodesFromEvent(modelData: Handlers.Types.ParsedTrace, event: Types.Events.Event): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null> | null>;
27
- /**
28
- * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.
29
- * Results are cached based on 1) the provided ParsedTrace and 2) the provided set of IDs.
30
- */
31
- export declare function domNodesForMultipleBackendNodeIds(modelData: Handlers.Types.ParsedTrace, nodeIds: Protocol.DOM.BackendNodeId[]): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode | null>>;
32
- export interface LayoutShiftSource {
33
- previousRect: DOMRect;
34
- currentRect: DOMRect;
35
- node: SDK.DOMModel.DOMNode;
36
- }
37
- /**
38
- * Calculates and returns a list of sources for a LayoutShift.
39
- * Here, a source is considered as a node that moved and contributed to the
40
- * given LayoutShift existing and the score it was given. Each source returned
41
- * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both
42
- * before and now, so we can see how this node changed and how that impacted the
43
- * layout shift.
44
- *
45
- * This data is cached based on the provided model data and the given layout
46
- * shift, so it is is safe to call multiple times with the same input.
47
- */
48
- export declare function sourcesForLayoutShift(modelData: Handlers.Types.ParsedTrace, event: Types.Events.LayoutShift): Promise<readonly LayoutShiftSource[]>;
49
- /**
50
- * Takes a LayoutShift and normalizes its node dimensions based on the device
51
- * pixel ratio (DPR) of the user's display.
52
- * This is required because the Layout Instability API is not based on CSS
53
- * pixels, but physical pixels. Therefore we need to map these to normalized CSS
54
- * pixels if we can. For example, if the user is on a device with a DPR of 2,
55
- * the values of the node dimensions reported by the Instability API need to be
56
- * divided by 2 to be accurate.
57
- * This function is safe to call multiple times as results are cached based on
58
- * the provided model data.
59
- * See https://crbug.com/1300309 for details.
60
- */
61
- export declare function normalizedImpactedNodesForLayoutShift(modelData: Handlers.Types.ParsedTrace, event: Types.Events.LayoutShift): Promise<readonly Types.Events.TraceImpactedNode[]>;
@@ -1,214 +0,0 @@
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
- import * as Types from '../types/types.js';
6
- const domLookUpSingleNodeCache = new Map();
7
- const domLookUpBatchNodesCache = new Map();
8
- export function clearCacheForTesting() {
9
- domLookUpSingleNodeCache.clear();
10
- domLookUpBatchNodesCache.clear();
11
- layoutShiftSourcesCache.clear();
12
- normalizedLayoutShiftNodesCache.clear();
13
- }
14
- /**
15
- * Looks up the DOM Node on the page for the given BackendNodeId. Uses the
16
- * provided ParsedTrace as the cache and will cache the result after the
17
- * first lookup.
18
- */
19
- export async function domNodeForBackendNodeID(modelData, nodeId) {
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;
35
- }
36
- const nodeIdsForEventCache = new WeakMap();
37
- /**
38
- * Extracts a set of NodeIds for a given event.
39
- * NOTE: you probably don't want to call this and instead use
40
- * `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.
41
- * This method is primarily exported so we can test the logic more easily
42
- * without having to mock the CDP layer.
43
- **/
44
- export function nodeIdsForEvent(modelData, event) {
45
- const fromCache = nodeIdsForEventCache.get(event);
46
- if (fromCache) {
47
- return fromCache;
48
- }
49
- const foundIds = new Set();
50
- if (Types.Events.isLayout(event)) {
51
- event.args.endData?.layoutRoots.forEach(root => foundIds.add(root.nodeId));
52
- }
53
- else if (Types.Events.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {
54
- event.args.data.impacted_nodes.forEach(node => foundIds.add(node.node_id));
55
- }
56
- else if (Types.Events.isLargestContentfulPaintCandidate(event) && typeof event.args.data?.nodeId !== 'undefined') {
57
- foundIds.add(event.args.data.nodeId);
58
- }
59
- else if (Types.Events.isPaint(event) && typeof event.args.data.nodeId !== 'undefined') {
60
- foundIds.add(event.args.data.nodeId);
61
- }
62
- else if (Types.Events.isPaintImage(event) && typeof event.args.data.nodeId !== 'undefined') {
63
- foundIds.add(event.args.data.nodeId);
64
- }
65
- else if (Types.Events.isScrollLayer(event) && typeof event.args.data.nodeId !== 'undefined') {
66
- foundIds.add(event.args.data.nodeId);
67
- }
68
- else if (Types.Events.isSyntheticAnimation(event) && typeof event.args.data.beginEvent.args.data.nodeId !== 'undefined') {
69
- foundIds.add(event.args.data.beginEvent.args.data.nodeId);
70
- }
71
- else if (Types.Events.isDecodeImage(event)) {
72
- // For a DecodeImage event, we can use the ImagePaintingHandler, which has
73
- // done the work to build the relationship between a DecodeImage event and
74
- // the corresponding PaintImage event.
75
- const paintImageEvent = modelData.ImagePainting.paintImageForEvent.get(event);
76
- if (typeof paintImageEvent?.args.data.nodeId !== 'undefined') {
77
- foundIds.add(paintImageEvent.args.data.nodeId);
78
- }
79
- }
80
- else if (Types.Events.isDrawLazyPixelRef(event) && event.args?.LazyPixelRef) {
81
- const paintImageEvent = modelData.ImagePainting.paintImageByDrawLazyPixelRef.get(event.args.LazyPixelRef);
82
- if (typeof paintImageEvent?.args.data.nodeId !== 'undefined') {
83
- foundIds.add(paintImageEvent.args.data.nodeId);
84
- }
85
- }
86
- else if (Types.Events.isParseMetaViewport(event) && typeof event.args?.data.node_id !== 'undefined') {
87
- foundIds.add(event.args.data.node_id);
88
- }
89
- nodeIdsForEventCache.set(event, foundIds);
90
- return foundIds;
91
- }
92
- /**
93
- * Looks up for backend node ids in different types of trace events
94
- * and resolves them into related DOM nodes.
95
- * This method should be progressively updated to support more events
96
- * containing node ids which we want to resolve.
97
- */
98
- export async function extractRelatedDOMNodesFromEvent(modelData, event) {
99
- const nodeIds = nodeIdsForEvent(modelData, event);
100
- if (nodeIds.size) {
101
- return await domNodesForMultipleBackendNodeIds(modelData, Array.from(nodeIds));
102
- }
103
- return null;
104
- }
105
- /**
106
- * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.
107
- * Results are cached based on 1) the provided ParsedTrace and 2) the provided set of IDs.
108
- */
109
- export async function domNodesForMultipleBackendNodeIds(modelData, nodeIds) {
110
- const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);
111
- if (fromCache) {
112
- return fromCache;
113
- }
114
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
115
- const domModel = target?.model(SDK.DOMModel.DOMModel);
116
- if (!domModel) {
117
- return new Map();
118
- }
119
- const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set(nodeIds)) || new Map();
120
- const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||
121
- new Map();
122
- cacheForModel.set(nodeIds, domNodesMap);
123
- domLookUpBatchNodesCache.set(modelData, cacheForModel);
124
- return domNodesMap;
125
- }
126
- const layoutShiftSourcesCache = new Map();
127
- const normalizedLayoutShiftNodesCache = new Map();
128
- /**
129
- * Calculates and returns a list of sources for a LayoutShift.
130
- * Here, a source is considered as a node that moved and contributed to the
131
- * given LayoutShift existing and the score it was given. Each source returned
132
- * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both
133
- * before and now, so we can see how this node changed and how that impacted the
134
- * layout shift.
135
- *
136
- * This data is cached based on the provided model data and the given layout
137
- * shift, so it is is safe to call multiple times with the same input.
138
- */
139
- export async function sourcesForLayoutShift(modelData, event) {
140
- const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);
141
- if (fromCache) {
142
- return fromCache;
143
- }
144
- const impactedNodes = event.args.data?.impacted_nodes;
145
- if (!impactedNodes) {
146
- return [];
147
- }
148
- const sources = [];
149
- await Promise.all(impactedNodes.map(async (node) => {
150
- const domNode = await domNodeForBackendNodeID(modelData, node.node_id);
151
- if (domNode) {
152
- sources.push({
153
- previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),
154
- currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),
155
- node: domNode,
156
- });
157
- }
158
- }));
159
- const cacheForModel = layoutShiftSourcesCache.get(modelData) || new Map();
160
- cacheForModel.set(event, sources);
161
- layoutShiftSourcesCache.set(modelData, cacheForModel);
162
- return sources;
163
- }
164
- /**
165
- * Takes a LayoutShift and normalizes its node dimensions based on the device
166
- * pixel ratio (DPR) of the user's display.
167
- * This is required because the Layout Instability API is not based on CSS
168
- * pixels, but physical pixels. Therefore we need to map these to normalized CSS
169
- * pixels if we can. For example, if the user is on a device with a DPR of 2,
170
- * the values of the node dimensions reported by the Instability API need to be
171
- * divided by 2 to be accurate.
172
- * This function is safe to call multiple times as results are cached based on
173
- * the provided model data.
174
- * See https://crbug.com/1300309 for details.
175
- */
176
- export async function normalizedImpactedNodesForLayoutShift(modelData, event) {
177
- const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);
178
- if (fromCache) {
179
- return fromCache;
180
- }
181
- const impactedNodes = event.args?.data?.impacted_nodes;
182
- if (!impactedNodes) {
183
- return [];
184
- }
185
- let viewportScale = null;
186
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
187
- // Get the CSS-to-physical pixel ratio of the device the inspected
188
- // target is running at.
189
- const evaluateResult = await target?.runtimeAgent().invoke_evaluate({ expression: 'window.devicePixelRatio' });
190
- if (evaluateResult?.result.type === 'number') {
191
- viewportScale = evaluateResult?.result.value ?? null;
192
- }
193
- if (!viewportScale) {
194
- // Bail and return the nodes as is.
195
- return impactedNodes;
196
- }
197
- const normalizedNodes = [];
198
- for (const impactedNode of impactedNodes) {
199
- const newNode = { ...impactedNode };
200
- for (let i = 0; i < impactedNode.old_rect.length; i++) {
201
- newNode.old_rect[i] /= viewportScale;
202
- }
203
- for (let i = 0; i < impactedNode.new_rect.length; i++) {
204
- newNode.new_rect[i] /= viewportScale;
205
- }
206
- normalizedNodes.push(newNode);
207
- }
208
- const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||
209
- new Map();
210
- cacheForModel.set(event, normalizedNodes);
211
- normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);
212
- return normalizedNodes;
213
- }
214
- //# sourceMappingURL=FetchNodes.js.map
@@ -1 +0,0 @@
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 * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nconst domLookUpSingleNodeCache =\n new Map<Handlers.Types.ParsedTrace, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\nconst domLookUpBatchNodesCache = new Map<\n Handlers.Types.ParsedTrace,\n Map<Protocol.DOM.BackendNodeId[], Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>>();\n\nexport function clearCacheForTesting(): 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 ParsedTrace as the cache and will cache the result after the\n * first lookup.\n */\nexport async function domNodeForBackendNodeID(\n modelData: Handlers.Types.ParsedTrace, 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\nconst nodeIdsForEventCache = new WeakMap<Types.Events.Event, Set<Protocol.DOM.BackendNodeId>>();\n/**\n * Extracts a set of NodeIds for a given event.\n * NOTE: you probably don't want to call this and instead use\n * `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.\n * This method is primarily exported so we can test the logic more easily\n * without having to mock the CDP layer.\n **/\nexport function nodeIdsForEvent(\n modelData: Handlers.Types.ParsedTrace,\n event: Types.Events.Event,\n ): Set<Protocol.DOM.BackendNodeId> {\n const fromCache = nodeIdsForEventCache.get(event);\n if (fromCache) {\n return fromCache;\n }\n const foundIds = new Set<Protocol.DOM.BackendNodeId>();\n\n if (Types.Events.isLayout(event)) {\n event.args.endData?.layoutRoots.forEach(root => foundIds.add(root.nodeId));\n } else if (Types.Events.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {\n event.args.data.impacted_nodes.forEach(node => foundIds.add(node.node_id));\n } else if (Types.Events.isLargestContentfulPaintCandidate(event) && typeof event.args.data?.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.Events.isPaint(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.Events.isPaintImage(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.Events.isScrollLayer(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (\n Types.Events.isSyntheticAnimation(event) && typeof event.args.data.beginEvent.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.beginEvent.args.data.nodeId);\n } else if (Types.Events.isDecodeImage(event)) {\n // For a DecodeImage event, we can use the ImagePaintingHandler, which has\n // done the work to build the relationship between a DecodeImage event and\n // the corresponding PaintImage event.\n const paintImageEvent = modelData.ImagePainting.paintImageForEvent.get(event);\n if (typeof paintImageEvent?.args.data.nodeId !== 'undefined') {\n foundIds.add(paintImageEvent.args.data.nodeId);\n }\n } else if (Types.Events.isDrawLazyPixelRef(event) && event.args?.LazyPixelRef) {\n const paintImageEvent = modelData.ImagePainting.paintImageByDrawLazyPixelRef.get(event.args.LazyPixelRef);\n if (typeof paintImageEvent?.args.data.nodeId !== 'undefined') {\n foundIds.add(paintImageEvent.args.data.nodeId);\n }\n } else if (Types.Events.isParseMetaViewport(event) && typeof event.args?.data.node_id !== 'undefined') {\n foundIds.add(event.args.data.node_id);\n }\n nodeIdsForEventCache.set(event, foundIds);\n return foundIds;\n}\n\n/**\n * Looks up for backend node ids in different types of trace events\n * and resolves them into related DOM nodes.\n * This method should be progressively updated to support more events\n * containing node ids which we want to resolve.\n */\nexport async function extractRelatedDOMNodesFromEvent(modelData: Handlers.Types.ParsedTrace, event: Types.Events.Event):\n Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>|null> {\n const nodeIds = nodeIdsForEvent(modelData, event);\n if (nodeIds.size) {\n return await domNodesForMultipleBackendNodeIds(modelData, Array.from(nodeIds));\n }\n return null;\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 ParsedTrace and 2) the provided set of IDs.\n */\nexport async function domNodesForMultipleBackendNodeIds(\n modelData: Handlers.Types.ParsedTrace,\n nodeIds: 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(new Set(nodeIds)) || new Map();\n\n const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||\n new Map<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 =\n new Map<Handlers.Types.ParsedTrace, Map<Types.Events.LayoutShift, readonly LayoutShiftSource[]>>();\n\nconst normalizedLayoutShiftNodesCache =\n new Map<Handlers.Types.ParsedTrace, Map<Types.Events.LayoutShift, readonly Types.Events.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.ParsedTrace, event: Types.Events.LayoutShift): 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.Events.LayoutShift, 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.ParsedTrace,\n event: Types.Events.LayoutShift): Promise<readonly Types.Events.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.Events.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.Events.LayoutShift, readonly Types.Events.TraceImpactedNode[]>();\n cacheForModel.set(event, normalizedNodes);\n normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);\n\n return normalizedNodes;\n}\n"]}
@@ -1,3 +0,0 @@
1
- // import type * as CrUXManager from '../../crux-manager/crux-manager.js';
2
- import * as Types from '../types/types.js';
3
- export declare function forNewRecording(isCpuProfile: boolean, recordStartTime?: number, emulatedDeviceTitle?: string, cruxFieldData?: any[]): Promise<Types.File.MetaData>;
@@ -1,71 +0,0 @@
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
- import * as Types from '../types/types.js';
6
- export async function forNewRecording(isCpuProfile, recordStartTime, emulatedDeviceTitle, cruxFieldData) {
7
- try {
8
- if (isCpuProfile) {
9
- // For CPU profile, only specify data origin
10
- return {
11
- dataOrigin: "CPUProfile" /* Types.File.DataOrigin.CPU_PROFILE */,
12
- };
13
- }
14
- const cpuThrottlingManager = SDK.CPUThrottlingManager.CPUThrottlingManager.instance();
15
- // If the CPU Throttling manager has yet to have its primary page target
16
- // set, it will block on the call to get the current hardware concurrency
17
- // until it does. At this point where the user has recorded a trace, that
18
- // target should have been set. So if it doesn't have it set, we instead
19
- // just bail and don't store the hardware concurrency (this is only
20
- // metadata, not mission critical information).
21
- // We also race this call against a 1s timeout, because sometimes this call
22
- // can hang (unsure exactly why) and we do not want to block parsing for
23
- // too long as a result.
24
- function getConcurrencyOrTimeout() {
25
- return Promise.race([
26
- SDK.CPUThrottlingManager.CPUThrottlingManager.instance().getHardwareConcurrency(),
27
- new Promise(resolve => {
28
- setTimeout(() => resolve(undefined), 1_000);
29
- }),
30
- ]);
31
- }
32
- const hardwareConcurrency = cpuThrottlingManager.hasPrimaryPageTargetSet() ? await getConcurrencyOrTimeout() : undefined;
33
- const cpuThrottling = SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate();
34
- const networkConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().isThrottling() ?
35
- SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions() :
36
- undefined;
37
- let networkThrottlingConditions;
38
- let networkTitle;
39
- if (networkConditions) {
40
- networkThrottlingConditions = {
41
- download: networkConditions.download,
42
- upload: networkConditions.upload,
43
- latency: networkConditions.latency,
44
- packetLoss: networkConditions.packetLoss,
45
- packetQueueLength: networkConditions.packetQueueLength,
46
- packetReordering: networkConditions.packetReordering,
47
- targetLatency: networkConditions.targetLatency,
48
- };
49
- networkTitle =
50
- typeof networkConditions.title === 'function' ? networkConditions.title() : networkConditions.title;
51
- }
52
- return {
53
- source: 'DevTools',
54
- startTime: recordStartTime ? new Date(recordStartTime).toJSON() : undefined, // ISO-8601 timestamp
55
- emulatedDeviceTitle,
56
- cpuThrottling: cpuThrottling !== 1 ? cpuThrottling : undefined,
57
- networkThrottling: networkTitle,
58
- networkThrottlingConditions,
59
- hardwareConcurrency,
60
- dataOrigin: "TraceEvents" /* Types.File.DataOrigin.TRACE_EVENTS */,
61
- cruxFieldData,
62
- };
63
- }
64
- catch {
65
- // If anything went wrong, it does not really matter. The impact is that we
66
- // will not save the metadata when we save the trace to disk, but that is
67
- // not really important, so just return empty object and move on
68
- return {};
69
- }
70
- }
71
- //# sourceMappingURL=Metadata.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Metadata.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/Metadata.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAEhD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,YAAqB,EAAE,eAAwB,EAAE,mBAA4B,EAC7E,aAAwC;IAC1C,IAAI,CAAC;QACH,IAAI,YAAY,EAAE,CAAC;YACjB,4CAA4C;YAC5C,OAAO;gBACL,UAAU,sDAAmC;aAC9C,CAAC;QACJ,CAAC;QACD,MAAM,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC;QAEtF,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,+CAA+C;QAC/C,2EAA2E;QAC3E,wEAAwE;QACxE,wBAAwB;QACxB,SAAS,uBAAuB;YAC9B,OAAO,OAAO,CAAC,IAAI,CAAC;gBAClB,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC,sBAAsB,EAAE;gBACjF,IAAI,OAAO,CAAY,OAAO,CAAC,EAAE;oBAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC9C,CAAC,CAAC;aACH,CAAC,CAAC;QACL,CAAC;QAED,MAAM,mBAAmB,GACrB,oBAAoB,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC,MAAM,uBAAuB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,MAAM,aAAa,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QACnG,MAAM,iBAAiB,GAAG,GAAG,CAAC,cAAc,CAAC,yBAAyB,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;YAC9F,GAAG,CAAC,cAAc,CAAC,yBAAyB,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;YAC7E,SAAS,CAAC;QAEd,IAAI,2BAA2B,CAAC;QAChC,IAAI,YAAY,CAAC;QACjB,IAAI,iBAAiB,EAAE,CAAC;YACtB,2BAA2B,GAAG;gBAC5B,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;gBACpC,MAAM,EAAE,iBAAiB,CAAC,MAAM;gBAChC,OAAO,EAAE,iBAAiB,CAAC,OAAO;gBAClC,UAAU,EAAE,iBAAiB,CAAC,UAAU;gBACxC,iBAAiB,EAAE,iBAAiB,CAAC,iBAAiB;gBACtD,gBAAgB,EAAE,iBAAiB,CAAC,gBAAgB;gBACpD,aAAa,EAAE,iBAAiB,CAAC,aAAa;aAC/C,CAAC;YACF,YAAY;gBACR,OAAO,iBAAiB,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAC1G,CAAC;QAED,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,EAAG,qBAAqB;YACnG,mBAAmB;YACnB,aAAa,EAAE,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;YAC9D,iBAAiB,EAAE,YAAY;YAC/B,2BAA2B;YAC3B,mBAAmB;YACnB,UAAU,wDAAoC;YAC9C,aAAa;SACd,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,yEAAyE;QACzE,gEAAgE;QAChE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,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 SDK from '../../../core/sdk/sdk.js';\nimport type * as CrUXManager from '../../crux-manager/crux-manager.js';\nimport * as Types from '../types/types.js';\n\nexport async function forNewRecording(\n isCpuProfile: boolean, recordStartTime?: number, emulatedDeviceTitle?: string,\n cruxFieldData?: CrUXManager.PageResult[]): Promise<Types.File.MetaData> {\n try {\n if (isCpuProfile) {\n // For CPU profile, only specify data origin\n return {\n dataOrigin: Types.File.DataOrigin.CPU_PROFILE,\n };\n }\n const cpuThrottlingManager = SDK.CPUThrottlingManager.CPUThrottlingManager.instance();\n\n // If the CPU Throttling manager has yet to have its primary page target\n // set, it will block on the call to get the current hardware concurrency\n // until it does. At this point where the user has recorded a trace, that\n // target should have been set. So if it doesn't have it set, we instead\n // just bail and don't store the hardware concurrency (this is only\n // metadata, not mission critical information).\n // We also race this call against a 1s timeout, because sometimes this call\n // can hang (unsure exactly why) and we do not want to block parsing for\n // too long as a result.\n function getConcurrencyOrTimeout(): Promise<number|undefined> {\n return Promise.race([\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().getHardwareConcurrency(),\n new Promise<undefined>(resolve => {\n setTimeout(() => resolve(undefined), 1_000);\n }),\n ]);\n }\n\n const hardwareConcurrency =\n cpuThrottlingManager.hasPrimaryPageTargetSet() ? await getConcurrencyOrTimeout() : undefined;\n const cpuThrottling = SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate();\n const networkConditions = SDK.NetworkManager.MultitargetNetworkManager.instance().isThrottling() ?\n SDK.NetworkManager.MultitargetNetworkManager.instance().networkConditions() :\n undefined;\n\n let networkThrottlingConditions;\n let networkTitle;\n if (networkConditions) {\n networkThrottlingConditions = {\n download: networkConditions.download,\n upload: networkConditions.upload,\n latency: networkConditions.latency,\n packetLoss: networkConditions.packetLoss,\n packetQueueLength: networkConditions.packetQueueLength,\n packetReordering: networkConditions.packetReordering,\n targetLatency: networkConditions.targetLatency,\n };\n networkTitle =\n typeof networkConditions.title === 'function' ? networkConditions.title() : networkConditions.title;\n }\n\n return {\n source: 'DevTools',\n startTime: recordStartTime ? new Date(recordStartTime).toJSON() : undefined, // ISO-8601 timestamp\n emulatedDeviceTitle,\n cpuThrottling: cpuThrottling !== 1 ? cpuThrottling : undefined,\n networkThrottling: networkTitle,\n networkThrottlingConditions,\n hardwareConcurrency,\n dataOrigin: Types.File.DataOrigin.TRACE_EVENTS,\n cruxFieldData,\n };\n } catch {\n // If anything went wrong, it does not really matter. The impact is that we\n // will not save the metadata when we save the trace to disk, but that is\n // not really important, so just return empty object and move on\n return {};\n }\n}\n"]}