@paulirish/trace_engine 0.0.39 → 0.0.41
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.
- package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
- package/core/platform/DevToolsPath.d.ts +30 -9
- package/core/platform/DevToolsPath.js +21 -0
- package/core/platform/DevToolsPath.js.map +1 -1
- package/core/platform/MapUtilities.js +1 -1
- package/core/platform/MapUtilities.js.map +1 -1
- package/core/platform/ServerTiming.d.ts +2 -2
- package/core/platform/ServerTiming.js.map +1 -1
- package/core/platform/StringUtilities.js +1 -1
- package/core/platform/StringUtilities.js.map +1 -1
- package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/core/platform/platform-tsconfig.json +2 -1
- package/generated/protocol.d.ts +203 -73
- package/locales/af.json +26 -2
- package/locales/am.json +27 -3
- package/locales/ar.json +26 -2
- package/locales/as.json +26 -2
- package/locales/az.json +26 -2
- package/locales/be.json +26 -2
- package/locales/bg.json +26 -2
- package/locales/bn.json +26 -2
- package/locales/bs.json +26 -2
- package/locales/ca.json +26 -2
- package/locales/cs.json +26 -2
- package/locales/cy.json +26 -2
- package/locales/da.json +26 -2
- package/locales/de.json +26 -2
- package/locales/el.json +26 -2
- package/locales/en-GB.json +26 -2
- package/locales/en-US.json +20 -2
- package/locales/en-XL.json +20 -2
- package/locales/es-419.json +26 -2
- package/locales/es.json +26 -2
- package/locales/et.json +26 -2
- package/locales/eu.json +26 -2
- package/locales/fa.json +26 -2
- package/locales/fi.json +26 -2
- package/locales/fil.json +26 -2
- package/locales/fr-CA.json +26 -2
- package/locales/fr.json +26 -2
- package/locales/gl.json +26 -2
- package/locales/gu.json +26 -2
- package/locales/he.json +26 -2
- package/locales/hi.json +26 -2
- package/locales/hr.json +26 -2
- package/locales/hu.json +26 -2
- package/locales/hy.json +26 -2
- package/locales/id.json +26 -2
- package/locales/is.json +26 -2
- package/locales/it.json +26 -2
- package/locales/ja.json +26 -2
- package/locales/ka.json +26 -2
- package/locales/kk.json +26 -2
- package/locales/km.json +26 -2
- package/locales/kn.json +26 -2
- package/locales/ko.json +26 -2
- package/locales/ky.json +26 -2
- package/locales/lo.json +26 -2
- package/locales/lt.json +26 -2
- package/locales/lv.json +26 -2
- package/locales/mk.json +26 -2
- package/locales/ml.json +26 -2
- package/locales/mn.json +27 -3
- package/locales/mr.json +26 -2
- package/locales/ms.json +26 -2
- package/locales/my.json +26 -2
- package/locales/ne.json +26 -2
- package/locales/nl.json +26 -2
- package/locales/no.json +26 -2
- package/locales/or.json +27 -3
- package/locales/pa.json +26 -2
- package/locales/pl.json +26 -2
- package/locales/pt-PT.json +26 -2
- package/locales/pt.json +26 -2
- package/locales/ro.json +26 -2
- package/locales/ru.json +26 -2
- package/locales/si.json +26 -2
- package/locales/sk.json +26 -2
- package/locales/sl.json +26 -2
- package/locales/sq.json +26 -2
- package/locales/sr-Latn.json +26 -2
- package/locales/sr.json +26 -2
- package/locales/sv.json +26 -2
- package/locales/sw.json +26 -2
- package/locales/ta.json +26 -2
- package/locales/te.json +26 -2
- package/locales/th.json +26 -2
- package/locales/tr.json +26 -2
- package/locales/uk.json +26 -2
- package/locales/ur.json +26 -2
- package/locales/uz.json +26 -2
- package/locales/vi.json +26 -2
- package/locales/zh-HK.json +26 -2
- package/locales/zh-TW.json +26 -2
- package/locales/zh.json +26 -2
- package/locales/zu.json +26 -2
- package/models/cpu_profile/ProfileTreeModel.js +0 -2
- package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
- package/models/cpu_profile/cpu_profile-tsconfig.json +2 -1
- package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/LanternComputationData.js +1 -1
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +6 -6
- package/models/trace/ModelImpl.js +1 -0
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.d.ts +6 -0
- package/models/trace/Processor.js +90 -9
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/extras/StackTraceForEvent.d.ts +12 -0
- package/models/trace/extras/StackTraceForEvent.js +163 -0
- package/models/trace/extras/StackTraceForEvent.js.map +1 -0
- package/models/trace/extras/ThirdParties.d.ts +7 -4
- package/models/trace/extras/ThirdParties.js +56 -65
- package/models/trace/extras/ThirdParties.js.map +1 -1
- package/models/trace/extras/TraceTree.js +8 -8
- package/models/trace/extras/TraceTree.js.map +1 -1
- package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/extras/extras-tsconfig.json +3 -2
- package/models/trace/extras/extras.js.map +1 -1
- package/models/trace/handlers/AnimationFramesHandler.d.ts +11 -0
- package/models/trace/handlers/AnimationFramesHandler.js +102 -0
- package/models/trace/handlers/AnimationFramesHandler.js.map +1 -0
- package/models/trace/handlers/AsyncJSCallsHandler.d.ts +15 -0
- package/models/trace/handlers/AsyncJSCallsHandler.js +153 -0
- package/models/trace/handlers/AsyncJSCallsHandler.js.map +1 -0
- package/models/trace/handlers/DOMStatsHandler.d.ts +8 -0
- package/models/trace/handlers/DOMStatsHandler.js +22 -0
- package/models/trace/handlers/DOMStatsHandler.js.map +1 -0
- package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +80 -2
- package/models/trace/handlers/ExtensionTraceDataHandler.js +163 -13
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/FlowsHandler.js +47 -55
- package/models/trace/handlers/FlowsHandler.js.map +1 -1
- package/models/trace/handlers/InitiatorsHandler.d.ts +11 -0
- package/models/trace/handlers/InitiatorsHandler.js +33 -25
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
- package/models/trace/handlers/LargestImagePaintHandler.d.ts +0 -2
- package/models/trace/handlers/LargestImagePaintHandler.js +27 -24
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +2 -2
- package/models/trace/handlers/LayoutShiftsHandler.js +3 -2
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.d.ts +2 -2
- package/models/trace/handlers/MetaHandler.js +1 -1
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +4 -1
- package/models/trace/handlers/ModelHandlers.js +4 -1
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +2 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +21 -0
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -2
- package/models/trace/handlers/PageLoadMetricsHandler.js +9 -9
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/RendererHandler.d.ts +4 -0
- package/models/trace/handlers/RendererHandler.js +33 -2
- package/models/trace/handlers/RendererHandler.js.map +1 -1
- package/models/trace/handlers/SamplesHandler.d.ts +2 -2
- package/models/trace/handlers/SamplesHandler.js +3 -3
- package/models/trace/handlers/SamplesHandler.js.map +1 -1
- package/models/trace/handlers/ServerTimingsHandler.js +2 -2
- package/models/trace/handlers/ServerTimingsHandler.js.map +1 -1
- package/models/trace/handlers/Threads.d.ts +1 -0
- package/models/trace/handlers/Threads.js +8 -0
- package/models/trace/handlers/Threads.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.js +5 -6
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/handlers/UserTimingsHandler.d.ts +1 -1
- package/models/trace/handlers/UserTimingsHandler.js +1 -1
- package/models/trace/handlers/UserTimingsHandler.js.map +1 -1
- package/models/trace/handlers/WarningsHandler.js +2 -2
- package/models/trace/handlers/WarningsHandler.js.map +1 -1
- package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/handlers/handlers-tsconfig.json +9 -1
- package/models/trace/handlers/handlers.d.ts +1 -0
- package/models/trace/handlers/handlers.js +1 -0
- package/models/trace/handlers/handlers.js.map +1 -1
- package/models/trace/handlers/helpers.d.ts +19 -0
- package/models/trace/handlers/helpers.js +123 -0
- package/models/trace/handlers/helpers.js.map +1 -0
- package/models/trace/helpers/SamplesIntegrator.js +2 -2
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
- package/models/trace/helpers/SyntheticEvents.js +1 -1
- package/models/trace/helpers/SyntheticEvents.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +5 -6
- package/models/trace/helpers/Timing.js +22 -31
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +24 -10
- package/models/trace/helpers/Trace.js +53 -6
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/TreeHelpers.d.ts +0 -31
- package/models/trace/helpers/TreeHelpers.js +1 -142
- package/models/trace/helpers/TreeHelpers.js.map +1 -1
- package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/helpers/helpers-tsconfig.json +2 -1
- package/models/trace/insights/CLSCulprits.d.ts +9 -0
- package/models/trace/insights/CLSCulprits.js +2 -3
- package/models/trace/insights/CLSCulprits.js.map +1 -1
- package/models/trace/insights/Common.d.ts +38 -1
- package/models/trace/insights/Common.js +123 -0
- package/models/trace/insights/Common.js.map +1 -1
- package/models/trace/insights/DOMSize.d.ts +19 -0
- package/models/trace/insights/DOMSize.js +102 -0
- package/models/trace/insights/DOMSize.js.map +1 -0
- package/models/trace/insights/DocumentLatency.d.ts +10 -0
- package/models/trace/insights/DocumentLatency.js +2 -2
- package/models/trace/insights/DocumentLatency.js.map +1 -1
- package/models/trace/insights/FontDisplay.d.ts +8 -0
- package/models/trace/insights/FontDisplay.js +2 -2
- package/models/trace/insights/FontDisplay.js.map +1 -1
- package/models/trace/insights/ImageDelivery.d.ts +54 -4
- package/models/trace/insights/ImageDelivery.js +77 -7
- package/models/trace/insights/ImageDelivery.js.map +1 -1
- package/models/trace/insights/InteractionToNextPaint.d.ts +10 -0
- package/models/trace/insights/InteractionToNextPaint.js +1 -1
- package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
- package/models/trace/insights/LCPDiscovery.d.ts +10 -0
- package/models/trace/insights/LCPDiscovery.js +3 -3
- package/models/trace/insights/LCPDiscovery.js.map +1 -1
- package/models/trace/insights/LCPPhases.d.ts +11 -0
- package/models/trace/insights/LCPPhases.js +8 -8
- package/models/trace/insights/LCPPhases.js.map +1 -1
- package/models/trace/insights/Models.d.ts +1 -0
- package/models/trace/insights/Models.js +1 -0
- package/models/trace/insights/Models.js.map +1 -1
- package/models/trace/insights/RenderBlocking.d.ts +10 -0
- package/models/trace/insights/RenderBlocking.js +1 -1
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/SlowCSSSelector.d.ts +10 -0
- package/models/trace/insights/SlowCSSSelector.js +1 -1
- package/models/trace/insights/SlowCSSSelector.js.map +1 -1
- package/models/trace/insights/Statistics.d.ts +14 -0
- package/models/trace/insights/Statistics.js +86 -0
- package/models/trace/insights/Statistics.js.map +1 -0
- package/models/trace/insights/ThirdParties.d.ts +11 -2
- package/models/trace/insights/ThirdParties.js +6 -5
- package/models/trace/insights/ThirdParties.js.map +1 -1
- package/models/trace/insights/Viewport.d.ts +8 -0
- package/models/trace/insights/Viewport.js +3 -3
- package/models/trace/insights/Viewport.js.map +1 -1
- package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/insights/insights-tsconfig.json +4 -1
- package/models/trace/insights/insights.d.ts +1 -0
- package/models/trace/insights/insights.js +1 -0
- package/models/trace/insights/insights.js.map +1 -1
- package/models/trace/insights/types.d.ts +4 -3
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/core/NetworkAnalyzer.d.ts +2 -2
- package/models/trace/lantern/core/NetworkAnalyzer.js +2 -3
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
- package/models/trace/lantern/core/core-tsconfig.json +2 -1
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js +0 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/graph/graph-tsconfig.json +2 -1
- package/models/trace/lantern/lantern-tsconfig.json +2 -1
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/metrics/metrics-tsconfig.json +2 -1
- package/models/trace/lantern/simulation/DNSCache.d.ts +2 -2
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/simulation/simulation-tsconfig.json +2 -1
- package/models/trace/lantern/types/Lantern.d.ts +10 -10
- package/models/trace/lantern/types/Lantern.js.map +1 -1
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/lantern/types/types-tsconfig.json +2 -1
- package/models/trace/root-causes/LayoutShift.d.ts +6 -6
- package/models/trace/root-causes/LayoutShift.js +1 -1
- package/models/trace/root-causes/LayoutShift.js.map +1 -1
- package/models/trace/root-causes/RootCauses.d.ts +2 -2
- package/models/trace/root-causes/RootCauses.js.map +1 -1
- package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/root-causes/root-causes-tsconfig.json +2 -1
- package/models/trace/trace-tsconfig.json +2 -1
- package/models/trace/types/Configuration.d.ts +2 -2
- package/models/trace/types/Configuration.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +3 -3
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +11 -11
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/Timing.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +107 -31
- package/models/trace/types/TraceEvents.js +34 -14
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +2 -1
- package/models/trace/types/types-tsconfig.json +2 -1
- package/package.json +1 -1
- package/test/test-trace-engine.mjs +8 -7
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Platform from '../../../core/platform/platform.js';
|
|
5
|
+
import * as Types from '../types/types.js';
|
|
6
|
+
import { data as flowsHandlerData } from './FlowsHandler.js';
|
|
7
|
+
import { data as rendererHandlerData } from './RendererHandler.js';
|
|
8
|
+
const schedulerToRunEntryPoints = new Map();
|
|
9
|
+
const asyncCallToScheduler = new Map();
|
|
10
|
+
export function reset() {
|
|
11
|
+
schedulerToRunEntryPoints.clear();
|
|
12
|
+
asyncCallToScheduler.clear();
|
|
13
|
+
}
|
|
14
|
+
export function handleEvent(_) {
|
|
15
|
+
}
|
|
16
|
+
export async function finalize() {
|
|
17
|
+
const { flows } = flowsHandlerData();
|
|
18
|
+
const { entryToNode } = rendererHandlerData();
|
|
19
|
+
// Process async task flows
|
|
20
|
+
for (const flow of flows) {
|
|
21
|
+
const asyncTaskScheduled = flow.at(0);
|
|
22
|
+
if (!asyncTaskScheduled || !Types.Events.isDebuggerAsyncTaskScheduled(asyncTaskScheduled)) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const taskName = asyncTaskScheduled.args.taskName;
|
|
26
|
+
const asyncTaskRun = flow.at(1);
|
|
27
|
+
if (!asyncTaskRun || !Types.Events.isDebuggerAsyncTaskRun(asyncTaskRun)) {
|
|
28
|
+
// Unexpected flow shape, ignore.
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const asyncCaller = findNearestJSAncestor(asyncTaskScheduled, entryToNode);
|
|
32
|
+
if (!asyncCaller) {
|
|
33
|
+
// Unexpected async call trace data shape, ignore.
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const asyncEntryPoint = findFirstJsInvocationForAsyncTaskRun(asyncTaskRun, entryToNode);
|
|
37
|
+
if (!asyncEntryPoint) {
|
|
38
|
+
// Unexpected async call trace data shape, ignore.
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Set scheduler -> schedulee mapping.
|
|
42
|
+
// The schedulee being the JS entrypoint
|
|
43
|
+
const entryPoints = Platform.MapUtilities.getWithDefault(schedulerToRunEntryPoints, asyncCaller, () => []);
|
|
44
|
+
entryPoints.push(asyncEntryPoint);
|
|
45
|
+
// Set schedulee -> scheduler mapping.
|
|
46
|
+
// The schedulees being the JS calls (instead of the entrypoints as
|
|
47
|
+
// above, for usage ergonomics).
|
|
48
|
+
const scheduledProfileCalls = findFirstJSCallsForAsyncTaskRun(asyncTaskRun, entryToNode);
|
|
49
|
+
for (const call of scheduledProfileCalls) {
|
|
50
|
+
asyncCallToScheduler.set(call, { taskName, scheduler: asyncCaller });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Given a DebuggerAsyncTaskScheduled event, returns its closest
|
|
56
|
+
* ProfileCall or JS invocation ancestor, which represents the JS call
|
|
57
|
+
* that scheduled the async task.
|
|
58
|
+
*/
|
|
59
|
+
function findNearestJSAncestor(asyncTaskScheduled, entryToNode) {
|
|
60
|
+
let node = entryToNode.get(asyncTaskScheduled)?.parent;
|
|
61
|
+
while (node) {
|
|
62
|
+
if (Types.Events.isProfileCall(node.entry) || acceptJSInvocationsPredicate(node.entry)) {
|
|
63
|
+
return node.entry;
|
|
64
|
+
}
|
|
65
|
+
node = node.parent;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Entrypoints to JS execution in the timeline. We ignore those starting
|
|
71
|
+
* with 'v8' because they aren't shown in the timeline, and ultimately
|
|
72
|
+
* this function's output results in "initiated" events, so ideally this
|
|
73
|
+
* returns events that end up in the flame chart.
|
|
74
|
+
*/
|
|
75
|
+
function acceptJSInvocationsPredicate(event) {
|
|
76
|
+
const eventIsConsoleRunTask = Types.Events.isConsoleRunTask(event);
|
|
77
|
+
const eventIsV8EntryPoint = event.name.startsWith('v8') || event.name.startsWith('V8');
|
|
78
|
+
return Types.Events.isJSInvocationEvent(event) && (eventIsConsoleRunTask || !eventIsV8EntryPoint);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Given a DebuggerAsyncTaskRun event, returns its closest JS entry
|
|
82
|
+
* point descendant, which contains the task being scheduled.
|
|
83
|
+
*/
|
|
84
|
+
function findFirstJsInvocationForAsyncTaskRun(asyncTaskRun, entryToNode) {
|
|
85
|
+
// Ignore descendants of other DebuggerAsyncTaskRuns since they
|
|
86
|
+
// are part of another async task and have to be handled separately
|
|
87
|
+
return findFirstDescendantsOfType(asyncTaskRun, entryToNode, acceptJSInvocationsPredicate, Types.Events.isDebuggerAsyncTaskRun)
|
|
88
|
+
.at(0);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Given an async task run event, returns the top level call frames
|
|
92
|
+
* (profile calls) directly called by the async task. This implies that
|
|
93
|
+
* any profile calls under another async task run event are ignored.
|
|
94
|
+
* These profile calls represent the JS task being scheduled, AKA
|
|
95
|
+
* the other part of the async stack.
|
|
96
|
+
*
|
|
97
|
+
* For example, here the profile calls "js 1", "js 2" and "js 4" would
|
|
98
|
+
* be returned:
|
|
99
|
+
*
|
|
100
|
+
* |------------------Async Task Run------------------|
|
|
101
|
+
* |--FunctionCall--| |--FunctionCall--|
|
|
102
|
+
* |-js 1-||-js 2-| |-js 4-|
|
|
103
|
+
* |-js 3-|
|
|
104
|
+
*
|
|
105
|
+
* But here, only "js 1" and "js 2" would be returned:
|
|
106
|
+
*
|
|
107
|
+
* |------------------Async Task Run------------------|
|
|
108
|
+
* |--FunctionCall--| |------------------------|
|
|
109
|
+
* |-js 1-||-js 2-| |---Async Task Run--|
|
|
110
|
+
* |-js 3-| |--FunctionCall--|
|
|
111
|
+
* |-js 4-|
|
|
112
|
+
*/
|
|
113
|
+
function findFirstJSCallsForAsyncTaskRun(asyncTaskRun, entryToNode) {
|
|
114
|
+
// Ignore descendants of other DebuggerAsyncTaskRuns since they
|
|
115
|
+
// are part of another async task and have to be handled separately
|
|
116
|
+
return findFirstDescendantsOfType(asyncTaskRun, entryToNode, Types.Events.isProfileCall, Types.Events.isDebuggerAsyncTaskRun);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Given a root event returns all the first descendants that meet a
|
|
120
|
+
* predicate condition (predicateAccept) while ignoring subtrees whose
|
|
121
|
+
* top event meets an ignore condition (predicateIgnore).
|
|
122
|
+
*/
|
|
123
|
+
function findFirstDescendantsOfType(root, entryToNode, predicateAccept, predicateIgnore) {
|
|
124
|
+
const node = entryToNode.get(root);
|
|
125
|
+
if (!node) {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
const childrenGroups = [[...node.children]];
|
|
129
|
+
const firstDescendants = [];
|
|
130
|
+
for (let i = 0; i < childrenGroups.length; i++) {
|
|
131
|
+
const siblings = childrenGroups[i];
|
|
132
|
+
for (let j = 0; j < siblings.length; j++) {
|
|
133
|
+
const node = siblings[j];
|
|
134
|
+
if (predicateAccept(node.entry)) {
|
|
135
|
+
firstDescendants.push(node.entry);
|
|
136
|
+
}
|
|
137
|
+
else if (!predicateIgnore(node.entry)) {
|
|
138
|
+
childrenGroups.push([...node.children]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return firstDescendants;
|
|
143
|
+
}
|
|
144
|
+
export function data() {
|
|
145
|
+
return {
|
|
146
|
+
schedulerToRunEntryPoints,
|
|
147
|
+
asyncCallToScheduler,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function deps() {
|
|
151
|
+
return ['Renderer', 'Flows'];
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=AsyncJSCallsHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AsyncJSCallsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AsyncJSCallsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,IAAI,IAAI,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAC,IAAI,IAAI,mBAAmB,EAAC,MAAM,sBAAsB,CAAC;AAEjE,MAAM,yBAAyB,GAAkD,IAAI,GAAG,EAAE,CAAC;AAC3F,MAAM,oBAAoB,GACtB,IAAI,GAAG,EAAE,CAAC;AAEd,MAAM,UAAU,KAAK;IACnB,yBAAyB,CAAC,KAAK,EAAE,CAAC;IAClC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,CAAqB;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,EAAC,KAAK,EAAC,GAAG,gBAAgB,EAAE,CAAC;IACnC,MAAM,EAAC,WAAW,EAAC,GAAG,mBAAmB,EAAE,CAAC;IAC5C,2BAA2B;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,4BAA4B,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC1F,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,YAAY,CAAC,EAAE,CAAC;YACxE,iCAAiC;YACjC,SAAS;QACX,CAAC;QACD,MAAM,WAAW,GAAG,qBAAqB,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;QAC3E,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,kDAAkD;YAClD,SAAS;QACX,CAAC;QACD,MAAM,eAAe,GAAG,oCAAoC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QACxF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,kDAAkD;YAClD,SAAS;QACX,CAAC;QACD,sCAAsC;QACtC,wCAAwC;QACxC,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,yBAAyB,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3G,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAElC,sCAAsC;QACtC,mEAAmE;QACnE,gCAAgC;QAChC,MAAM,qBAAqB,GAAG,+BAA+B,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QACzF,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;YACzC,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,EAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;AACH,CAAC;AACD;;;;GAIG;AACH,SAAS,qBAAqB,CAC1B,kBAA2D,EAC3D,WAAwE;IAC1E,IAAI,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACvD,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACvF,OAAO,IAAI,CAAC,KAAK,CAAC;QACpB,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AACD;;;;;GAKG;AACH,SAAS,4BAA4B,CAAC,KAAyB;IAC7D,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACnE,MAAM,mBAAmB,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACvF,OAAO,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,mBAAmB,CAAC,CAAC;AACpG,CAAC;AAED;;;GAGG;AACH,SAAS,oCAAoC,CACzC,YAA+C,EAC/C,WAAwE;IAC1E,+DAA+D;IAC/D,mEAAmE;IACnE,OAAO,0BAA0B,CACtB,YAAY,EAAE,WAAW,EAAE,4BAA4B,EAAE,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC;SACnG,EAAE,CAAC,CAAC,CAAC,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAS,+BAA+B,CACpC,YAA+C,EAC/C,WAAwE;IAC1E,+DAA+D;IAC/D,mEAAmE;IACnE,OAAO,0BAA0B,CAC7B,YAAY,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAClG,CAAC;AAED;;;;GAIG;AACH,SAAS,0BAA0B,CAC/B,IAAwB,EAAE,WAAwE,EAClG,eAA0D,EAC1D,eAAuD;IACzD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,cAAc,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5C,MAAM,gBAAgB,GAAG,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;iBAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxC,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,IAAI;IAWlB,OAAO;QACL,yBAAyB;QACzB,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as flowsHandlerData} from './FlowsHandler.js';\nimport {data as rendererHandlerData} from './RendererHandler.js';\n\nconst schedulerToRunEntryPoints: Map<Types.Events.Event, Types.Events.Event[]> = new Map();\nconst asyncCallToScheduler: Map<Types.Events.SyntheticProfileCall, {taskName: string, scheduler: Types.Events.Event}> =\n new Map();\n\nexport function reset(): void {\n schedulerToRunEntryPoints.clear();\n asyncCallToScheduler.clear();\n}\n\nexport function handleEvent(_: Types.Events.Event): void {\n}\n\nexport async function finalize(): Promise<void> {\n const {flows} = flowsHandlerData();\n const {entryToNode} = rendererHandlerData();\n // Process async task flows\n for (const flow of flows) {\n const asyncTaskScheduled = flow.at(0);\n if (!asyncTaskScheduled || !Types.Events.isDebuggerAsyncTaskScheduled(asyncTaskScheduled)) {\n continue;\n }\n const taskName = asyncTaskScheduled.args.taskName;\n const asyncTaskRun = flow.at(1);\n if (!asyncTaskRun || !Types.Events.isDebuggerAsyncTaskRun(asyncTaskRun)) {\n // Unexpected flow shape, ignore.\n continue;\n }\n const asyncCaller = findNearestJSAncestor(asyncTaskScheduled, entryToNode);\n if (!asyncCaller) {\n // Unexpected async call trace data shape, ignore.\n continue;\n }\n const asyncEntryPoint = findFirstJsInvocationForAsyncTaskRun(asyncTaskRun, entryToNode);\n if (!asyncEntryPoint) {\n // Unexpected async call trace data shape, ignore.\n continue;\n }\n // Set scheduler -> schedulee mapping.\n // The schedulee being the JS entrypoint\n const entryPoints = Platform.MapUtilities.getWithDefault(schedulerToRunEntryPoints, asyncCaller, () => []);\n entryPoints.push(asyncEntryPoint);\n\n // Set schedulee -> scheduler mapping.\n // The schedulees being the JS calls (instead of the entrypoints as\n // above, for usage ergonomics).\n const scheduledProfileCalls = findFirstJSCallsForAsyncTaskRun(asyncTaskRun, entryToNode);\n for (const call of scheduledProfileCalls) {\n asyncCallToScheduler.set(call, {taskName, scheduler: asyncCaller});\n }\n }\n}\n/**\n * Given a DebuggerAsyncTaskScheduled event, returns its closest\n * ProfileCall or JS invocation ancestor, which represents the JS call\n * that scheduled the async task.\n */\nfunction findNearestJSAncestor(\n asyncTaskScheduled: Types.Events.DebuggerAsyncTaskScheduled,\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>): Types.Events.Event|null {\n let node = entryToNode.get(asyncTaskScheduled)?.parent;\n while (node) {\n if (Types.Events.isProfileCall(node.entry) || acceptJSInvocationsPredicate(node.entry)) {\n return node.entry;\n }\n node = node.parent;\n }\n return null;\n}\n/**\n * Entrypoints to JS execution in the timeline. We ignore those starting\n * with 'v8' because they aren't shown in the timeline, and ultimately\n * this function's output results in \"initiated\" events, so ideally this\n * returns events that end up in the flame chart.\n */\nfunction acceptJSInvocationsPredicate(event: Types.Events.Event): event is Types.Events.Event {\n const eventIsConsoleRunTask = Types.Events.isConsoleRunTask(event);\n const eventIsV8EntryPoint = event.name.startsWith('v8') || event.name.startsWith('V8');\n return Types.Events.isJSInvocationEvent(event) && (eventIsConsoleRunTask || !eventIsV8EntryPoint);\n}\n\n/**\n * Given a DebuggerAsyncTaskRun event, returns its closest JS entry\n * point descendant, which contains the task being scheduled.\n */\nfunction findFirstJsInvocationForAsyncTaskRun(\n asyncTaskRun: Types.Events.DebuggerAsyncTaskRun,\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>): Types.Events.Event|undefined {\n // Ignore descendants of other DebuggerAsyncTaskRuns since they\n // are part of another async task and have to be handled separately\n return findFirstDescendantsOfType(\n asyncTaskRun, entryToNode, acceptJSInvocationsPredicate, Types.Events.isDebuggerAsyncTaskRun)\n .at(0);\n}\n\n/**\n * Given an async task run event, returns the top level call frames\n * (profile calls) directly called by the async task. This implies that\n * any profile calls under another async task run event are ignored.\n * These profile calls represent the JS task being scheduled, AKA\n * the other part of the async stack.\n *\n * For example, here the profile calls \"js 1\", \"js 2\" and \"js 4\" would\n * be returned:\n *\n * |------------------Async Task Run------------------|\n * |--FunctionCall--| |--FunctionCall--|\n * |-js 1-||-js 2-| |-js 4-|\n * |-js 3-|\n *\n * But here, only \"js 1\" and \"js 2\" would be returned:\n *\n * |------------------Async Task Run------------------|\n * |--FunctionCall--| |------------------------|\n * |-js 1-||-js 2-| |---Async Task Run--|\n * |-js 3-| |--FunctionCall--|\n * |-js 4-|\n */\nfunction findFirstJSCallsForAsyncTaskRun(\n asyncTaskRun: Types.Events.DebuggerAsyncTaskRun,\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>): Types.Events.SyntheticProfileCall[] {\n // Ignore descendants of other DebuggerAsyncTaskRuns since they\n // are part of another async task and have to be handled separately\n return findFirstDescendantsOfType(\n asyncTaskRun, entryToNode, Types.Events.isProfileCall, Types.Events.isDebuggerAsyncTaskRun);\n}\n\n/**\n * Given a root event returns all the first descendants that meet a\n * predicate condition (predicateAccept) while ignoring subtrees whose\n * top event meets an ignore condition (predicateIgnore).\n */\nfunction findFirstDescendantsOfType<T extends Types.Events.Event>(\n root: Types.Events.Event, entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>,\n predicateAccept: (event: Types.Events.Event) => event is T,\n predicateIgnore: (event: Types.Events.Event) => boolean): T[] {\n const node = entryToNode.get(root);\n if (!node) {\n return [];\n }\n const childrenGroups = [[...node.children]];\n const firstDescendants = [];\n for (let i = 0; i < childrenGroups.length; i++) {\n const siblings = childrenGroups[i];\n for (let j = 0; j < siblings.length; j++) {\n const node = siblings[j];\n if (predicateAccept(node.entry)) {\n firstDescendants.push(node.entry);\n } else if (!predicateIgnore(node.entry)) {\n childrenGroups.push([...node.children]);\n }\n }\n }\n return firstDescendants;\n}\n\nexport function data(): {\n // Given a profile call, returns the JS entrypoint it scheduled (if any).\n // For example, given a setTimeout call, returns the JS entry point\n // trace event for the timeout callback run event (usually a\n // FunctionCall event).\n schedulerToRunEntryPoints: typeof schedulerToRunEntryPoints,\n // Given a profile call, returns the profile call that scheduled it.\n // For example given a timeout callback run event, returns its\n // setTimeout call event.\n asyncCallToScheduler: typeof asyncCallToScheduler,\n} {\n return {\n schedulerToRunEntryPoints,\n asyncCallToScheduler,\n };\n}\n\nexport function deps(): ['Renderer', 'Flows'] {\n return ['Renderer', 'Flows'];\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
export interface DOMStatsData {
|
|
3
|
+
domStatsByFrameId: Map<string, Types.Events.DOMStats[]>;
|
|
4
|
+
}
|
|
5
|
+
export declare function reset(): void;
|
|
6
|
+
export declare function handleEvent(event: Types.Events.Event): void;
|
|
7
|
+
export declare function finalize(): Promise<void>;
|
|
8
|
+
export declare function data(): DOMStatsData;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2025 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
import * as Platform from '../../../core/platform/platform.js';
|
|
5
|
+
import * as Types from '../types/types.js';
|
|
6
|
+
const domStatsByFrameId = new Map();
|
|
7
|
+
export function reset() {
|
|
8
|
+
domStatsByFrameId.clear();
|
|
9
|
+
}
|
|
10
|
+
export function handleEvent(event) {
|
|
11
|
+
if (!Types.Events.isDOMStats(event)) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const domStatEvents = Platform.MapUtilities.getWithDefault(domStatsByFrameId, event.args.data.frame, () => []);
|
|
15
|
+
domStatEvents.push(event);
|
|
16
|
+
}
|
|
17
|
+
export async function finalize() {
|
|
18
|
+
}
|
|
19
|
+
export function data() {
|
|
20
|
+
return { domStatsByFrameId };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=DOMStatsHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DOMStatsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/DOMStatsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAM3C,MAAM,iBAAiB,GAAsC,IAAI,GAAG,EAAE,CAAC;AAEvE,MAAM,UAAU,KAAK;IACnB,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO;IACT,CAAC;IACD,MAAM,aAAa,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/G,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;AAC9B,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,EAAC,iBAAiB,EAAC,CAAC;AAC7B,CAAC","sourcesContent":["// Copyright 2025 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Types from '../types/types.js';\n\nexport interface DOMStatsData {\n domStatsByFrameId: Map<string, Types.Events.DOMStats[]>;\n}\n\nconst domStatsByFrameId: DOMStatsData['domStatsByFrameId'] = new Map();\n\nexport function reset(): void {\n domStatsByFrameId.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (!Types.Events.isDOMStats(event)) {\n return;\n }\n const domStatEvents = Platform.MapUtilities.getWithDefault(domStatsByFrameId, event.args.data.frame, () => []);\n domStatEvents.push(event);\n}\n\nexport async function finalize(): Promise<void> {\n}\n\nexport function data(): DOMStatsData {\n return {domStatsByFrameId};\n}\n"]}
|
|
@@ -5,11 +5,89 @@ export interface ExtensionTraceData {
|
|
|
5
5
|
extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];
|
|
6
6
|
extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];
|
|
7
7
|
entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;
|
|
8
|
+
syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[];
|
|
8
9
|
}
|
|
9
10
|
export declare function handleEvent(_event: Types.Events.Event): void;
|
|
10
11
|
export declare function reset(): void;
|
|
11
12
|
export declare function finalize(): Promise<void>;
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Extracts extension entries from console.timeStamp events.
|
|
15
|
+
*
|
|
16
|
+
* Entries are built by pairing `console.timeStamp` events based on
|
|
17
|
+
* their names. When a `console.timeStamp` event includes a `start`
|
|
18
|
+
* argument (and optionally an `end` argument), it attempts to find
|
|
19
|
+
* previously recorded `console.timeStamp` events with names matching
|
|
20
|
+
* the `start` and `end` values. These matching events are then used to
|
|
21
|
+
* determine the start and end times of the new entry.
|
|
22
|
+
*
|
|
23
|
+
* If a `console.timeStamp` event includes data for a custom track
|
|
24
|
+
* (specified by the `track` argument), an extension track entry is
|
|
25
|
+
* created and added to the `extensionTrackEntries` array. These entries
|
|
26
|
+
* are used to visualize custom tracks in the Performance panel.
|
|
27
|
+
*
|
|
28
|
+
* If a `console.timeStamp` event includes data for a custom track
|
|
29
|
+
* (specified by the `track` argument), an extension track entry is
|
|
30
|
+
* created and added to the `extensionTrackEntries` array. These entries
|
|
31
|
+
* are used to visualize custom tracks in the Performance panel.
|
|
32
|
+
*
|
|
33
|
+
* If a `console.timeStamp` event does not specify a custom track but
|
|
34
|
+
* includes a start and/or end time (referencing other
|
|
35
|
+
* `console.timeStamp` names), a synthetic console time stamp entry is
|
|
36
|
+
* created and added to the `syntheticConsoleEntriesForTimingsTrack`
|
|
37
|
+
* array. These entries are displayed in the "Timings" track.
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractConsoleAPIExtensionEntries(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Extracts extension entries from Performance API events (marks and
|
|
42
|
+
* measures).
|
|
43
|
+
* It specifically looks for events that contain extension-specific data
|
|
44
|
+
* within their `detail` property.
|
|
45
|
+
*
|
|
46
|
+
* If an event's `detail` property can be parsed as a JSON object and
|
|
47
|
+
* contains a `devtools` field with a valid extension payload, a
|
|
48
|
+
* synthetic extension entry is created. The type of extension entry
|
|
49
|
+
* created depends on the payload:
|
|
50
|
+
*
|
|
51
|
+
* - If the payload conforms to `ExtensionPayloadMarker`, a
|
|
52
|
+
* `SyntheticExtensionMarker` is created and added to the
|
|
53
|
+
* `extensionMarkers` array. These markers represent single points in
|
|
54
|
+
* time.
|
|
55
|
+
* - If the payload conforms to `ExtensionPayloadTrackEntry`, a
|
|
56
|
+
* `SyntheticExtensionTrackEntry` is created and added to the
|
|
57
|
+
* `extensionTrackEntries` array. These entries represent events with
|
|
58
|
+
* a duration and are displayed on custom tracks in the Performance
|
|
59
|
+
* panel.
|
|
60
|
+
*
|
|
61
|
+
* **Note:** Only events with a `detail` property that contains valid
|
|
62
|
+
* extension data are processed. Other `performance.mark` and
|
|
63
|
+
* `performance.measure` events are ignored.
|
|
64
|
+
*
|
|
65
|
+
* @param timings An array of `SyntheticUserTimingPair` or
|
|
66
|
+
* `PerformanceMark` events, typically obtained from the
|
|
67
|
+
* `UserTimingsHandler`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractPerformanceAPIExtensionEntries(timings: (Types.Events.SyntheticUserTimingPair | Types.Events.PerformanceMark)[]): void;
|
|
70
|
+
export declare function extensionDataInPerformanceTiming(timing: Types.Events.SyntheticUserTimingPair | Types.Events.PerformanceMark): Types.Extensions.ExtensionDataPayload | null;
|
|
71
|
+
/**
|
|
72
|
+
* Extracts extension data from a `console.timeStamp` event.
|
|
73
|
+
*
|
|
74
|
+
* Checks if a `console.timeStamp` event contains data intended for
|
|
75
|
+
* creating a custom track entry in the DevTools Performance panel. It
|
|
76
|
+
* specifically looks for a `track` argument within the event's data.
|
|
77
|
+
*
|
|
78
|
+
* If a `track` argument is present (and not an empty string), the
|
|
79
|
+
* function constructs an `ExtensionTrackEntryPayload` object containing
|
|
80
|
+
* the track name, an optional color, an optional track group. This
|
|
81
|
+
* payload is then used to create a `SyntheticExtensionTrackEntry`.
|
|
82
|
+
*
|
|
83
|
+
* **Note:** The `color` argument is optional and its type is validated
|
|
84
|
+
* against a predefined palette (see
|
|
85
|
+
* `ExtensionUI::extensionEntryColor`).
|
|
86
|
+
*
|
|
87
|
+
* @param timeStamp The `ConsoleTimeStamp` event to extract data from.
|
|
88
|
+
* @return An `ExtensionTrackEntryPayload` object if the event contains
|
|
89
|
+
* valid extension data for a track entry, or `null` otherwise.
|
|
90
|
+
*/
|
|
91
|
+
export declare function extensionDataInConsoleTimeStamp(timeStamp: Types.Events.ConsoleTimeStamp): Types.Extensions.ExtensionTrackEntryPayload | null;
|
|
14
92
|
export declare function data(): ExtensionTraceData;
|
|
15
93
|
export declare function deps(): HandlerName[];
|
|
@@ -4,18 +4,22 @@
|
|
|
4
4
|
import * as Helpers from '../helpers/helpers.js';
|
|
5
5
|
import * as Types from '../types/types.js';
|
|
6
6
|
import { data as userTimingsData } from './UserTimingsHandler.js';
|
|
7
|
-
const
|
|
7
|
+
const extensionTrackEntries = [];
|
|
8
8
|
const extensionTrackData = [];
|
|
9
9
|
const extensionMarkers = [];
|
|
10
10
|
const entryToNode = new Map();
|
|
11
|
+
const timeStampByName = new Map();
|
|
12
|
+
const syntheticConsoleEntriesForTimingsTrack = [];
|
|
11
13
|
export function handleEvent(_event) {
|
|
12
14
|
// Implementation not needed because data is sourced from UserTimingsHandler
|
|
13
15
|
}
|
|
14
16
|
export function reset() {
|
|
15
|
-
|
|
17
|
+
extensionTrackEntries.length = 0;
|
|
18
|
+
syntheticConsoleEntriesForTimingsTrack.length = 0;
|
|
16
19
|
extensionTrackData.length = 0;
|
|
17
20
|
extensionMarkers.length = 0;
|
|
18
21
|
entryToNode.clear();
|
|
22
|
+
timeStampByName.clear();
|
|
19
23
|
}
|
|
20
24
|
export async function finalize() {
|
|
21
25
|
createExtensionFlameChartEntries();
|
|
@@ -24,12 +28,122 @@ function createExtensionFlameChartEntries() {
|
|
|
24
28
|
const pairedMeasures = userTimingsData().performanceMeasures;
|
|
25
29
|
const marks = userTimingsData().performanceMarks;
|
|
26
30
|
const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
extractPerformanceAPIExtensionEntries(mergedRawExtensionEvents);
|
|
32
|
+
extractConsoleAPIExtensionEntries();
|
|
33
|
+
// extensionTrackEntries is filled by the above two calls.
|
|
34
|
+
Helpers.Trace.sortTraceEventsInPlace(extensionTrackEntries);
|
|
35
|
+
Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionTrackEntries, extensionTrackData, entryToNode);
|
|
29
36
|
}
|
|
30
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Extracts extension entries from console.timeStamp events.
|
|
39
|
+
*
|
|
40
|
+
* Entries are built by pairing `console.timeStamp` events based on
|
|
41
|
+
* their names. When a `console.timeStamp` event includes a `start`
|
|
42
|
+
* argument (and optionally an `end` argument), it attempts to find
|
|
43
|
+
* previously recorded `console.timeStamp` events with names matching
|
|
44
|
+
* the `start` and `end` values. These matching events are then used to
|
|
45
|
+
* determine the start and end times of the new entry.
|
|
46
|
+
*
|
|
47
|
+
* If a `console.timeStamp` event includes data for a custom track
|
|
48
|
+
* (specified by the `track` argument), an extension track entry is
|
|
49
|
+
* created and added to the `extensionTrackEntries` array. These entries
|
|
50
|
+
* are used to visualize custom tracks in the Performance panel.
|
|
51
|
+
*
|
|
52
|
+
* If a `console.timeStamp` event includes data for a custom track
|
|
53
|
+
* (specified by the `track` argument), an extension track entry is
|
|
54
|
+
* created and added to the `extensionTrackEntries` array. These entries
|
|
55
|
+
* are used to visualize custom tracks in the Performance panel.
|
|
56
|
+
*
|
|
57
|
+
* If a `console.timeStamp` event does not specify a custom track but
|
|
58
|
+
* includes a start and/or end time (referencing other
|
|
59
|
+
* `console.timeStamp` names), a synthetic console time stamp entry is
|
|
60
|
+
* created and added to the `syntheticConsoleEntriesForTimingsTrack`
|
|
61
|
+
* array. These entries are displayed in the "Timings" track.
|
|
62
|
+
*/
|
|
63
|
+
export function extractConsoleAPIExtensionEntries() {
|
|
64
|
+
const consoleTimeStamps = userTimingsData().timestampEvents;
|
|
65
|
+
for (const currentTimeStamp of consoleTimeStamps) {
|
|
66
|
+
const timeStampName = String(currentTimeStamp.args.data.name);
|
|
67
|
+
timeStampByName.set(timeStampName, currentTimeStamp);
|
|
68
|
+
const extensionData = extensionDataInConsoleTimeStamp(currentTimeStamp);
|
|
69
|
+
const startName = currentTimeStamp.args.data.start;
|
|
70
|
+
const endName = currentTimeStamp.args.data.end;
|
|
71
|
+
if (!extensionData && !startName && !endName) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const startTimeStamp = startName ? timeStampByName.get(String(startName)) : undefined;
|
|
75
|
+
const endTimeStamp = endName ? timeStampByName.get(String(endName)) : undefined;
|
|
76
|
+
if (endTimeStamp && !startTimeStamp) {
|
|
77
|
+
// Invalid data
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const entryStartTime = startTimeStamp?.ts ?? currentTimeStamp.ts;
|
|
81
|
+
const entryEndTime = endTimeStamp?.ts ?? currentTimeStamp.ts;
|
|
82
|
+
if (extensionData) {
|
|
83
|
+
const unregisteredExtensionEntry = {
|
|
84
|
+
...currentTimeStamp,
|
|
85
|
+
name: timeStampName,
|
|
86
|
+
cat: 'devtools.extension',
|
|
87
|
+
args: extensionData,
|
|
88
|
+
rawSourceEvent: currentTimeStamp,
|
|
89
|
+
dur: Types.Timing.MicroSeconds(entryEndTime - entryStartTime),
|
|
90
|
+
ts: entryStartTime,
|
|
91
|
+
};
|
|
92
|
+
const extensionEntry = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()
|
|
93
|
+
.registerSyntheticEvent(unregisteredExtensionEntry);
|
|
94
|
+
extensionTrackEntries.push(extensionEntry);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// If no extension data is found in the entry (no custom track name
|
|
98
|
+
// was passed), but the entry has a duration. we still save it here
|
|
99
|
+
// to be added in the timings track. Note that timings w/o duration
|
|
100
|
+
// and extension data are already handled by the UserTimingsHandler.
|
|
101
|
+
const unregisteredSyntheticTimeStamp = {
|
|
102
|
+
...currentTimeStamp,
|
|
103
|
+
name: timeStampName,
|
|
104
|
+
cat: 'disabled-by-default-v8.inspector',
|
|
105
|
+
ph: "X" /* Types.Events.Phase.COMPLETE */,
|
|
106
|
+
ts: entryStartTime,
|
|
107
|
+
dur: Types.Timing.MicroSeconds(entryEndTime - entryStartTime),
|
|
108
|
+
rawSourceEvent: currentTimeStamp
|
|
109
|
+
};
|
|
110
|
+
const syntheticTimeStamp = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()
|
|
111
|
+
.registerSyntheticEvent(unregisteredSyntheticTimeStamp);
|
|
112
|
+
syntheticConsoleEntriesForTimingsTrack.push(syntheticTimeStamp);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extracts extension entries from Performance API events (marks and
|
|
117
|
+
* measures).
|
|
118
|
+
* It specifically looks for events that contain extension-specific data
|
|
119
|
+
* within their `detail` property.
|
|
120
|
+
*
|
|
121
|
+
* If an event's `detail` property can be parsed as a JSON object and
|
|
122
|
+
* contains a `devtools` field with a valid extension payload, a
|
|
123
|
+
* synthetic extension entry is created. The type of extension entry
|
|
124
|
+
* created depends on the payload:
|
|
125
|
+
*
|
|
126
|
+
* - If the payload conforms to `ExtensionPayloadMarker`, a
|
|
127
|
+
* `SyntheticExtensionMarker` is created and added to the
|
|
128
|
+
* `extensionMarkers` array. These markers represent single points in
|
|
129
|
+
* time.
|
|
130
|
+
* - If the payload conforms to `ExtensionPayloadTrackEntry`, a
|
|
131
|
+
* `SyntheticExtensionTrackEntry` is created and added to the
|
|
132
|
+
* `extensionTrackEntries` array. These entries represent events with
|
|
133
|
+
* a duration and are displayed on custom tracks in the Performance
|
|
134
|
+
* panel.
|
|
135
|
+
*
|
|
136
|
+
* **Note:** Only events with a `detail` property that contains valid
|
|
137
|
+
* extension data are processed. Other `performance.mark` and
|
|
138
|
+
* `performance.measure` events are ignored.
|
|
139
|
+
*
|
|
140
|
+
* @param timings An array of `SyntheticUserTimingPair` or
|
|
141
|
+
* `PerformanceMark` events, typically obtained from the
|
|
142
|
+
* `UserTimingsHandler`.
|
|
143
|
+
*/
|
|
144
|
+
export function extractPerformanceAPIExtensionEntries(timings) {
|
|
31
145
|
for (const timing of timings) {
|
|
32
|
-
const extensionPayload =
|
|
146
|
+
const extensionPayload = extensionDataInPerformanceTiming(timing);
|
|
33
147
|
if (!extensionPayload) {
|
|
34
148
|
// Not an extension user timing.
|
|
35
149
|
continue;
|
|
@@ -37,8 +151,8 @@ export function extractExtensionEntries(timings) {
|
|
|
37
151
|
const extensionSyntheticEntry = {
|
|
38
152
|
name: timing.name,
|
|
39
153
|
ph: "X" /* Types.Events.Phase.COMPLETE */,
|
|
40
|
-
pid:
|
|
41
|
-
tid:
|
|
154
|
+
pid: timing.pid,
|
|
155
|
+
tid: timing.tid,
|
|
42
156
|
ts: timing.ts,
|
|
43
157
|
dur: timing.dur,
|
|
44
158
|
cat: 'devtools.extension',
|
|
@@ -54,12 +168,12 @@ export function extractExtensionEntries(timings) {
|
|
|
54
168
|
if (Types.Extensions.isExtensionPayloadTrackEntry(extensionSyntheticEntry.args)) {
|
|
55
169
|
const extensionTrackEntry = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()
|
|
56
170
|
.registerSyntheticEvent(extensionSyntheticEntry);
|
|
57
|
-
|
|
171
|
+
extensionTrackEntries.push(extensionTrackEntry);
|
|
58
172
|
continue;
|
|
59
173
|
}
|
|
60
174
|
}
|
|
61
175
|
}
|
|
62
|
-
export function
|
|
176
|
+
export function extensionDataInPerformanceTiming(timing) {
|
|
63
177
|
const timingDetail = Types.Events.isPerformanceMark(timing) ? timing.args.data?.detail : timing.args.data.beginEvent.args.detail;
|
|
64
178
|
if (!timingDetail) {
|
|
65
179
|
return null;
|
|
@@ -80,17 +194,53 @@ export function extensionDataInTiming(timing) {
|
|
|
80
194
|
}
|
|
81
195
|
return detailObj.devtools;
|
|
82
196
|
}
|
|
83
|
-
catch
|
|
197
|
+
catch {
|
|
84
198
|
// No need to worry about this error, just discard this event and don't
|
|
85
199
|
// treat it as having any useful information for the purposes of extensions
|
|
86
200
|
return null;
|
|
87
201
|
}
|
|
88
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Extracts extension data from a `console.timeStamp` event.
|
|
205
|
+
*
|
|
206
|
+
* Checks if a `console.timeStamp` event contains data intended for
|
|
207
|
+
* creating a custom track entry in the DevTools Performance panel. It
|
|
208
|
+
* specifically looks for a `track` argument within the event's data.
|
|
209
|
+
*
|
|
210
|
+
* If a `track` argument is present (and not an empty string), the
|
|
211
|
+
* function constructs an `ExtensionTrackEntryPayload` object containing
|
|
212
|
+
* the track name, an optional color, an optional track group. This
|
|
213
|
+
* payload is then used to create a `SyntheticExtensionTrackEntry`.
|
|
214
|
+
*
|
|
215
|
+
* **Note:** The `color` argument is optional and its type is validated
|
|
216
|
+
* against a predefined palette (see
|
|
217
|
+
* `ExtensionUI::extensionEntryColor`).
|
|
218
|
+
*
|
|
219
|
+
* @param timeStamp The `ConsoleTimeStamp` event to extract data from.
|
|
220
|
+
* @return An `ExtensionTrackEntryPayload` object if the event contains
|
|
221
|
+
* valid extension data for a track entry, or `null` otherwise.
|
|
222
|
+
*/
|
|
223
|
+
export function extensionDataInConsoleTimeStamp(timeStamp) {
|
|
224
|
+
const trackName = timeStamp.args.data.track;
|
|
225
|
+
if (trackName === '' || trackName === undefined) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
// the color is defaulted to primary if it's value isn't one from
|
|
230
|
+
// the defined palette (see ExtensionUI::extensionEntryColor) so
|
|
231
|
+
// we don't need to check the value is valid here.
|
|
232
|
+
color: String(timeStamp.args.data.color),
|
|
233
|
+
track: String(trackName),
|
|
234
|
+
dataType: 'track-entry',
|
|
235
|
+
trackGroup: timeStamp.args.data.trackGroup !== undefined ? String(timeStamp.args.data.trackGroup) : undefined
|
|
236
|
+
};
|
|
237
|
+
}
|
|
89
238
|
export function data() {
|
|
90
239
|
return {
|
|
91
240
|
entryToNode,
|
|
92
|
-
extensionTrackData
|
|
93
|
-
extensionMarkers
|
|
241
|
+
extensionTrackData,
|
|
242
|
+
extensionMarkers,
|
|
243
|
+
syntheticConsoleEntriesForTimingsTrack,
|
|
94
244
|
};
|
|
95
245
|
}
|
|
96
246
|
export function deps() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {HandlerName} from './types.js';\nimport {data as userTimingsData} from './UserTimingsHandler.js';\n\nconst extensionFlameChartEntries: Types.Extensions.SyntheticExtensionTrackEntry[] = [];\nconst extensionTrackData: Types.Extensions.ExtensionTrackData[] = [];\nconst extensionMarkers: Types.Extensions.SyntheticExtensionMarker[] = [];\nconst entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode> = new Map();\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;\n}\n\nexport function handleEvent(_event: Types.Events.Event): void {\n // Implementation not needed because data is sourced from UserTimingsHandler\n}\n\nexport function reset(): void {\n extensionFlameChartEntries.length = 0;\n extensionTrackData.length = 0;\n extensionMarkers.length = 0;\n entryToNode.clear();\n}\n\nexport async function finalize(): Promise<void> {\n createExtensionFlameChartEntries();\n}\n\nfunction createExtensionFlameChartEntries(): void {\n const pairedMeasures: readonly Types.Events.SyntheticUserTimingPair[] = userTimingsData().performanceMeasures;\n const marks: readonly Types.Events.PerformanceMark[] = userTimingsData().performanceMarks;\n const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);\n\n extractExtensionEntries(mergedRawExtensionEvents);\n Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionFlameChartEntries, extensionTrackData, entryToNode);\n}\n\nexport function extractExtensionEntries(timings: (Types.Events.SyntheticUserTimingPair|Types.Events.PerformanceMark)[]):\n void {\n for (const timing of timings) {\n const extensionPayload = extensionDataInTiming(timing);\n if (!extensionPayload) {\n // Not an extension user timing.\n continue;\n }\n\n const extensionSyntheticEntry = {\n name: timing.name,\n ph: Types.Events.Phase.COMPLETE,\n pid: Types.Events.ProcessID(0),\n tid: Types.Events.ThreadID(0),\n ts: timing.ts,\n dur: timing.dur as Types.Timing.MicroSeconds,\n cat: 'devtools.extension',\n args: extensionPayload,\n rawSourceEvent: Types.Events.isSyntheticUserTiming(timing) ? timing.rawSourceEvent : timing,\n };\n\n if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {\n const extensionMarker =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Extensions.SyntheticExtensionMarker>(\n extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionMarker, '_tag'>);\n extensionMarkers.push(extensionMarker);\n continue;\n }\n\n if (Types.Extensions.isExtensionPayloadTrackEntry(extensionSyntheticEntry.args)) {\n const extensionTrackEntry =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Extensions.SyntheticExtensionTrackEntry>(\n extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionTrackEntry, '_tag'>);\n extensionFlameChartEntries.push(extensionTrackEntry);\n continue;\n }\n }\n}\n\nexport function extensionDataInTiming(timing: Types.Events.SyntheticUserTimingPair|\n Types.Events.PerformanceMark): Types.Extensions.ExtensionDataPayload|null {\n const timingDetail =\n Types.Events.isPerformanceMark(timing) ? timing.args.data?.detail : timing.args.data.beginEvent.args.detail;\n if (!timingDetail) {\n return null;\n }\n try {\n // Attempt to parse the detail as an object that might be coming from a\n // DevTools Perf extension.\n // Wrapped in a try-catch because timingDetail might either:\n // 1. Not be `json.parse`-able (it should, but just in case...)\n // 2.Not be an object - in which case the `in` check will error.\n // If we hit either of these cases, we just ignore this mark and move on.\n const detailObj = JSON.parse(timingDetail);\n if (!('devtools' in detailObj)) {\n return null;\n }\n if (!Types.Extensions.isValidExtensionPayload(detailObj.devtools)) {\n return null;\n }\n return detailObj.devtools;\n } catch (e) {\n // No need to worry about this error, just discard this event and don't\n // treat it as having any useful information for the purposes of extensions\n return null;\n }\n}\n\nexport function data(): ExtensionTraceData {\n return {\n entryToNode,\n extensionTrackData: [...extensionTrackData],\n extensionMarkers: [...extensionMarkers],\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['UserTimings'];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport type {HandlerName} from './types.js';\nimport {data as userTimingsData} from './UserTimingsHandler.js';\n\nconst extensionTrackEntries: Types.Extensions.SyntheticExtensionTrackEntry[] = [];\nconst extensionTrackData: Types.Extensions.ExtensionTrackData[] = [];\nconst extensionMarkers: Types.Extensions.SyntheticExtensionMarker[] = [];\nconst entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode> = new Map();\nconst timeStampByName: Map<string, Types.Events.ConsoleTimeStamp> = new Map();\n\nconst syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[] = [];\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n entryToNode: Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>;\n syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[];\n}\n\nexport function handleEvent(_event: Types.Events.Event): void {\n // Implementation not needed because data is sourced from UserTimingsHandler\n}\n\nexport function reset(): void {\n extensionTrackEntries.length = 0;\n syntheticConsoleEntriesForTimingsTrack.length = 0;\n extensionTrackData.length = 0;\n extensionMarkers.length = 0;\n entryToNode.clear();\n timeStampByName.clear();\n}\n\nexport async function finalize(): Promise<void> {\n createExtensionFlameChartEntries();\n}\n\nfunction createExtensionFlameChartEntries(): void {\n const pairedMeasures: readonly Types.Events.SyntheticUserTimingPair[] = userTimingsData().performanceMeasures;\n const marks: readonly Types.Events.PerformanceMark[] = userTimingsData().performanceMarks;\n const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);\n\n extractPerformanceAPIExtensionEntries(mergedRawExtensionEvents);\n extractConsoleAPIExtensionEntries();\n // extensionTrackEntries is filled by the above two calls.\n Helpers.Trace.sortTraceEventsInPlace(extensionTrackEntries);\n Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionTrackEntries, extensionTrackData, entryToNode);\n}\n\n/**\n * Extracts extension entries from console.timeStamp events.\n *\n * Entries are built by pairing `console.timeStamp` events based on\n * their names. When a `console.timeStamp` event includes a `start`\n * argument (and optionally an `end` argument), it attempts to find\n * previously recorded `console.timeStamp` events with names matching\n * the `start` and `end` values. These matching events are then used to\n * determine the start and end times of the new entry.\n *\n * If a `console.timeStamp` event includes data for a custom track\n * (specified by the `track` argument), an extension track entry is\n * created and added to the `extensionTrackEntries` array. These entries\n * are used to visualize custom tracks in the Performance panel.\n *\n * If a `console.timeStamp` event includes data for a custom track\n * (specified by the `track` argument), an extension track entry is\n * created and added to the `extensionTrackEntries` array. These entries\n * are used to visualize custom tracks in the Performance panel.\n *\n * If a `console.timeStamp` event does not specify a custom track but\n * includes a start and/or end time (referencing other\n * `console.timeStamp` names), a synthetic console time stamp entry is\n * created and added to the `syntheticConsoleEntriesForTimingsTrack`\n * array. These entries are displayed in the \"Timings\" track.\n */\nexport function extractConsoleAPIExtensionEntries(): void {\n const consoleTimeStamps: readonly Types.Events.ConsoleTimeStamp[] = userTimingsData().timestampEvents;\n for (const currentTimeStamp of consoleTimeStamps) {\n const timeStampName = String(currentTimeStamp.args.data.name);\n timeStampByName.set(timeStampName, currentTimeStamp);\n const extensionData = extensionDataInConsoleTimeStamp(currentTimeStamp);\n const startName = currentTimeStamp.args.data.start;\n const endName = currentTimeStamp.args.data.end;\n if (!extensionData && !startName && !endName) {\n continue;\n }\n const startTimeStamp = startName ? timeStampByName.get(String(startName)) : undefined;\n const endTimeStamp = endName ? timeStampByName.get(String(endName)) : undefined;\n if (endTimeStamp && !startTimeStamp) {\n // Invalid data\n continue;\n }\n const entryStartTime = startTimeStamp?.ts ?? currentTimeStamp.ts;\n const entryEndTime = endTimeStamp?.ts ?? currentTimeStamp.ts;\n if (extensionData) {\n const unregisteredExtensionEntry: Omit<Types.Extensions.SyntheticExtensionTrackEntry, '_tag'> = {\n ...currentTimeStamp,\n name: timeStampName,\n cat: 'devtools.extension',\n args: extensionData,\n rawSourceEvent: currentTimeStamp,\n dur: Types.Timing.MicroSeconds(entryEndTime - entryStartTime),\n ts: entryStartTime,\n };\n const extensionEntry =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Extensions.SyntheticExtensionTrackEntry>(unregisteredExtensionEntry);\n extensionTrackEntries.push(extensionEntry);\n continue;\n }\n // If no extension data is found in the entry (no custom track name\n // was passed), but the entry has a duration. we still save it here\n // to be added in the timings track. Note that timings w/o duration\n // and extension data are already handled by the UserTimingsHandler.\n const unregisteredSyntheticTimeStamp: Omit<Types.Events.SyntheticConsoleTimeStamp, '_tag'> = {\n ...currentTimeStamp,\n name: timeStampName,\n cat: 'disabled-by-default-v8.inspector',\n ph: Types.Events.Phase.COMPLETE,\n ts: entryStartTime,\n dur: Types.Timing.MicroSeconds(entryEndTime - entryStartTime),\n rawSourceEvent: currentTimeStamp\n };\n const syntheticTimeStamp =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Events.SyntheticConsoleTimeStamp>(unregisteredSyntheticTimeStamp);\n syntheticConsoleEntriesForTimingsTrack.push(syntheticTimeStamp);\n }\n}\n\n/**\n * Extracts extension entries from Performance API events (marks and\n * measures).\n * It specifically looks for events that contain extension-specific data\n * within their `detail` property.\n *\n * If an event's `detail` property can be parsed as a JSON object and\n * contains a `devtools` field with a valid extension payload, a\n * synthetic extension entry is created. The type of extension entry\n * created depends on the payload:\n *\n * - If the payload conforms to `ExtensionPayloadMarker`, a\n * `SyntheticExtensionMarker` is created and added to the\n * `extensionMarkers` array. These markers represent single points in\n * time.\n * - If the payload conforms to `ExtensionPayloadTrackEntry`, a\n * `SyntheticExtensionTrackEntry` is created and added to the\n * `extensionTrackEntries` array. These entries represent events with\n * a duration and are displayed on custom tracks in the Performance\n * panel.\n *\n * **Note:** Only events with a `detail` property that contains valid\n * extension data are processed. Other `performance.mark` and\n * `performance.measure` events are ignored.\n *\n * @param timings An array of `SyntheticUserTimingPair` or\n * `PerformanceMark` events, typically obtained from the\n * `UserTimingsHandler`.\n */\nexport function extractPerformanceAPIExtensionEntries(\n timings: (Types.Events.SyntheticUserTimingPair|Types.Events.PerformanceMark)[]): void {\n for (const timing of timings) {\n const extensionPayload = extensionDataInPerformanceTiming(timing);\n if (!extensionPayload) {\n // Not an extension user timing.\n continue;\n }\n\n const extensionSyntheticEntry = {\n name: timing.name,\n ph: Types.Events.Phase.COMPLETE,\n pid: timing.pid,\n tid: timing.tid,\n ts: timing.ts,\n dur: timing.dur as Types.Timing.MicroSeconds,\n cat: 'devtools.extension',\n args: extensionPayload,\n rawSourceEvent: Types.Events.isSyntheticUserTiming(timing) ? timing.rawSourceEvent : timing,\n };\n\n if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {\n const extensionMarker =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Extensions.SyntheticExtensionMarker>(\n extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionMarker, '_tag'>);\n extensionMarkers.push(extensionMarker);\n continue;\n }\n\n if (Types.Extensions.isExtensionPayloadTrackEntry(extensionSyntheticEntry.args)) {\n const extensionTrackEntry =\n Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticEvent<Types.Extensions.SyntheticExtensionTrackEntry>(\n extensionSyntheticEntry as Omit<Types.Extensions.SyntheticExtensionTrackEntry, '_tag'>);\n extensionTrackEntries.push(extensionTrackEntry);\n continue;\n }\n }\n}\n\nexport function extensionDataInPerformanceTiming(timing: Types.Events.SyntheticUserTimingPair|\n Types.Events.PerformanceMark): Types.Extensions.ExtensionDataPayload|\n null {\n const timingDetail =\n Types.Events.isPerformanceMark(timing) ? timing.args.data?.detail : timing.args.data.beginEvent.args.detail;\n if (!timingDetail) {\n return null;\n }\n try {\n // Attempt to parse the detail as an object that might be coming from a\n // DevTools Perf extension.\n // Wrapped in a try-catch because timingDetail might either:\n // 1. Not be `json.parse`-able (it should, but just in case...)\n // 2.Not be an object - in which case the `in` check will error.\n // If we hit either of these cases, we just ignore this mark and move on.\n const detailObj = JSON.parse(timingDetail);\n if (!('devtools' in detailObj)) {\n return null;\n }\n if (!Types.Extensions.isValidExtensionPayload(detailObj.devtools)) {\n return null;\n }\n return detailObj.devtools;\n } catch {\n // No need to worry about this error, just discard this event and don't\n // treat it as having any useful information for the purposes of extensions\n return null;\n }\n}\n/**\n * Extracts extension data from a `console.timeStamp` event.\n *\n * Checks if a `console.timeStamp` event contains data intended for\n * creating a custom track entry in the DevTools Performance panel. It\n * specifically looks for a `track` argument within the event's data.\n *\n * If a `track` argument is present (and not an empty string), the\n * function constructs an `ExtensionTrackEntryPayload` object containing\n * the track name, an optional color, an optional track group. This\n * payload is then used to create a `SyntheticExtensionTrackEntry`.\n *\n * **Note:** The `color` argument is optional and its type is validated\n * against a predefined palette (see\n * `ExtensionUI::extensionEntryColor`).\n *\n * @param timeStamp The `ConsoleTimeStamp` event to extract data from.\n * @return An `ExtensionTrackEntryPayload` object if the event contains\n * valid extension data for a track entry, or `null` otherwise.\n */\nexport function extensionDataInConsoleTimeStamp(timeStamp: Types.Events.ConsoleTimeStamp):\n Types.Extensions.ExtensionTrackEntryPayload|null {\n const trackName = timeStamp.args.data.track;\n if (trackName === '' || trackName === undefined) {\n return null;\n }\n return {\n // the color is defaulted to primary if it's value isn't one from\n // the defined palette (see ExtensionUI::extensionEntryColor) so\n // we don't need to check the value is valid here.\n color: String(timeStamp.args.data.color) as Types.Extensions.ExtensionTrackEntryPayload['color'],\n track: String(trackName),\n dataType: 'track-entry',\n trackGroup: timeStamp.args.data.trackGroup !== undefined ? String(timeStamp.args.data.trackGroup) : undefined\n };\n}\n\nexport function data(): ExtensionTraceData {\n return {\n entryToNode,\n extensionTrackData,\n extensionMarkers,\n syntheticConsoleEntriesForTimingsTrack,\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['UserTimings'];\n}\n"]}
|