@paulirish/trace_engine 0.0.51 → 0.0.52

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 (79) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/core/platform/StringUtilities.js +4 -1
  3. package/core/platform/StringUtilities.js.map +1 -1
  4. package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  5. package/core/platform/platform-tsconfig.json +1 -1
  6. package/generated/protocol.d.ts +150 -31
  7. package/locales/en-US.json +3 -0
  8. package/locales/en-XL.json +3 -0
  9. package/models/cpu_profile/cpu_profile-tsconfig.json +1 -1
  10. package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  11. package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  12. package/models/trace/extras/ScriptDuplication.d.ts +5 -2
  13. package/models/trace/extras/ScriptDuplication.js +4 -2
  14. package/models/trace/extras/ScriptDuplication.js.map +1 -1
  15. package/models/trace/extras/StackTraceForEvent.js +80 -47
  16. package/models/trace/extras/StackTraceForEvent.js.map +1 -1
  17. package/models/trace/extras/ThirdParties.d.ts +13 -12
  18. package/models/trace/extras/ThirdParties.js +50 -19
  19. package/models/trace/extras/ThirdParties.js.map +1 -1
  20. package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  21. package/models/trace/extras/extras-tsconfig.json +1 -1
  22. package/models/trace/extras/extras.d.ts +98 -6
  23. package/models/trace/extras/extras.js +98 -6
  24. package/models/trace/handlers/AsyncJSCallsHandler.d.ts +5 -0
  25. package/models/trace/handlers/AsyncJSCallsHandler.js +12 -9
  26. package/models/trace/handlers/AsyncJSCallsHandler.js.map +1 -1
  27. package/models/trace/handlers/ScreenshotsHandler.js +1 -0
  28. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  29. package/models/trace/handlers/ScriptsHandler.js +9 -3
  30. package/models/trace/handlers/ScriptsHandler.js.map +1 -1
  31. package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  32. package/models/trace/handlers/handlers-tsconfig.json +1 -1
  33. package/models/trace/handlers/helpers.js +9 -0
  34. package/models/trace/handlers/helpers.js.map +1 -1
  35. package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  36. package/models/trace/helpers/helpers-tsconfig.json +1 -1
  37. package/models/trace/insights/CLSCulprits.d.ts +6 -1
  38. package/models/trace/insights/CLSCulprits.js +11 -2
  39. package/models/trace/insights/CLSCulprits.js.map +1 -1
  40. package/models/trace/insights/Cache.d.ts +0 -1
  41. package/models/trace/insights/Cache.js +1 -1
  42. package/models/trace/insights/Cache.js.map +1 -1
  43. package/models/trace/insights/Common.js +3 -0
  44. package/models/trace/insights/Common.js.map +1 -1
  45. package/models/trace/insights/DocumentLatency.js +1 -0
  46. package/models/trace/insights/DocumentLatency.js.map +1 -1
  47. package/models/trace/insights/DuplicatedJavaScript.js +9 -3
  48. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
  49. package/models/trace/insights/ImageDelivery.d.ts +0 -1
  50. package/models/trace/insights/ImageDelivery.js +1 -1
  51. package/models/trace/insights/ImageDelivery.js.map +1 -1
  52. package/models/trace/insights/LegacyJavaScript.js +5 -2
  53. package/models/trace/insights/LegacyJavaScript.js.map +1 -1
  54. package/models/trace/insights/ThirdParties.d.ts +1 -1
  55. package/models/trace/insights/ThirdParties.js +6 -6
  56. package/models/trace/insights/ThirdParties.js.map +1 -1
  57. package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  58. package/models/trace/insights/insights-tsconfig.json +1 -1
  59. package/models/trace/insights/types.d.ts +9 -0
  60. package/models/trace/insights/types.js.map +1 -1
  61. package/models/trace/lantern/core/core-tsconfig.json +1 -1
  62. package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  63. package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  64. package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  65. package/models/trace/lantern/graph/graph-tsconfig.json +1 -1
  66. package/models/trace/lantern/lantern-tsconfig.json +1 -1
  67. package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  68. package/models/trace/lantern/metrics/metrics-tsconfig.json +1 -1
  69. package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  70. package/models/trace/lantern/simulation/simulation-tsconfig.json +1 -1
  71. package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  72. package/models/trace/lantern/types/types-tsconfig.json +1 -1
  73. package/models/trace/trace-tsconfig.json +1 -1
  74. package/models/trace/types/TraceEvents.d.ts +2 -4
  75. package/models/trace/types/TraceEvents.js.map +1 -1
  76. package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +1 -1
  77. package/models/trace/types/types-tsconfig.json +1 -1
  78. package/package.json +1 -1
  79. package/test/test-trace-engine.mjs +2 -2
@@ -1,6 +1,7 @@
1
1
  // Copyright 2024 The Chromium Authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
+ import * as Helpers from '../helpers/helpers.js';
4
5
  import * as Types from '../types/types.js';
5
6
  export const stackTraceForEventInTrace = new Map();
6
7
  export function clearCacheForTrace(parsedTrace) {
@@ -23,20 +24,23 @@ export function get(event, parsedTrace) {
23
24
  return resultFromCache;
24
25
  }
25
26
  let result = null;
26
- if (Types.Events.isProfileCall(event)) {
27
- result = getForProfileCall(event, parsedTrace);
28
- }
29
- else if (Types.Extensions.isSyntheticExtensionEntry(event)) {
27
+ if (Types.Extensions.isSyntheticExtensionEntry(event)) {
30
28
  result = getForExtensionEntry(event, parsedTrace);
31
29
  }
32
- else if (Types.Events.isUserTiming(event)) {
33
- result = getForUserTiming(event, parsedTrace);
30
+ else if (Types.Events.isPerformanceMeasureBegin(event)) {
31
+ result = getForPerformanceMeasure(event, parsedTrace);
34
32
  }
35
- else if (Types.Events.isLayout(event) || Types.Events.isUpdateLayoutTree(event)) {
36
- const node = parsedTrace.Renderer.entryToNode.get(event);
37
- const parent = node?.parent?.entry;
38
- if (parent) {
39
- result = get(parent, parsedTrace);
33
+ else {
34
+ result = getForEvent(event, parsedTrace);
35
+ const maybeProtocolCallFrame = getPayloadStackAsProtocolCallFrame(event);
36
+ if (result && maybeProtocolCallFrame && !isNativeJSFunction(maybeProtocolCallFrame)) {
37
+ // If the event has a payload stack trace, replace the top frame
38
+ // of the calculated stack with the top frame of the payload stack
39
+ // because trace payload call frames contain call locations, unlike
40
+ // profile call frames (which contain function declaration locations).
41
+ // This way the user knows which exact JS location triggered an
42
+ // event.
43
+ result.callFrames[0] = maybeProtocolCallFrame;
40
44
  }
41
45
  }
42
46
  if (result) {
@@ -44,21 +48,36 @@ export function get(event, parsedTrace) {
44
48
  }
45
49
  return result;
46
50
  }
47
- function getForProfileCall(event, parsedTrace) {
51
+ /**
52
+ * Fallback method to obtain a stack trace using the parsed event tree
53
+ * hierarchy. This shouldn't be called outside of this file, use `get`
54
+ * instead to ensure the correct event in the tree hierarchy is used.
55
+ */
56
+ function getForEvent(event, parsedTrace) {
48
57
  // When working with a CPU profile the renderer handler won't have
49
58
  // entries in its tree.
50
59
  const entryToNode = parsedTrace.Renderer.entryToNode.size > 0 ? parsedTrace.Renderer.entryToNode : parsedTrace.Samples.entryToNode;
51
60
  const topStackTrace = { callFrames: [] };
52
61
  let stackTrace = topStackTrace;
53
- let currentEntry = event;
62
+ let currentEntry;
54
63
  let node = entryToNode.get(event);
55
64
  const traceCache = stackTraceForEventInTrace.get(parsedTrace) || new Map();
56
65
  stackTraceForEventInTrace.set(parsedTrace, traceCache);
57
- // Move up this node's ancestor tree appending frames to its
58
- // stack trace.
66
+ // Move up this node's ancestor tree appending JS frames to its
67
+ // stack trace. If an async caller is detected, move up in the async
68
+ // stack instead.
59
69
  while (node) {
60
70
  if (!Types.Events.isProfileCall(node.entry)) {
61
- node = node.parent;
71
+ const maybeAsyncParent = parsedTrace.AsyncJSCalls.runEntryPointToScheduler.get(node.entry);
72
+ if (!maybeAsyncParent) {
73
+ node = node.parent;
74
+ continue;
75
+ }
76
+ const maybeAsyncParentNode = maybeAsyncParent && entryToNode.get(maybeAsyncParent.scheduler);
77
+ if (maybeAsyncParentNode) {
78
+ stackTrace = addAsyncParentToStack(stackTrace, maybeAsyncParent.taskName);
79
+ node = maybeAsyncParentNode;
80
+ }
62
81
  continue;
63
82
  }
64
83
  currentEntry = node.entry;
@@ -83,18 +102,7 @@ function getForProfileCall(event, parsedTrace) {
83
102
  const maybeAsyncParentEvent = parsedTrace.AsyncJSCalls.asyncCallToScheduler.get(currentEntry);
84
103
  const maybeAsyncParentNode = maybeAsyncParentEvent && entryToNode.get(maybeAsyncParentEvent.scheduler);
85
104
  if (maybeAsyncParentNode) {
86
- // The Protocol.Runtime.StackTrace type is recursive, so we
87
- // move one level deeper in it as we walk up the ancestor tree.
88
- stackTrace.parent = { callFrames: [] };
89
- stackTrace = stackTrace.parent;
90
- // Note: this description effectively corresponds to the name
91
- // of the task that scheduled the stack trace we are jumping
92
- // FROM, so it would make sense that it was set to that stack
93
- // trace instead of the one we are jumping TO. However, the
94
- // JS presentation utils we use to present async stack traces
95
- // assume the description is added to the stack trace that
96
- // scheduled the async task, so we build the data that way.
97
- stackTrace.description = maybeAsyncParentEvent.taskName;
105
+ stackTrace = addAsyncParentToStack(stackTrace, maybeAsyncParentEvent.taskName);
98
106
  node = maybeAsyncParentNode;
99
107
  continue;
100
108
  }
@@ -102,39 +110,54 @@ function getForProfileCall(event, parsedTrace) {
102
110
  }
103
111
  return topStackTrace;
104
112
  }
113
+ function addAsyncParentToStack(stackTrace, taskName) {
114
+ const parent = { callFrames: [] };
115
+ // The Protocol.Runtime.StackTrace type is recursive, so we
116
+ // move one level deeper in it as we walk up the ancestor tree.
117
+ stackTrace.parent = parent;
118
+ // Note: this description effectively corresponds to the name
119
+ // of the task that scheduled the stack trace we are jumping
120
+ // FROM, so it would make sense that it was set to that stack
121
+ // trace instead of the one we are jumping TO. However, the
122
+ // JS presentation utils we use to present async stack traces
123
+ // assume the description is added to the stack trace that
124
+ // scheduled the async task, so we build the data that way.
125
+ parent.description = taskName;
126
+ return parent;
127
+ }
105
128
  /**
106
129
  * Finds the JS call in which an extension entry was injected (the
107
130
  * code location that called the extension API), and returns its stack
108
131
  * trace.
109
132
  */
110
133
  function getForExtensionEntry(event, parsedTrace) {
111
- return getForUserTiming(event.rawSourceEvent, parsedTrace);
134
+ const rawEvent = event.rawSourceEvent;
135
+ if (Types.Events.isPerformanceMeasureBegin(rawEvent)) {
136
+ return getForPerformanceMeasure(rawEvent, parsedTrace);
137
+ }
138
+ if (!rawEvent) {
139
+ return null;
140
+ }
141
+ return get(rawEvent, parsedTrace);
112
142
  }
113
143
  /**
114
- * Finds the JS call in which the user timing API was called and returns
115
- * its stack trace.
144
+ * Gets the raw event for a user timing and obtains its stack trace.
116
145
  */
117
- function getForUserTiming(event, parsedTrace) {
146
+ function getForPerformanceMeasure(event, parsedTrace) {
118
147
  let rawEvent = event;
119
- if (Types.Events.isPerformanceMeasureBegin(event)) {
120
- if (event.args.traceId === undefined) {
121
- return null;
122
- }
123
- rawEvent = parsedTrace.UserTimings.measureTraceByTraceId.get(event.args.traceId);
148
+ if (event.args.traceId === undefined) {
149
+ return null;
124
150
  }
151
+ // performance.measure calls dispatch 2 events: one for the call
152
+ // itself and another to represent the measured entry in the trace
153
+ // timeline. They are connected via a common traceId. At this
154
+ // point `rawEvent` corresponds to the second case, we must
155
+ // encounter the event for the call itself to obtain its callstack.
156
+ rawEvent = parsedTrace.UserTimings.measureTraceByTraceId.get(event.args.traceId);
125
157
  if (!rawEvent) {
126
158
  return null;
127
159
  }
128
- // Look for the nearest profile call ancestor of the event tracing
129
- // the call to the API.
130
- let node = parsedTrace.Renderer.entryToNode.get(rawEvent);
131
- while (node && !Types.Events.isProfileCall(node.entry)) {
132
- node = node.parent;
133
- }
134
- if (node && Types.Events.isProfileCall(node.entry)) {
135
- return get(node.entry, parsedTrace);
136
- }
137
- return null;
160
+ return get(rawEvent, parsedTrace);
138
161
  }
139
162
  /**
140
163
  * Determines if a function is a native JS API (like setTimeout,
@@ -148,4 +171,14 @@ function getForUserTiming(event, parsedTrace) {
148
171
  function isNativeJSFunction({ columnNumber, lineNumber, url, scriptId }) {
149
172
  return lineNumber === -1 && columnNumber === -1 && url === '' && scriptId === '0';
150
173
  }
174
+ /**
175
+ * Extracts the top frame in the stack contained in a trace event's payload
176
+ * (if any) and casts it as a Protocol.Runtime.CallFrame.
177
+ */
178
+ function getPayloadStackAsProtocolCallFrame(event) {
179
+ const maybeCallStack = Helpers.Trace.getZeroIndexedStackTraceInEventPayload(event);
180
+ const maybeCallFrame = maybeCallStack?.at(0);
181
+ const maybeProtocolCallFrame = maybeCallFrame && { ...maybeCallFrame, scriptId: String(maybeCallFrame.scriptId) };
182
+ return maybeProtocolCallFrame || null;
183
+ }
151
184
  //# sourceMappingURL=StackTraceForEvent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackTraceForEvent.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/StackTraceForEvent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nexport const stackTraceForEventInTrace =\n new Map<Handlers.Types.ParsedTrace, Map<Types.Events.Event, Protocol.Runtime.StackTrace>>();\n\nexport function clearCacheForTrace(parsedTrace: Handlers.Types.ParsedTrace): void {\n stackTraceForEventInTrace.delete(parsedTrace);\n}\n/**\n * This util builds a stack trace that includes async calls for a given\n * event. It leverages data we collect from sampling to deduce sync\n * stacks and trace event instrumentation on the V8 debugger to stitch\n * them together.\n */\nexport function get(event: Types.Events.Event, parsedTrace: Handlers.Types.ParsedTrace): Protocol.Runtime.StackTrace|\n null {\n let cacheForTrace = stackTraceForEventInTrace.get(parsedTrace);\n if (!cacheForTrace) {\n cacheForTrace = new Map();\n stackTraceForEventInTrace.set(parsedTrace, cacheForTrace);\n }\n const resultFromCache = cacheForTrace.get(event);\n if (resultFromCache) {\n return resultFromCache;\n }\n let result: Protocol.Runtime.StackTrace|null = null;\n if (Types.Events.isProfileCall(event)) {\n result = getForProfileCall(event, parsedTrace);\n } else if (Types.Extensions.isSyntheticExtensionEntry(event)) {\n result = getForExtensionEntry(event, parsedTrace);\n } else if (Types.Events.isUserTiming(event)) {\n result = getForUserTiming(event, parsedTrace);\n } else if (Types.Events.isLayout(event) || Types.Events.isUpdateLayoutTree(event)) {\n const node = parsedTrace.Renderer.entryToNode.get(event);\n const parent = node?.parent?.entry;\n if (parent) {\n result = get(parent, parsedTrace);\n }\n }\n if (result) {\n cacheForTrace.set(event, result);\n }\n return result;\n}\n\nfunction getForProfileCall(\n event: Types.Events.SyntheticProfileCall, parsedTrace: Handlers.Types.ParsedTrace): Protocol.Runtime.StackTrace {\n // When working with a CPU profile the renderer handler won't have\n // entries in its tree.\n const entryToNode =\n parsedTrace.Renderer.entryToNode.size > 0 ? parsedTrace.Renderer.entryToNode : parsedTrace.Samples.entryToNode;\n const topStackTrace: Protocol.Runtime.StackTrace = {callFrames: []};\n let stackTrace: Protocol.Runtime.StackTrace = topStackTrace;\n let currentEntry = event;\n let node: Helpers.TreeHelpers.TraceEntryNode|null|undefined = entryToNode.get(event);\n const traceCache =\n stackTraceForEventInTrace.get(parsedTrace) || new Map<Types.Events.Event, Protocol.Runtime.StackTrace>();\n stackTraceForEventInTrace.set(parsedTrace, traceCache);\n // Move up this node's ancestor tree appending frames to its\n // stack trace.\n while (node) {\n if (!Types.Events.isProfileCall(node.entry)) {\n node = node.parent;\n continue;\n }\n\n currentEntry = node.entry;\n // First check if this entry was processed before.\n const stackTraceFromCache = traceCache.get(node.entry);\n if (stackTraceFromCache) {\n stackTrace.callFrames.push(...stackTraceFromCache.callFrames.filter(callFrame => !isNativeJSFunction(callFrame)));\n stackTrace.parent = stackTraceFromCache.parent;\n // Only set the description to the cache value if we didn't\n // compute it in the previous iteration, since the async stack\n // trace descriptions / taskNames is only extracted when jumping\n // to the async parent, and that might not have happened when\n // the cached value was computed (e.g. the cached value\n // computation started at some point inside the parent stack\n // trace).\n stackTrace.description = stackTrace.description || stackTraceFromCache.description;\n break;\n }\n\n if (!isNativeJSFunction(currentEntry.callFrame)) {\n stackTrace.callFrames.push(currentEntry.callFrame);\n }\n const maybeAsyncParentEvent = parsedTrace.AsyncJSCalls.asyncCallToScheduler.get(currentEntry);\n const maybeAsyncParentNode = maybeAsyncParentEvent && entryToNode.get(maybeAsyncParentEvent.scheduler);\n if (maybeAsyncParentNode) {\n // The Protocol.Runtime.StackTrace type is recursive, so we\n // move one level deeper in it as we walk up the ancestor tree.\n stackTrace.parent = {callFrames: []};\n stackTrace = stackTrace.parent;\n // Note: this description effectively corresponds to the name\n // of the task that scheduled the stack trace we are jumping\n // FROM, so it would make sense that it was set to that stack\n // trace instead of the one we are jumping TO. However, the\n // JS presentation utils we use to present async stack traces\n // assume the description is added to the stack trace that\n // scheduled the async task, so we build the data that way.\n stackTrace.description = maybeAsyncParentEvent.taskName;\n node = maybeAsyncParentNode;\n continue;\n }\n node = node.parent;\n }\n return topStackTrace;\n}\n\n/**\n * Finds the JS call in which an extension entry was injected (the\n * code location that called the extension API), and returns its stack\n * trace.\n */\nfunction getForExtensionEntry(event: Types.Extensions.SyntheticExtensionEntry, parsedTrace: Handlers.Types.ParsedTrace):\n Protocol.Runtime.StackTrace|null {\n return getForUserTiming(event.rawSourceEvent, parsedTrace);\n}\n\n/**\n * Finds the JS call in which the user timing API was called and returns\n * its stack trace.\n */\nfunction getForUserTiming(\n event: Types.Events.UserTiming|Types.Events.ConsoleTimeStamp,\n parsedTrace: Handlers.Types.ParsedTrace): Protocol.Runtime.StackTrace|null {\n let rawEvent: Types.Events.Event|undefined = event;\n if (Types.Events.isPerformanceMeasureBegin(event)) {\n if (event.args.traceId === undefined) {\n return null;\n }\n rawEvent = parsedTrace.UserTimings.measureTraceByTraceId.get(event.args.traceId);\n }\n if (!rawEvent) {\n return null;\n }\n // Look for the nearest profile call ancestor of the event tracing\n // the call to the API.\n let node: Helpers.TreeHelpers.TraceEntryNode|undefined|null = parsedTrace.Renderer.entryToNode.get(rawEvent);\n while (node && !Types.Events.isProfileCall(node.entry)) {\n node = node.parent;\n }\n if (node && Types.Events.isProfileCall(node.entry)) {\n return get(node.entry, parsedTrace);\n }\n return null;\n}\n/**\n * Determines if a function is a native JS API (like setTimeout,\n * requestAnimationFrame, consoleTask.run. etc.). This is useful to\n * discard stack frames corresponding to the JS scheduler function\n * itself, since it's already being used as title of async stack traces\n * taken from the async `taskName`. This is also consistent with the\n * behaviour of the stack trace in the sources\n * panel.\n */\nfunction isNativeJSFunction({columnNumber, lineNumber, url, scriptId}: Protocol.Runtime.CallFrame): boolean {\n return lineNumber === -1 && columnNumber === -1 && url === '' && scriptId === '0';\n}\n"]}
1
+ {"version":3,"file":"StackTraceForEvent.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/StackTraceForEvent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nexport const stackTraceForEventInTrace =\n new Map<Handlers.Types.ParsedTrace, Map<Types.Events.Event, Protocol.Runtime.StackTrace>>();\n\nexport function clearCacheForTrace(parsedTrace: Handlers.Types.ParsedTrace): void {\n stackTraceForEventInTrace.delete(parsedTrace);\n}\n/**\n * This util builds a stack trace that includes async calls for a given\n * event. It leverages data we collect from sampling to deduce sync\n * stacks and trace event instrumentation on the V8 debugger to stitch\n * them together.\n */\nexport function get(event: Types.Events.Event, parsedTrace: Handlers.Types.ParsedTrace): Protocol.Runtime.StackTrace|\n null {\n let cacheForTrace = stackTraceForEventInTrace.get(parsedTrace);\n if (!cacheForTrace) {\n cacheForTrace = new Map();\n stackTraceForEventInTrace.set(parsedTrace, cacheForTrace);\n }\n const resultFromCache = cacheForTrace.get(event);\n if (resultFromCache) {\n return resultFromCache;\n }\n let result: Protocol.Runtime.StackTrace|null = null;\n if (Types.Extensions.isSyntheticExtensionEntry(event)) {\n result = getForExtensionEntry(event, parsedTrace);\n } else if (Types.Events.isPerformanceMeasureBegin(event)) {\n result = getForPerformanceMeasure(event, parsedTrace);\n } else {\n result = getForEvent(event, parsedTrace);\n const maybeProtocolCallFrame = getPayloadStackAsProtocolCallFrame(event);\n if (result && maybeProtocolCallFrame && !isNativeJSFunction(maybeProtocolCallFrame)) {\n // If the event has a payload stack trace, replace the top frame\n // of the calculated stack with the top frame of the payload stack\n // because trace payload call frames contain call locations, unlike\n // profile call frames (which contain function declaration locations).\n // This way the user knows which exact JS location triggered an\n // event.\n result.callFrames[0] = maybeProtocolCallFrame;\n }\n }\n if (result) {\n cacheForTrace.set(event, result);\n }\n return result;\n}\n\n/**\n * Fallback method to obtain a stack trace using the parsed event tree\n * hierarchy. This shouldn't be called outside of this file, use `get`\n * instead to ensure the correct event in the tree hierarchy is used.\n */\nfunction getForEvent(event: Types.Events.Event, parsedTrace: Handlers.Types.ParsedTrace): Protocol.Runtime.StackTrace {\n // When working with a CPU profile the renderer handler won't have\n // entries in its tree.\n const entryToNode =\n parsedTrace.Renderer.entryToNode.size > 0 ? parsedTrace.Renderer.entryToNode : parsedTrace.Samples.entryToNode;\n const topStackTrace: Protocol.Runtime.StackTrace = {callFrames: []};\n let stackTrace: Protocol.Runtime.StackTrace = topStackTrace;\n let currentEntry: Types.Events.SyntheticProfileCall;\n let node: Helpers.TreeHelpers.TraceEntryNode|null|undefined = entryToNode.get(event);\n const traceCache =\n stackTraceForEventInTrace.get(parsedTrace) || new Map<Types.Events.Event, Protocol.Runtime.StackTrace>();\n stackTraceForEventInTrace.set(parsedTrace, traceCache);\n // Move up this node's ancestor tree appending JS frames to its\n // stack trace. If an async caller is detected, move up in the async\n // stack instead.\n while (node) {\n if (!Types.Events.isProfileCall(node.entry)) {\n const maybeAsyncParent = parsedTrace.AsyncJSCalls.runEntryPointToScheduler.get(node.entry);\n if (!maybeAsyncParent) {\n node = node.parent;\n continue;\n }\n const maybeAsyncParentNode = maybeAsyncParent && entryToNode.get(maybeAsyncParent.scheduler);\n if (maybeAsyncParentNode) {\n stackTrace = addAsyncParentToStack(stackTrace, maybeAsyncParent.taskName);\n node = maybeAsyncParentNode;\n }\n continue;\n }\n currentEntry = node.entry;\n // First check if this entry was processed before.\n const stackTraceFromCache = traceCache.get(node.entry);\n if (stackTraceFromCache) {\n stackTrace.callFrames.push(...stackTraceFromCache.callFrames.filter(callFrame => !isNativeJSFunction(callFrame)));\n stackTrace.parent = stackTraceFromCache.parent;\n // Only set the description to the cache value if we didn't\n // compute it in the previous iteration, since the async stack\n // trace descriptions / taskNames is only extracted when jumping\n // to the async parent, and that might not have happened when\n // the cached value was computed (e.g. the cached value\n // computation started at some point inside the parent stack\n // trace).\n stackTrace.description = stackTrace.description || stackTraceFromCache.description;\n break;\n }\n\n if (!isNativeJSFunction(currentEntry.callFrame)) {\n stackTrace.callFrames.push(currentEntry.callFrame);\n }\n const maybeAsyncParentEvent = parsedTrace.AsyncJSCalls.asyncCallToScheduler.get(currentEntry);\n const maybeAsyncParentNode = maybeAsyncParentEvent && entryToNode.get(maybeAsyncParentEvent.scheduler);\n if (maybeAsyncParentNode) {\n stackTrace = addAsyncParentToStack(stackTrace, maybeAsyncParentEvent.taskName);\n node = maybeAsyncParentNode;\n continue;\n }\n node = node.parent;\n }\n return topStackTrace;\n}\n\nfunction addAsyncParentToStack(stackTrace: Protocol.Runtime.StackTrace, taskName: string): Protocol.Runtime.StackTrace {\n const parent: Protocol.Runtime.StackTrace = {callFrames: []};\n // The Protocol.Runtime.StackTrace type is recursive, so we\n // move one level deeper in it as we walk up the ancestor tree.\n stackTrace.parent = parent;\n // Note: this description effectively corresponds to the name\n // of the task that scheduled the stack trace we are jumping\n // FROM, so it would make sense that it was set to that stack\n // trace instead of the one we are jumping TO. However, the\n // JS presentation utils we use to present async stack traces\n // assume the description is added to the stack trace that\n // scheduled the async task, so we build the data that way.\n parent.description = taskName;\n return parent;\n}\n\n/**\n * Finds the JS call in which an extension entry was injected (the\n * code location that called the extension API), and returns its stack\n * trace.\n */\nfunction getForExtensionEntry(event: Types.Extensions.SyntheticExtensionEntry, parsedTrace: Handlers.Types.ParsedTrace):\n Protocol.Runtime.StackTrace|null {\n const rawEvent: Types.Events.Event = event.rawSourceEvent;\n if (Types.Events.isPerformanceMeasureBegin(rawEvent)) {\n return getForPerformanceMeasure(rawEvent, parsedTrace);\n }\n if (!rawEvent) {\n return null;\n }\n return get(rawEvent, parsedTrace);\n}\n\n/**\n * Gets the raw event for a user timing and obtains its stack trace.\n */\nfunction getForPerformanceMeasure(event: Types.Events.PerformanceMeasureBegin, parsedTrace: Handlers.Types.ParsedTrace):\n Protocol.Runtime.StackTrace|null {\n let rawEvent: Types.Events.Event|undefined = event;\n if (event.args.traceId === undefined) {\n return null;\n }\n // performance.measure calls dispatch 2 events: one for the call\n // itself and another to represent the measured entry in the trace\n // timeline. They are connected via a common traceId. At this\n // point `rawEvent` corresponds to the second case, we must\n // encounter the event for the call itself to obtain its callstack.\n rawEvent = parsedTrace.UserTimings.measureTraceByTraceId.get(event.args.traceId);\n if (!rawEvent) {\n return null;\n }\n return get(rawEvent, parsedTrace);\n}\n/**\n * Determines if a function is a native JS API (like setTimeout,\n * requestAnimationFrame, consoleTask.run. etc.). This is useful to\n * discard stack frames corresponding to the JS scheduler function\n * itself, since it's already being used as title of async stack traces\n * taken from the async `taskName`. This is also consistent with the\n * behaviour of the stack trace in the sources\n * panel.\n */\nfunction isNativeJSFunction({columnNumber, lineNumber, url, scriptId}: Protocol.Runtime.CallFrame): boolean {\n return lineNumber === -1 && columnNumber === -1 && url === '' && scriptId === '0';\n}\n\n/**\n * Extracts the top frame in the stack contained in a trace event's payload\n * (if any) and casts it as a Protocol.Runtime.CallFrame.\n */\nfunction getPayloadStackAsProtocolCallFrame(event: Types.Events.Event): Protocol.Runtime.CallFrame|null {\n const maybeCallStack = Helpers.Trace.getZeroIndexedStackTraceInEventPayload(event);\n const maybeCallFrame = maybeCallStack?.at(0);\n const maybeProtocolCallFrame =\n maybeCallFrame && {...maybeCallFrame, scriptId: String(maybeCallFrame.scriptId) as Protocol.Runtime.ScriptId};\n return maybeProtocolCallFrame || null;\n}\n"]}
@@ -1,21 +1,22 @@
1
1
  import type * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';
2
- import type * as Handlers from '../handlers/handlers.js';
2
+ import * as Handlers from '../handlers/handlers.js';
3
3
  import * as Types from '../types/types.js';
4
4
  export type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];
5
- export interface Summary {
5
+ interface BaseSummary {
6
+ entity: Entity;
6
7
  transferSize: number;
7
8
  mainThreadTime: Types.Timing.Milli;
8
- relatedEvents?: Types.Events.Event[];
9
- entity: Entity;
10
9
  }
11
- export interface ThirdPartySummary {
12
- byEntity: Map<Entity, Summary>;
13
- byUrl: Map<string, Summary>;
14
- urlsByEntity: Map<Entity, Set<string>>;
15
- eventsByEntity: Map<Entity, Types.Events.Event[]>;
16
- madeUpEntityCache: Map<string, Entity>;
10
+ export interface EntitySummary extends BaseSummary {
11
+ relatedEvents: Types.Events.Event[];
12
+ }
13
+ export interface URLSummary extends BaseSummary {
14
+ url: string;
15
+ request?: Types.Events.SyntheticNetworkRequest;
17
16
  }
17
+ export declare function summarizeByThirdParty(parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): EntitySummary[];
18
18
  /**
19
- * @param networkRequests Won't be filtered by trace bounds, so callers should ensure it is filtered.
19
+ * Used only by Lighthouse.
20
20
  */
21
- export declare function summarizeThirdParties(parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): Summary[];
21
+ export declare function summarizeByURL(parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): URLSummary[];
22
+ export {};
@@ -1,6 +1,7 @@
1
1
  // Copyright 2024 The Chromium Authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
+ import * as Handlers from '../handlers/handlers.js';
4
5
  import * as Helpers from '../helpers/helpers.js';
5
6
  import * as Types from '../types/types.js';
6
7
  import * as TraceFilter from './TraceFilter.js';
@@ -25,22 +26,32 @@ function collectMainThreadActivity(parsedTrace) {
25
26
  }
26
27
  return mainFrameMainThread.entries;
27
28
  }
29
+ export function summarizeByThirdParty(parsedTrace, traceBounds) {
30
+ const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);
31
+ const groupingFunction = (event) => {
32
+ const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(event);
33
+ return entity?.name ?? '';
34
+ };
35
+ const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);
36
+ const summaries = summarizeBottomUpByEntity(node, parsedTrace);
37
+ return summaries;
38
+ }
28
39
  /**
29
- * @param networkRequests Won't be filtered by trace bounds, so callers should ensure it is filtered.
40
+ * Used only by Lighthouse.
30
41
  */
31
- export function summarizeThirdParties(parsedTrace, traceBounds) {
42
+ export function summarizeByURL(parsedTrace, traceBounds) {
32
43
  const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);
33
- const node = getBottomUpTree(mainThreadEvents, parsedTrace, traceBounds);
34
- const summaries = summarizeBottomUp(node, parsedTrace);
44
+ const groupingFunction = (event) => {
45
+ return Handlers.Helpers.getNonResolvedURL(event, parsedTrace) ?? '';
46
+ };
47
+ const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);
48
+ const summaries = summarizeBottomUpByURL(node, parsedTrace);
35
49
  return summaries;
36
50
  }
37
- function summarizeBottomUp(thirdPartyBottomUp, parsedTrace) {
38
- const summaryForEntity = new Map();
51
+ function summarizeBottomUpByEntity(root, parsedTrace) {
39
52
  const summaries = [];
40
- // Our top nodes are the 3P entities.
41
- // Tree nodes are built lazily, .children() is essential, it triggers the
42
- // construction of the root node's child nodes.
43
- const topNodes = [...thirdPartyBottomUp.children().values()].flat();
53
+ // Top nodes are the 3P entities.
54
+ const topNodes = [...root.children().values()].flat();
44
55
  for (const node of topNodes) {
45
56
  if (node.id === '') {
46
57
  continue;
@@ -49,25 +60,45 @@ function summarizeBottomUp(thirdPartyBottomUp, parsedTrace) {
49
60
  if (!entity) {
50
61
  continue;
51
62
  }
63
+ // Lets use the mapper events as our source of events, since we use the main thread to construct
64
+ // the bottom up tree. The mapper will give us all related events.
52
65
  const summary = {
53
66
  transferSize: node.transferSize,
54
67
  mainThreadTime: Types.Timing.Milli(node.selfTime),
55
- // Lets use the mapper events as our source of events, since we use the main thread to construct
56
- // the bottom up tree. The mapper will give us all related events.
68
+ entity,
57
69
  relatedEvents: parsedTrace.Renderer.entityMappings.eventsByEntity.get(entity) ?? [],
70
+ };
71
+ summaries.push(summary);
72
+ }
73
+ return summaries;
74
+ }
75
+ function summarizeBottomUpByURL(root, parsedTrace) {
76
+ const summaries = [];
77
+ const allRequests = parsedTrace.NetworkRequests.byTime;
78
+ // Top nodes are URLs.
79
+ const topNodes = [...root.children().values()].flat();
80
+ for (const node of topNodes) {
81
+ if (node.id === '' || typeof node.id !== 'string') {
82
+ continue;
83
+ }
84
+ const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);
85
+ if (!entity) {
86
+ continue;
87
+ }
88
+ const url = node.id;
89
+ const request = allRequests.find(r => r.args.data.url === url);
90
+ const summary = {
91
+ request,
92
+ url,
58
93
  entity,
94
+ transferSize: node.transferSize,
95
+ mainThreadTime: Types.Timing.Milli(node.selfTime),
59
96
  };
60
- summaryForEntity.set(entity, summary);
61
97
  summaries.push(summary);
62
98
  }
63
99
  return summaries;
64
100
  }
65
- function getBottomUpTree(mainThreadEvents, parsedTrace, tracebounds) {
66
- const mappings = parsedTrace.Renderer.entityMappings;
67
- const groupingFunction = (event) => {
68
- const entity = mappings?.entityByEvent.get(event);
69
- return entity?.name ?? '';
70
- };
101
+ function getBottomUpTree(mainThreadEvents, tracebounds, groupingFunction) {
71
102
  // Use the same filtering as front_end/panels/timeline/TimelineTreeView.ts.
72
103
  const visibleEvents = Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();
73
104
  const filter = new TraceFilter.VisibleEventsFilter(visibleEvents.concat(["SyntheticNetworkRequest" /* Types.Events.Name.SYNTHETIC_NETWORK_REQUEST */]));
@@ -1 +1 @@
1
- {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport * as TraceFilter from './TraceFilter.js';\nimport * as TraceTree from './TraceTree.js';\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\nexport interface Summary {\n transferSize: number;\n mainThreadTime: Types.Timing.Milli;\n relatedEvents?: Types.Events.Event[];\n entity: Entity;\n}\n\nexport interface ThirdPartySummary {\n byEntity: Map<Entity, Summary>;\n byUrl: Map<string, Summary>;\n urlsByEntity: Map<Entity, Set<string>>;\n eventsByEntity: Map<Entity, Types.Events.Event[]>;\n madeUpEntityCache: Map<string, Entity>;\n}\n\n/**\n *\n * Returns Main frame main thread events.\n * These events are inline with the ones used by selectedEvents() of TimelineTreeViews\n */\nfunction collectMainThreadActivity(parsedTrace: Handlers.Types.ParsedTrace): Types.Events.Event[] {\n // TODO: Note b/402658800 could be an issue here.\n const mainFrameMainThread = parsedTrace.Renderer.processes.values()\n .find(p => {\n const url = p.url ?? '';\n // Frame url checked a la CompatibilityTracksAppenders's addThreadAppenders\n return p.isOnMainFrame && !url.startsWith('about:') && !url.startsWith('chrome:');\n })\n ?.threads.values()\n .find(t => t.name === 'CrRendererMain');\n\n if (!mainFrameMainThread) {\n return [];\n }\n\n return mainFrameMainThread.entries;\n}\n\n/**\n * @param networkRequests Won't be filtered by trace bounds, so callers should ensure it is filtered.\n */\nexport function summarizeThirdParties(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): Summary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const node = getBottomUpTree(mainThreadEvents, parsedTrace, traceBounds);\n const summaries = summarizeBottomUp(node, parsedTrace);\n\n return summaries;\n}\n\nfunction summarizeBottomUp(\n thirdPartyBottomUp: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): Summary[] {\n const summaryForEntity: Map<Entity, Summary> = new Map<Entity, Summary>();\n const summaries: Summary[] = [];\n\n // Our top nodes are the 3P entities.\n // Tree nodes are built lazily, .children() is essential, it triggers the\n // construction of the root node's child nodes.\n const topNodes = [...thirdPartyBottomUp.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '') {\n continue;\n }\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n const summary: Summary = {\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n // Lets use the mapper events as our source of events, since we use the main thread to construct\n // the bottom up tree. The mapper will give us all related events.\n relatedEvents: parsedTrace.Renderer.entityMappings.eventsByEntity.get(entity) ?? [],\n entity,\n };\n summaryForEntity.set(entity, summary);\n summaries.push(summary);\n }\n return summaries;\n}\n\nfunction getBottomUpTree(\n mainThreadEvents: Types.Events.Event[], parsedTrace: Handlers.Types.ParsedTrace,\n tracebounds: Types.Timing.TraceWindowMicro): TraceTree.BottomUpRootNode {\n const mappings = parsedTrace.Renderer.entityMappings;\n\n const groupingFunction = (event: Types.Events.Event): string => {\n const entity = mappings?.entityByEvent.get(event);\n return entity?.name ?? '';\n };\n // Use the same filtering as front_end/panels/timeline/TimelineTreeView.ts.\n const visibleEvents = Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();\n const filter =\n new TraceFilter.VisibleEventsFilter(visibleEvents.concat([Types.Events.Name.SYNTHETIC_NETWORK_REQUEST]));\n\n // The bottom up root node handles all the \"in Tracebounds\" checks we need for the insight.\n const startTime = Helpers.Timing.microToMilli(tracebounds.min);\n const endTime = Helpers.Timing.microToMilli(tracebounds.max);\n const node = new TraceTree.BottomUpRootNode(mainThreadEvents, {\n textFilter: new TraceFilter.ExclusiveNameFilter([]),\n filters: [filter],\n startTime,\n endTime,\n eventGroupIdCallback: groupingFunction,\n calculateTransferSize: true,\n // Ensure we group by 3P alongside eventID for correct 3P grouping.\n forceGroupIdCallback: true,\n }) as TraceTree.BottomUpRootNode;\n return node;\n}\n"]}
1
+ {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport * as TraceFilter from './TraceFilter.js';\nimport * as TraceTree from './TraceTree.js';\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\ninterface BaseSummary {\n entity: Entity;\n transferSize: number;\n mainThreadTime: Types.Timing.Milli;\n}\n\nexport interface EntitySummary extends BaseSummary {\n relatedEvents: Types.Events.Event[];\n}\n\nexport interface URLSummary extends BaseSummary {\n url: string;\n request?: Types.Events.SyntheticNetworkRequest;\n}\n\n/**\n *\n * Returns Main frame main thread events.\n * These events are inline with the ones used by selectedEvents() of TimelineTreeViews\n */\nfunction collectMainThreadActivity(parsedTrace: Handlers.Types.ParsedTrace): Types.Events.Event[] {\n // TODO: Note b/402658800 could be an issue here.\n const mainFrameMainThread = parsedTrace.Renderer.processes.values()\n .find(p => {\n const url = p.url ?? '';\n // Frame url checked a la CompatibilityTracksAppenders's addThreadAppenders\n return p.isOnMainFrame && !url.startsWith('about:') && !url.startsWith('chrome:');\n })\n ?.threads.values()\n .find(t => t.name === 'CrRendererMain');\n\n if (!mainFrameMainThread) {\n return [];\n }\n\n return mainFrameMainThread.entries;\n}\n\nexport function summarizeByThirdParty(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): EntitySummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(event);\n return entity?.name ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByEntity(node, parsedTrace);\n\n return summaries;\n}\n\n/**\n * Used only by Lighthouse.\n */\nexport function summarizeByURL(\n parsedTrace: Handlers.Types.ParsedTrace, traceBounds: Types.Timing.TraceWindowMicro): URLSummary[] {\n const mainThreadEvents = collectMainThreadActivity(parsedTrace).sort(Helpers.Trace.eventTimeComparator);\n const groupingFunction = (event: Types.Events.Event): string => {\n return Handlers.Helpers.getNonResolvedURL(event, parsedTrace) ?? '';\n };\n const node = getBottomUpTree(mainThreadEvents, traceBounds, groupingFunction);\n const summaries = summarizeBottomUpByURL(node, parsedTrace);\n\n return summaries;\n}\n\nfunction summarizeBottomUpByEntity(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): EntitySummary[] {\n const summaries: EntitySummary[] = [];\n\n // Top nodes are the 3P entities.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n // Lets use the mapper events as our source of events, since we use the main thread to construct\n // the bottom up tree. The mapper will give us all related events.\n const summary: EntitySummary = {\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n entity,\n relatedEvents: parsedTrace.Renderer.entityMappings.eventsByEntity.get(entity) ?? [],\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction summarizeBottomUpByURL(\n root: TraceTree.BottomUpRootNode, parsedTrace: Handlers.Types.ParsedTrace): URLSummary[] {\n const summaries: URLSummary[] = [];\n const allRequests = parsedTrace.NetworkRequests.byTime;\n\n // Top nodes are URLs.\n const topNodes = [...root.children().values()].flat();\n for (const node of topNodes) {\n if (node.id === '' || typeof node.id !== 'string') {\n continue;\n }\n\n const entity = parsedTrace.Renderer.entityMappings.entityByEvent.get(node.event);\n if (!entity) {\n continue;\n }\n\n const url = node.id;\n const request = allRequests.find(r => r.args.data.url === url);\n\n const summary: URLSummary = {\n request,\n url,\n entity,\n transferSize: node.transferSize,\n mainThreadTime: Types.Timing.Milli(node.selfTime),\n };\n summaries.push(summary);\n }\n\n return summaries;\n}\n\nfunction getBottomUpTree(\n mainThreadEvents: Types.Events.Event[], tracebounds: Types.Timing.TraceWindowMicro,\n groupingFunction: ((arg0: Types.Events.Event) => string)|null): TraceTree.BottomUpRootNode {\n // Use the same filtering as front_end/panels/timeline/TimelineTreeView.ts.\n const visibleEvents = Helpers.Trace.VISIBLE_TRACE_EVENT_TYPES.values().toArray();\n const filter =\n new TraceFilter.VisibleEventsFilter(visibleEvents.concat([Types.Events.Name.SYNTHETIC_NETWORK_REQUEST]));\n\n // The bottom up root node handles all the \"in Tracebounds\" checks we need for the insight.\n const startTime = Helpers.Timing.microToMilli(tracebounds.min);\n const endTime = Helpers.Timing.microToMilli(tracebounds.max);\n const node = new TraceTree.BottomUpRootNode(mainThreadEvents, {\n textFilter: new TraceFilter.ExclusiveNameFilter([]),\n filters: [filter],\n startTime,\n endTime,\n eventGroupIdCallback: groupingFunction,\n calculateTransferSize: true,\n // Ensure we group by 3P alongside eventID for correct 3P grouping.\n forceGroupIdCallback: true,\n }) as TraceTree.BottomUpRootNode;\n return node;\n}\n"]}
@@ -17,7 +17,7 @@
17
17
  "noFallthroughCasesInSwitch": true,
18
18
  "noImplicitOverride": true,
19
19
  "noImplicitReturns": true,
20
- "noUnusedLocals": false,
20
+ "noUnusedLocals": true,
21
21
  "noUnusedParameters": true,
22
22
  "outDir": ".",
23
23
  "rootDir": "../../../../../../../front_end/models/trace/extras",
@@ -17,7 +17,7 @@
17
17
  "noFallthroughCasesInSwitch": true,
18
18
  "noImplicitOverride": true,
19
19
  "noImplicitReturns": true,
20
- "noUnusedLocals": false,
20
+ "noUnusedLocals": true,
21
21
  "noUnusedParameters": true,
22
22
  "outDir": ".",
23
23
  "rootDir": "../../../../../../../front_end/models/trace/extras",
@@ -20,6 +20,7 @@ export * as StackTraceForEvent from './StackTraceForEvent.js';
20
20
  // import 'es-iterator-helpers/Iterator.prototype.find/auto';
21
21
  // import 'es-iterator-helpers/Iterator.prototype.flatMap/auto';
22
22
  // import 'es-iterator-helpers/Iterator.prototype.map/auto';
23
+ // import 'es-iterator-helpers/Iterator.prototype.reduce/auto';
23
24
  // import 'es-iterator-helpers/Iterator.prototype.toArray/auto';
24
25
 
25
26
  "use strict";
@@ -3821,8 +3822,96 @@ export * as StackTraceForEvent from './StackTraceForEvent.js';
3821
3822
  }
3822
3823
  });
3823
3824
 
3824
- // node_modules/es-iterator-helpers/Iterator.prototype.toArray/implementation.js
3825
+ // node_modules/es-iterator-helpers/Iterator.prototype.reduce/implementation.js
3825
3826
  var require_implementation7 = __commonJS({
3827
+ "node_modules/es-iterator-helpers/Iterator.prototype.reduce/implementation.js"(exports, module) {
3828
+ "use strict";
3829
+ var $TypeError = require_type();
3830
+ var Call = require_Call();
3831
+ var GetIteratorDirect = require_GetIteratorDirect();
3832
+ var IsCallable = require_IsCallable();
3833
+ var IteratorClose = require_IteratorClose();
3834
+ var IteratorStepValue = require_IteratorStepValue();
3835
+ var ThrowCompletion = require_ThrowCompletion();
3836
+ var Type = require_Type2();
3837
+ module.exports = function reduce(reducer) {
3838
+ if (this instanceof reduce) {
3839
+ throw new $TypeError("`reduce` is not a constructor");
3840
+ }
3841
+ var O = this;
3842
+ if (Type(O) !== "Object") {
3843
+ throw new $TypeError("`this` value must be an Object");
3844
+ }
3845
+ if (!IsCallable(reducer)) {
3846
+ throw new $TypeError("`reducer` must be a function");
3847
+ }
3848
+ var iterated = GetIteratorDirect(O);
3849
+ var accumulator;
3850
+ var counter;
3851
+ if (arguments.length < 2) {
3852
+ accumulator = IteratorStepValue(iterated);
3853
+ if (iterated["[[Done]]"]) {
3854
+ throw new $TypeError("Reduce of empty iterator with no initial value");
3855
+ }
3856
+ counter = 1;
3857
+ } else {
3858
+ accumulator = arguments[1];
3859
+ counter = 0;
3860
+ }
3861
+ while (true) {
3862
+ var value = IteratorStepValue(iterated);
3863
+ if (iterated["[[Done]]"]) {
3864
+ return accumulator;
3865
+ }
3866
+ try {
3867
+ var result = Call(reducer, void 0, [accumulator, value, counter]);
3868
+ accumulator = result;
3869
+ } catch (e) {
3870
+ IteratorClose(
3871
+ iterated,
3872
+ ThrowCompletion(e)
3873
+ );
3874
+ }
3875
+ counter += 1;
3876
+ }
3877
+ };
3878
+ }
3879
+ });
3880
+
3881
+ // node_modules/es-iterator-helpers/Iterator.prototype.reduce/polyfill.js
3882
+ var require_polyfill4 = __commonJS({
3883
+ "node_modules/es-iterator-helpers/Iterator.prototype.reduce/polyfill.js"(exports, module) {
3884
+ "use strict";
3885
+ var implementation = require_implementation7();
3886
+ module.exports = function getPolyfill() {
3887
+ return typeof Iterator === "function" && typeof Iterator.prototype.reduce === "function" ? Iterator.prototype.reduce : implementation;
3888
+ };
3889
+ }
3890
+ });
3891
+
3892
+ // node_modules/es-iterator-helpers/Iterator.prototype.reduce/shim.js
3893
+ var require_shim4 = __commonJS({
3894
+ "node_modules/es-iterator-helpers/Iterator.prototype.reduce/shim.js"(exports, module) {
3895
+ "use strict";
3896
+ var define = require_define_properties();
3897
+ var getPolyfill = require_polyfill4();
3898
+ var $IteratorPrototype = require_implementation4();
3899
+ module.exports = function shimIteratorPrototypeReduce() {
3900
+ var polyfill = getPolyfill();
3901
+ define(
3902
+ $IteratorPrototype,
3903
+ { reduce: polyfill },
3904
+ { reduce: function() {
3905
+ return $IteratorPrototype.reduce !== polyfill;
3906
+ } }
3907
+ );
3908
+ return polyfill;
3909
+ };
3910
+ }
3911
+ });
3912
+
3913
+ // node_modules/es-iterator-helpers/Iterator.prototype.toArray/implementation.js
3914
+ var require_implementation8 = __commonJS({
3826
3915
  "node_modules/es-iterator-helpers/Iterator.prototype.toArray/implementation.js"(exports, module) {
3827
3916
  "use strict";
3828
3917
  var $TypeError = require_type();
@@ -3851,10 +3940,10 @@ export * as StackTraceForEvent from './StackTraceForEvent.js';
3851
3940
  });
3852
3941
 
3853
3942
  // node_modules/es-iterator-helpers/Iterator.prototype.toArray/polyfill.js
3854
- var require_polyfill4 = __commonJS({
3943
+ var require_polyfill5 = __commonJS({
3855
3944
  "node_modules/es-iterator-helpers/Iterator.prototype.toArray/polyfill.js"(exports, module) {
3856
3945
  "use strict";
3857
- var implementation = require_implementation7();
3946
+ var implementation = require_implementation8();
3858
3947
  module.exports = function getPolyfill() {
3859
3948
  return typeof Iterator === "function" && typeof Iterator.prototype.toArray === "function" ? Iterator.prototype.toArray : implementation;
3860
3949
  };
@@ -3862,11 +3951,11 @@ export * as StackTraceForEvent from './StackTraceForEvent.js';
3862
3951
  });
3863
3952
 
3864
3953
  // node_modules/es-iterator-helpers/Iterator.prototype.toArray/shim.js
3865
- var require_shim4 = __commonJS({
3954
+ var require_shim5 = __commonJS({
3866
3955
  "node_modules/es-iterator-helpers/Iterator.prototype.toArray/shim.js"(exports, module) {
3867
3956
  "use strict";
3868
3957
  var define = require_define_properties();
3869
- var getPolyfill = require_polyfill4();
3958
+ var getPolyfill = require_polyfill5();
3870
3959
  var $IteratorPrototype = require_implementation4();
3871
3960
  module.exports = function shimIteratorPrototypeToArray() {
3872
3961
  var polyfill = getPolyfill();
@@ -3891,6 +3980,9 @@ export * as StackTraceForEvent from './StackTraceForEvent.js';
3891
3980
  // node_modules/es-iterator-helpers/Iterator.prototype.map/auto.js
3892
3981
  require_shim3()();
3893
3982
 
3894
- // node_modules/es-iterator-helpers/Iterator.prototype.toArray/auto.js
3983
+ // node_modules/es-iterator-helpers/Iterator.prototype.reduce/auto.js
3895
3984
  require_shim4()();
3985
+
3986
+ // node_modules/es-iterator-helpers/Iterator.prototype.toArray/auto.js
3987
+ require_shim5()();
3896
3988
  })();