@paulirish/trace_engine 0.0.53 → 0.0.54
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/analyze-inspector-issues.d.mts +13 -0
- package/.tmp/tsbuildinfo/analyze-inspector-issues.d.mts.map +1 -0
- package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
- package/analyze-inspector-issues.mjs +60 -0
- package/core/common/common.d.ts +1 -0
- package/core/common/common.js +1 -0
- package/core/host/host.d.ts +1 -0
- package/core/host/host.js +1 -0
- package/core/platform/ServerTiming.d.ts +31 -0
- package/core/platform/ServerTiming.js +212 -0
- package/core/platform/ServerTiming.js.map +1 -0
- package/core/root/root.d.ts +1 -0
- package/core/root/root.js +1 -0
- package/core/sdk/sdk.d.ts +1 -0
- package/core/sdk/sdk.js +1 -0
- package/models/issues_manager/CheckFormsIssuesTrigger.d.ts +1 -0
- package/models/issues_manager/CheckFormsIssuesTrigger.js +1 -0
- package/models/issues_manager/ContrastCheckTrigger.d.ts +1 -0
- package/models/issues_manager/ContrastCheckTrigger.js +1 -0
- package/models/issues_manager/DeprecationIssue.d.ts +1 -0
- package/models/issues_manager/DeprecationIssue.js +1 -0
- package/models/issues_manager/IssueResolver.d.ts +1 -0
- package/models/issues_manager/IssueResolver.js +1 -0
- package/models/issues_manager/RelatedIssue.d.ts +1 -0
- package/models/issues_manager/RelatedIssue.js +1 -0
- package/models/issues_manager/SourceFrameIssuesManager.d.ts +1 -0
- package/models/issues_manager/SourceFrameIssuesManager.js +1 -0
- package/models/trace/LanternComputationData.js +2 -2
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.js +1 -1
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/extras/Metadata.js +2 -2
- package/models/trace/extras/Metadata.js.map +1 -1
- package/models/trace/extras/ThirdParties.js +1 -1
- package/models/trace/extras/ThirdParties.js.map +1 -1
- package/models/trace/extras/TimelineJSProfile.d.ts +13 -0
- package/models/trace/extras/TimelineJSProfile.js +55 -0
- package/models/trace/extras/TimelineJSProfile.js.map +1 -0
- package/models/trace/extras/TraceFilter.js +2 -2
- package/models/trace/extras/TraceFilter.js.map +1 -1
- package/models/trace/extras/URLForEntry.d.ts +12 -0
- package/models/trace/extras/URLForEntry.js +43 -0
- package/models/trace/extras/URLForEntry.js.map +1 -0
- package/models/trace/extras/extras.d.ts +4 -1
- package/models/trace/extras/extras.js +4 -1
- package/models/trace/handlers/AuctionWorkletsHandler.js +5 -5
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.js +4 -4
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/FlowsHandler.js +3 -3
- package/models/trace/handlers/FlowsHandler.js.map +1 -1
- package/models/trace/handlers/FramesHandler.js +7 -7
- package/models/trace/handlers/FramesHandler.js.map +1 -1
- package/models/trace/handlers/LargestImagePaintHandler.js +2 -2
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js +18 -10
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.js +7 -7
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.js +3 -3
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -2
- package/models/trace/handlers/PageLoadMetricsHandler.js +54 -25
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/RendererHandler.js +1 -1
- package/models/trace/handlers/RendererHandler.js.map +1 -1
- package/models/trace/handlers/ServerTimingsHandler.d.ts +9 -0
- package/models/trace/handlers/ServerTimingsHandler.js +106 -0
- package/models/trace/handlers/ServerTimingsHandler.js.map +1 -0
- package/models/trace/handlers/Threads.d.ts +1 -1
- package/models/trace/handlers/Threads.js +17 -7
- package/models/trace/handlers/Threads.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.js +4 -3
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/handlers/WarningsHandler.js +2 -2
- package/models/trace/handlers/WarningsHandler.js.map +1 -1
- package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
- package/models/trace/helpers/SamplesIntegrator.js +19 -12
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
- package/models/trace/helpers/Trace.js +111 -111
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/insights/CLSCulprits.d.ts +1 -1
- package/models/trace/insights/CLSCulprits.js +43 -22
- package/models/trace/insights/CLSCulprits.js.map +1 -1
- package/models/trace/insights/Common.js +4 -3
- package/models/trace/insights/Common.js.map +1 -1
- package/models/trace/insights/CumulativeLayoutShift.d.ts +57 -0
- package/models/trace/insights/CumulativeLayoutShift.js +335 -0
- package/models/trace/insights/CumulativeLayoutShift.js.map +1 -0
- package/models/trace/insights/DOMSize.js +3 -3
- package/models/trace/insights/DOMSize.js.map +1 -1
- package/models/trace/insights/DocumentLatency.js +2 -2
- package/models/trace/insights/DocumentLatency.js.map +1 -1
- package/models/trace/insights/DuplicatedJavaScript.js +2 -2
- package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
- package/models/trace/insights/FontDisplay.js +2 -2
- package/models/trace/insights/FontDisplay.js.map +1 -1
- package/models/trace/insights/ForcedReflow.js +2 -2
- package/models/trace/insights/ForcedReflow.js.map +1 -1
- package/models/trace/insights/ImageDelivery.js +2 -2
- package/models/trace/insights/ImageDelivery.js.map +1 -1
- package/models/trace/insights/InsightRunners.d.ts +9 -0
- package/models/trace/insights/InsightRunners.js +13 -0
- package/models/trace/insights/InsightRunners.js.map +1 -0
- package/models/trace/insights/InteractionToNextPaint.js +3 -3
- package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
- package/models/trace/insights/LCPDiscovery.js +3 -3
- package/models/trace/insights/LCPDiscovery.js.map +1 -1
- package/models/trace/insights/LCPPhases.js +3 -3
- package/models/trace/insights/LCPPhases.js.map +1 -1
- package/models/trace/insights/LargestContentfulPaint.d.ts +38 -0
- package/models/trace/insights/LargestContentfulPaint.js +113 -0
- package/models/trace/insights/LargestContentfulPaint.js.map +1 -0
- package/models/trace/insights/LegacyJavaScript.js +2 -2
- package/models/trace/insights/LegacyJavaScript.js.map +1 -1
- package/models/trace/insights/ModernHTTP.js +2 -2
- package/models/trace/insights/ModernHTTP.js.map +1 -1
- package/models/trace/insights/NetworkDependencyTree.js +2 -2
- package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
- package/models/trace/insights/RenderBlocking.js +3 -3
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/SlowCSSSelector.js +2 -2
- package/models/trace/insights/SlowCSSSelector.js.map +1 -1
- package/models/trace/insights/ThirdParties.js +2 -2
- package/models/trace/insights/ThirdParties.js.map +1 -1
- package/models/trace/insights/ThirdPartyWeb.d.ts +13 -0
- package/models/trace/insights/ThirdPartyWeb.js +42 -0
- package/models/trace/insights/ThirdPartyWeb.js.map +1 -0
- package/models/trace/insights/Viewport.js +2 -2
- package/models/trace/insights/Viewport.js.map +1 -1
- package/models/trace/insights/types.d.ts +1 -1
- package/models/trace/insights/types.js +19 -0
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/root-causes/LayoutShift.d.ts +125 -0
- package/models/trace/root-causes/LayoutShift.js +519 -0
- package/models/trace/root-causes/LayoutShift.js.map +1 -0
- package/models/trace/root-causes/RootCauses.d.ts +15 -0
- package/models/trace/root-causes/RootCauses.js +12 -0
- package/models/trace/root-causes/RootCauses.js.map +1 -0
- package/models/trace/root-causes/bundle-tsconfig.json +1 -0
- package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/root-causes/root-causes-tsconfig.json +55 -0
- package/models/trace/root-causes/root-causes.d.ts +1 -0
- package/models/trace/root-causes/root-causes.js +5 -0
- package/models/trace/root-causes/root-causes.js.map +1 -0
- package/models/trace/types/File.d.ts +3 -3
- package/models/trace/types/File.js +28 -4
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +6 -6
- package/models/trace/types/TraceEvents.js +373 -105
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
- package/test/test-trace-engine.mjs +77 -0
- package/third_party/marked/marked.d.ts +1 -0
- package/third_party/marked/marked.js +1 -0
- package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts +0 -4
- package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts.map +0 -1
|
@@ -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 * 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"]}
|
|
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"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
|
2
|
+
import * as Types from '../types/types.js';
|
|
3
|
+
export declare class TimelineJSProfileProcessor {
|
|
4
|
+
static isNativeRuntimeFrame(frame: Protocol.Runtime.CallFrame): boolean;
|
|
5
|
+
static nativeGroup(nativeName: string): string | null;
|
|
6
|
+
static createFakeTraceFromCpuProfile(profile: Protocol.Profiler.Profile, tid: Types.Events.ThreadID): Types.Events.Event[];
|
|
7
|
+
}
|
|
8
|
+
export declare namespace TimelineJSProfileProcessor {
|
|
9
|
+
const enum NativeGroups {
|
|
10
|
+
COMPILE = "Compile",
|
|
11
|
+
PARSE = "Parse"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Copyright 2014 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 Types from '../types/types.js';
|
|
5
|
+
// TODO(paulirish): Delete this file.
|
|
6
|
+
// - Move isNativeRuntimeFrame and nativeGroup to TraceEvents.d.ts (or TraceTree)
|
|
7
|
+
// - Move createFakeTraceFromCpuProfile to TimelineLoader
|
|
8
|
+
export class TimelineJSProfileProcessor {
|
|
9
|
+
static isNativeRuntimeFrame(frame) {
|
|
10
|
+
return frame.url === 'native V8Runtime';
|
|
11
|
+
}
|
|
12
|
+
static nativeGroup(nativeName) {
|
|
13
|
+
if (nativeName.startsWith('Parse')) {
|
|
14
|
+
return "Parse" /* TimelineJSProfileProcessor.NativeGroups.PARSE */;
|
|
15
|
+
}
|
|
16
|
+
if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile')) {
|
|
17
|
+
return "Compile" /* TimelineJSProfileProcessor.NativeGroups.COMPILE */;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
static createFakeTraceFromCpuProfile(profile, tid) {
|
|
22
|
+
const events = [];
|
|
23
|
+
const threadName = `Thread ${tid}`;
|
|
24
|
+
appendEvent('TracingStartedInPage', { data: { sessionId: '1' } }, 0, 0, "M" /* Types.Events.Phase.METADATA */);
|
|
25
|
+
appendEvent("thread_name" /* Types.Events.Name.THREAD_NAME */, { name: threadName }, 0, 0, "M" /* Types.Events.Phase.METADATA */, '__metadata');
|
|
26
|
+
if (!profile) {
|
|
27
|
+
return events;
|
|
28
|
+
}
|
|
29
|
+
// Append a root to show the start time of the profile (which is earlier than first sample), so the Performance
|
|
30
|
+
// panel won't truncate this time period.
|
|
31
|
+
// 'JSRoot' doesn't exist in the new engine and is not the name of an actual trace event, but changing it might break other trace processing tools that rely on this, so we stick with this name.
|
|
32
|
+
// TODO(crbug.com/341234884): consider removing this or clarify why it's required.
|
|
33
|
+
appendEvent('JSRoot', {}, profile.startTime, profile.endTime - profile.startTime, "X" /* Types.Events.Phase.COMPLETE */, 'toplevel');
|
|
34
|
+
// TODO: create a `Profile` event instead, as `cpuProfile` is legacy
|
|
35
|
+
appendEvent('CpuProfile', { data: { cpuProfile: profile } }, profile.endTime, 0, "X" /* Types.Events.Phase.COMPLETE */);
|
|
36
|
+
return events;
|
|
37
|
+
function appendEvent(name, args, ts, dur, ph, cat) {
|
|
38
|
+
const event = {
|
|
39
|
+
cat: cat || 'disabled-by-default-devtools.timeline',
|
|
40
|
+
name,
|
|
41
|
+
ph: ph || "X" /* Types.Events.Phase.COMPLETE */,
|
|
42
|
+
pid: Types.Events.ProcessID(1),
|
|
43
|
+
tid,
|
|
44
|
+
ts: Types.Timing.MicroSeconds(ts),
|
|
45
|
+
args,
|
|
46
|
+
};
|
|
47
|
+
if (dur) {
|
|
48
|
+
event.dur = Types.Timing.MicroSeconds(dur);
|
|
49
|
+
}
|
|
50
|
+
events.push(event);
|
|
51
|
+
return event;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=TimelineJSProfile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimelineJSProfile.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/TimelineJSProfile.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAK7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,qCAAqC;AACrC,mFAAmF;AACnF,2DAA2D;AAC3D,MAAM,OAAO,0BAA0B;IACrC,MAAM,CAAC,oBAAoB,CAAC,KAAiC;QAC3D,OAAO,KAAK,CAAC,GAAG,KAAK,kBAAkB,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,UAAkB;QACnC,IAAI,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,mEAAqD;QACvD,CAAC;QACD,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3E,uEAAuD;QACzD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,6BAA6B,CAAC,OAAkC,EAAE,GAA0B;QAEjG,MAAM,MAAM,GAAyB,EAAE,CAAC;QAExC,MAAM,UAAU,GAAG,UAAU,GAAG,EAAE,CAAC;QACnC,WAAW,CAAC,sBAAsB,EAAE,EAAC,IAAI,EAAE,EAAC,SAAS,EAAE,GAAG,EAAC,EAAC,EAAE,CAAC,EAAE,CAAC,wCAA8B,CAAC;QACjG,WAAW,oDAAgC,EAAC,IAAI,EAAE,UAAU,EAAC,EAAE,CAAC,EAAE,CAAC,yCAA+B,YAAY,CAAC,CAAC;QAChH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,+GAA+G;QAC/G,yCAAyC;QACzC,iMAAiM;QACjM,kFAAkF;QAClF,WAAW,CACP,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,yCAA+B,UAAU,CAAC,CAAC;QAEnH,oEAAoE;QACpE,WAAW,CAAC,YAAY,EAAE,EAAC,IAAI,EAAE,EAAC,UAAU,EAAE,OAAO,EAAC,EAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,wCAA8B,CAAC;QAC1G,OAAO,MAAM,CAAC;QAEd,SAAS,WAAW,CAChB,IAAY,EAAE,IAAS,EAAE,EAAU,EAAE,GAAY,EAAE,EAAuB,EAAE,GAAY;YAC1F,MAAM,KAAK,GAAuB;gBAChC,GAAG,EAAE,GAAG,IAAI,uCAAuC;gBACnD,IAAI;gBACJ,EAAE,EAAE,EAAE,yCAA+B;gBACrC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC9B,GAAG;gBACH,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjC,IAAI;aACL,CAAC;YAEF,IAAI,GAAG,EAAE,CAAC;gBACR,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF","sourcesContent":["// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as Types from '../types/types.js';\n\n// TODO(paulirish): Delete this file.\n// - Move isNativeRuntimeFrame and nativeGroup to TraceEvents.d.ts (or TraceTree)\n// - Move createFakeTraceFromCpuProfile to TimelineLoader\nexport class TimelineJSProfileProcessor {\n static isNativeRuntimeFrame(frame: Protocol.Runtime.CallFrame): boolean {\n return frame.url === 'native V8Runtime';\n }\n\n static nativeGroup(nativeName: string): string|null {\n if (nativeName.startsWith('Parse')) {\n return TimelineJSProfileProcessor.NativeGroups.PARSE;\n }\n if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile')) {\n return TimelineJSProfileProcessor.NativeGroups.COMPILE;\n }\n return null;\n }\n\n static createFakeTraceFromCpuProfile(profile: Protocol.Profiler.Profile, tid: Types.Events.ThreadID):\n Types.Events.Event[] {\n const events: Types.Events.Event[] = [];\n\n const threadName = `Thread ${tid}`;\n appendEvent('TracingStartedInPage', {data: {sessionId: '1'}}, 0, 0, Types.Events.Phase.METADATA);\n appendEvent(Types.Events.Name.THREAD_NAME, {name: threadName}, 0, 0, Types.Events.Phase.METADATA, '__metadata');\n if (!profile) {\n return events;\n }\n\n // Append a root to show the start time of the profile (which is earlier than first sample), so the Performance\n // panel won't truncate this time period.\n // 'JSRoot' doesn't exist in the new engine and is not the name of an actual trace event, but changing it might break other trace processing tools that rely on this, so we stick with this name.\n // TODO(crbug.com/341234884): consider removing this or clarify why it's required.\n appendEvent(\n 'JSRoot', {}, profile.startTime, profile.endTime - profile.startTime, Types.Events.Phase.COMPLETE, 'toplevel');\n\n // TODO: create a `Profile` event instead, as `cpuProfile` is legacy\n appendEvent('CpuProfile', {data: {cpuProfile: profile}}, profile.endTime, 0, Types.Events.Phase.COMPLETE);\n return events;\n\n function appendEvent(\n name: string, args: any, ts: number, dur?: number, ph?: Types.Events.Phase, cat?: string): Types.Events.Event {\n const event: Types.Events.Event = {\n cat: cat || 'disabled-by-default-devtools.timeline',\n name,\n ph: ph || Types.Events.Phase.COMPLETE,\n pid: Types.Events.ProcessID(1),\n tid,\n ts: Types.Timing.MicroSeconds(ts),\n args,\n };\n\n if (dur) {\n event.dur = Types.Timing.MicroSeconds(dur);\n }\n events.push(event);\n return event;\n }\n }\n}\n\nexport namespace TimelineJSProfileProcessor {\n export const enum NativeGroups {\n COMPILE = 'Compile',\n PARSE = 'Parse',\n }\n}\n"]}
|
|
@@ -19,11 +19,11 @@ export class VisibleEventsFilter extends TraceFilter {
|
|
|
19
19
|
static eventType(event) {
|
|
20
20
|
// Any blink.console category events are treated as ConsoleTime events
|
|
21
21
|
if (event.cat.includes('blink.console')) {
|
|
22
|
-
return
|
|
22
|
+
return Types.Events.Name.CONSOLE_TIME;
|
|
23
23
|
}
|
|
24
24
|
// Any blink.user_timing egory events are treated as UserTiming events
|
|
25
25
|
if (event.cat.includes('blink.user_timing')) {
|
|
26
|
-
return
|
|
26
|
+
return Types.Events.Name.USER_TIMING;
|
|
27
27
|
}
|
|
28
28
|
return event.name;
|
|
29
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TraceFilter.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/TraceFilter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,OAAgB,WAAW;CAEhC;AAED,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IACjC,YAAY,CAAc;IAC3C,YAAY,YAAsB;QAChC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,KAAyB;QAC9B,IAAI,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,KAAyB;QACxC,sEAAsE;QACtE,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACxC,
|
|
1
|
+
{"version":3,"file":"TraceFilter.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/TraceFilter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,OAAgB,WAAW;CAEhC;AAED,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IACjC,YAAY,CAAc;IAC3C,YAAY,YAAsB;QAChC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,KAAyB;QAC9B,IAAI,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,KAAyB;QACxC,sEAAsE;QACtE,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;QACxC,CAAC;QACD,sEAAsE;QACtE,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;QACvC,CAAC;QACD,OAAO,KAAK,CAAC,IAAyB,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,WAAW;IACpD,eAAe,CAAyB;IAExC,YAAY,cAAmC;QAC7C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,CAAC,KAAyB;QAC9B,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,WAAW;IAClD,aAAa,CAAyB;IACtC,YAAY,YAAiC;QAC3C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,KAAyB;QAC9B,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAyB,CAAC,CAAC;IAClE,CAAC;CACF","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nexport abstract class TraceFilter {\n abstract accept(_event: Types.Events.Event, parsedTrace?: Handlers.Types.ParsedTrace): boolean;\n}\n\nexport class VisibleEventsFilter extends TraceFilter {\n private readonly visibleTypes: Set<string>;\n constructor(visibleTypes: string[]) {\n super();\n this.visibleTypes = new Set(visibleTypes);\n }\n\n accept(event: Types.Events.Event): boolean {\n if (Types.Extensions.isSyntheticExtensionEntry(event)) {\n return true;\n }\n return this.visibleTypes.has(VisibleEventsFilter.eventType(event));\n }\n\n static eventType(event: Types.Events.Event): Types.Events.Name {\n // Any blink.console category events are treated as ConsoleTime events\n if (event.cat.includes('blink.console')) {\n return Types.Events.Name.CONSOLE_TIME;\n }\n // Any blink.user_timing egory events are treated as UserTiming events\n if (event.cat.includes('blink.user_timing')) {\n return Types.Events.Name.USER_TIMING;\n }\n return event.name as Types.Events.Name;\n }\n}\n\nexport class InvisibleEventsFilter extends TraceFilter {\n #invisibleTypes: Set<Types.Events.Name>;\n\n constructor(invisibleTypes: Types.Events.Name[]) {\n super();\n this.#invisibleTypes = new Set(invisibleTypes);\n }\n\n accept(event: Types.Events.Event): boolean {\n return !this.#invisibleTypes.has(VisibleEventsFilter.eventType(event));\n }\n}\n\nexport class ExclusiveNameFilter extends TraceFilter {\n #excludeNames: Set<Types.Events.Name>;\n constructor(excludeNames: Types.Events.Name[]) {\n super();\n this.#excludeNames = new Set(excludeNames);\n }\n\n accept(event: Types.Events.Event): boolean {\n return !this.#excludeNames.has(event.name as Types.Events.Name);\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type * as Platform from '../../../core/platform/platform.js';
|
|
2
|
+
import type * as Handlers from '../handlers/handlers.js';
|
|
3
|
+
import * as Types from '../types/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Use this helper whenever resolving an URL's source mapping is not an
|
|
6
|
+
* option. For example when processing non-ui data. Otherwise use the
|
|
7
|
+
* helper SourceMapsResolver::resolvedURLForEntry
|
|
8
|
+
*
|
|
9
|
+
* If an URL will be displayed in the UI, it's likely you should not use
|
|
10
|
+
* this helper and prefer the other option instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getNonResolved(parsedTrace: Handlers.Types.ParsedTrace, entry: Types.Events.Event): Platform.DevToolsPath.UrlString | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
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 Types from '../types/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Use this helper whenever resolving an URL's source mapping is not an
|
|
7
|
+
* option. For example when processing non-ui data. Otherwise use the
|
|
8
|
+
* helper SourceMapsResolver::resolvedURLForEntry
|
|
9
|
+
*
|
|
10
|
+
* If an URL will be displayed in the UI, it's likely you should not use
|
|
11
|
+
* this helper and prefer the other option instead.
|
|
12
|
+
*/
|
|
13
|
+
export function getNonResolved(parsedTrace, entry) {
|
|
14
|
+
if (Types.Events.isProfileCall(entry)) {
|
|
15
|
+
return entry.callFrame.url;
|
|
16
|
+
}
|
|
17
|
+
if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {
|
|
18
|
+
return entry.args.data.stackTrace[0].url;
|
|
19
|
+
}
|
|
20
|
+
if (Types.Events.isSyntheticNetworkRequest(entry)) {
|
|
21
|
+
return entry.args.data.url;
|
|
22
|
+
}
|
|
23
|
+
// DecodeImage events use the URL from the relevant PaintImage event.
|
|
24
|
+
if (Types.Events.isDecodeImage(entry)) {
|
|
25
|
+
const paintEvent = parsedTrace.ImagePainting.paintImageForEvent.get(entry);
|
|
26
|
+
return paintEvent ? getNonResolved(parsedTrace, paintEvent) : null;
|
|
27
|
+
}
|
|
28
|
+
// DrawLazyPixelRef events use the URL from the relevant PaintImage event.
|
|
29
|
+
if (Types.Events.isDrawLazyPixelRef(entry) && entry.args?.LazyPixelRef) {
|
|
30
|
+
const paintEvent = parsedTrace.ImagePainting.paintImageByDrawLazyPixelRef.get(entry.args.LazyPixelRef);
|
|
31
|
+
return paintEvent ? getNonResolved(parsedTrace, paintEvent) : null;
|
|
32
|
+
}
|
|
33
|
+
// ParseHTML events store the URL under beginData, not data.
|
|
34
|
+
if (Types.Events.isParseHTML(entry)) {
|
|
35
|
+
return entry.args.beginData.url;
|
|
36
|
+
}
|
|
37
|
+
// For all other events, try to see if the URL is provided, else return null.
|
|
38
|
+
if (entry.args?.data?.url) {
|
|
39
|
+
return entry.args.data.url;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=URLForEntry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"URLForEntry.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/URLForEntry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C;;;;;;;GAOG;AAEH,MAAM,UAAU,cAAc,CAC1B,WAAuC,EAAE,KAAyB;IACpE,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,SAAS,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAsC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,WAAW,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3E,OAAO,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;IAED,0EAA0E;IAC1E,IAAI,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QACvE,MAAM,UAAU,GAAG,WAAW,CAAC,aAAa,CAAC,4BAA4B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvG,OAAO,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;IAED,4DAA4D;IAC5D,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAsC,CAAC;IACrE,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,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.\n\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\n/**\n * Use this helper whenever resolving an URL's source mapping is not an\n * option. For example when processing non-ui data. Otherwise use the\n * helper SourceMapsResolver::resolvedURLForEntry\n *\n * If an URL will be displayed in the UI, it's likely you should not use\n * this helper and prefer the other option instead.\n */\n\nexport function getNonResolved(\n parsedTrace: Handlers.Types.ParsedTrace, entry: Types.Events.Event): Platform.DevToolsPath.UrlString|null {\n if (Types.Events.isProfileCall(entry)) {\n return entry.callFrame.url as Platform.DevToolsPath.UrlString;\n }\n\n if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {\n return entry.args.data.stackTrace[0].url as Platform.DevToolsPath.UrlString;\n }\n\n if (Types.Events.isSyntheticNetworkRequest(entry)) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n // DecodeImage events use the URL from the relevant PaintImage event.\n if (Types.Events.isDecodeImage(entry)) {\n const paintEvent = parsedTrace.ImagePainting.paintImageForEvent.get(entry);\n return paintEvent ? getNonResolved(parsedTrace, paintEvent) : null;\n }\n\n // DrawLazyPixelRef events use the URL from the relevant PaintImage event.\n if (Types.Events.isDrawLazyPixelRef(entry) && entry.args?.LazyPixelRef) {\n const paintEvent = parsedTrace.ImagePainting.paintImageByDrawLazyPixelRef.get(entry.args.LazyPixelRef);\n return paintEvent ? getNonResolved(parsedTrace, paintEvent) : null;\n }\n\n // ParseHTML events store the URL under beginData, not data.\n if (Types.Events.isParseHTML(entry)) {\n return entry.args.beginData.url as Platform.DevToolsPath.UrlString;\n }\n\n // For all other events, try to see if the URL is provided, else return null.\n if (entry.args?.data?.url) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n return null;\n}\n"]}
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
// found in the LICENSE file.
|
|
7
7
|
|
|
8
8
|
// Exclude the parts of extras.ts that have painful dependencies. Include these cuz they don't and are needed.
|
|
9
|
-
export * as ThirdParties from './ThirdParties.js';
|
|
10
9
|
export * as ScriptDuplication from './ScriptDuplication.js';
|
|
11
10
|
export * as StackTraceForEvent from './StackTraceForEvent.js';
|
|
11
|
+
export * as ThirdParties from './ThirdParties.js';
|
|
12
|
+
export * as TraceFilter from './TraceFilter.js';
|
|
13
|
+
export * as TraceTree from './TraceTree.js';
|
|
14
|
+
|
|
12
15
|
|
|
13
16
|
// The rest of this file is a polyfill :)
|
|
14
17
|
// Remove once Lighthouse drops Node 18 support.
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
// found in the LICENSE file.
|
|
7
7
|
|
|
8
8
|
// Exclude the parts of extras.ts that have painful dependencies. Include these cuz they don't and are needed.
|
|
9
|
-
export * as ThirdParties from './ThirdParties.js';
|
|
10
9
|
export * as ScriptDuplication from './ScriptDuplication.js';
|
|
11
10
|
export * as StackTraceForEvent from './StackTraceForEvent.js';
|
|
11
|
+
export * as ThirdParties from './ThirdParties.js';
|
|
12
|
+
export * as TraceFilter from './TraceFilter.js';
|
|
13
|
+
export * as TraceTree from './TraceTree.js';
|
|
14
|
+
|
|
12
15
|
|
|
13
16
|
// The rest of this file is a polyfill :)
|
|
14
17
|
// Remove once Lighthouse drops Node 18 support.
|
|
@@ -71,11 +71,11 @@ export function handleEvent(event) {
|
|
|
71
71
|
function workletType(input) {
|
|
72
72
|
switch (input) {
|
|
73
73
|
case 'seller':
|
|
74
|
-
return
|
|
74
|
+
return Types.Events.AuctionWorkletType.SELLER;
|
|
75
75
|
case 'bidder':
|
|
76
|
-
return
|
|
76
|
+
return Types.Events.AuctionWorkletType.BIDDER;
|
|
77
77
|
default:
|
|
78
|
-
return
|
|
78
|
+
return Types.Events.AuctionWorkletType.UNKNOWN;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
@@ -88,11 +88,11 @@ function makeSyntheticEventBase(event) {
|
|
|
88
88
|
.registerSyntheticEvent({
|
|
89
89
|
rawSourceEvent: event,
|
|
90
90
|
name: 'SyntheticAuctionWorklet',
|
|
91
|
-
s:
|
|
91
|
+
s: Types.Events.Scope.THREAD,
|
|
92
92
|
cat: event.cat,
|
|
93
93
|
tid: event.tid,
|
|
94
94
|
ts: event.ts,
|
|
95
|
-
ph:
|
|
95
|
+
ph: Types.Events.Phase.INSTANT,
|
|
96
96
|
pid: event.args.data.pid,
|
|
97
97
|
host: event.args.data.host,
|
|
98
98
|
target: event.args.data.target,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorklets as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents = new Map<Types.Events.ProcessID, Types.Events.AuctionWorkletRunningInProcess>();\nconst doneWithProcessEvents = new Map<Types.Events.ProcessID, Types.Events.AuctionWorkletDoneWithProcess>();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents = new Map<Types.Events.ProcessID, Types.Events.SyntheticAuctionWorklet>();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads = new Map<Types.Events.ProcessID, Types.Events.ThreadName>();\nconst v8HelperThreads = new Map<Types.Events.ProcessID, Types.Events.ThreadName>();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.Events.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.Events.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.Events.AuctionWorkletType.BIDDER;\n default:\n return Types.Events.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.Events.AuctionWorkletDoneWithProcess|\n Types.Events.AuctionWorkletRunningInProcess):\n Omit<Types.Events.SyntheticAuctionWorklet, 'args'> {\n return Helpers.SyntheticEvents.SyntheticEventsManager\n .registerSyntheticEvent<Omit<Types.Events.SyntheticAuctionWorklet, 'args'>>({\n rawSourceEvent: event,\n name: 'SyntheticAuctionWorklet',\n s: Types.Events.Scope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.Events.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n });\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.Events.SyntheticAuctionWorklet|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.Events.ProcessID, Types.Events.SyntheticAuctionWorklet>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorklets as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents = new Map<Types.Events.ProcessID, Types.Events.AuctionWorkletRunningInProcess>();\nconst doneWithProcessEvents = new Map<Types.Events.ProcessID, Types.Events.AuctionWorkletDoneWithProcess>();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents = new Map<Types.Events.ProcessID, Types.Events.SyntheticAuctionWorklet>();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads = new Map<Types.Events.ProcessID, Types.Events.ThreadName>();\nconst v8HelperThreads = new Map<Types.Events.ProcessID, Types.Events.ThreadName>();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.Events.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.Events.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.Events.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.Events.AuctionWorkletType.BIDDER;\n default:\n return Types.Events.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.Events.AuctionWorkletDoneWithProcess|\n Types.Events.AuctionWorkletRunningInProcess):\n Omit<Types.Events.SyntheticAuctionWorklet, 'args'> {\n return Helpers.SyntheticEvents.SyntheticEventsManager\n .registerSyntheticEvent<Omit<Types.Events.SyntheticAuctionWorklet, 'args'>>({\n rawSourceEvent: event,\n name: 'SyntheticAuctionWorklet',\n s: Types.Events.Scope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.Events.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n });\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.Events.SyntheticAuctionWorklet|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.Events.ProcessID, Types.Events.SyntheticAuctionWorklet>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}
|
|
@@ -95,7 +95,7 @@ export function extractConsoleAPIExtensionEntries() {
|
|
|
95
95
|
rawSourceEvent: currentTimeStamp,
|
|
96
96
|
dur: Types.Timing.Micro(entryEndTime - entryStartTime),
|
|
97
97
|
ts: entryStartTime,
|
|
98
|
-
ph:
|
|
98
|
+
ph: Types.Events.Phase.COMPLETE,
|
|
99
99
|
};
|
|
100
100
|
const extensionEntry = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()
|
|
101
101
|
.registerSyntheticEvent(unregisteredExtensionEntry);
|
|
@@ -110,7 +110,7 @@ export function extractConsoleAPIExtensionEntries() {
|
|
|
110
110
|
...currentTimeStamp,
|
|
111
111
|
name: timeStampName,
|
|
112
112
|
cat: 'disabled-by-default-v8.inspector',
|
|
113
|
-
ph:
|
|
113
|
+
ph: Types.Events.Phase.COMPLETE,
|
|
114
114
|
ts: entryStartTime,
|
|
115
115
|
dur: Types.Timing.Micro(entryEndTime - entryStartTime),
|
|
116
116
|
rawSourceEvent: currentTimeStamp
|
|
@@ -158,8 +158,8 @@ export function extractPerformanceAPIExtensionEntries(timings) {
|
|
|
158
158
|
}
|
|
159
159
|
const extensionSyntheticEntry = {
|
|
160
160
|
name: timing.name,
|
|
161
|
-
ph: Types.Extensions.isExtensionPayloadMarker(extensionPayload) ?
|
|
162
|
-
|
|
161
|
+
ph: Types.Extensions.isExtensionPayloadMarker(extensionPayload) ? Types.Events.Phase.INSTANT :
|
|
162
|
+
Types.Events.Phase.COMPLETE,
|
|
163
163
|
pid: timing.pid,
|
|
164
164
|
tid: timing.tid,
|
|
165
165
|
ts: timing.ts,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAC,IAAI,IAAI,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAEhE,MAAM,qBAAqB,GAAoD,EAAE,CAAC;AAClF,MAAM,kBAAkB,GAA0C,EAAE,CAAC;AACrE,MAAM,gBAAgB,GAAgD,EAAE,CAAC;AACzE,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0D,CAAC;AACtF,MAAM,eAAe,GAAG,IAAI,GAAG,EAAyC,CAAC;AAEzE,MAAM,sCAAsC,GAA6C,EAAE,CAAC;AAU5F,MAAM,UAAU,WAAW,CAAC,MAA0B;IACpD,4EAA4E;AAC9E,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,sCAAsC,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5B,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,eAAe,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,gCAAgC,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,gCAAgC;IACvC,MAAM,cAAc,GAAoD,eAAe,EAAE,CAAC,mBAAmB,CAAC;IAC9G,MAAM,KAAK,GAA4C,eAAe,EAAE,CAAC,gBAAgB,CAAC;IAC1F,MAAM,wBAAwB,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAEzF,qCAAqC,CAAC,wBAAwB,CAAC,CAAC;IAChE,iCAAiC,EAAE,CAAC;IACpC,0DAA0D;IAC1D,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,CAAC;IAC5D,OAAO,CAAC,UAAU,CAAC,kCAAkC,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,WAAW,CAAC,CAAC;AAChH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,iCAAiC;IAC/C,MAAM,iBAAiB,GAA6C,eAAe,EAAE,CAAC,eAAe,CAAC;IACtG,KAAK,MAAM,gBAAgB,IAAI,iBAAiB,EAAE,CAAC;QACjD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpG,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,+BAA+B,CAAC,gBAAgB,CAAC,CAAC;QACxE,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/C,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3C,IAAI,CAAC,aAAa,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;YACrC,SAAS;QACX,CAAC;QACD,kEAAkE;QAClE,gEAAgE;QAChE,kEAAkE;QAClE,2CAA2C;QAC3C,MAAM,cAAc,GAChB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACnG,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9G,IAAI,YAAY,KAAK,SAAS,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YAC/D,eAAe;YACf,SAAS;QACX,CAAC;QACD,MAAM,cAAc,GAAG,cAAc,IAAI,gBAAgB,CAAC,EAAE,CAAC;QAC7D,MAAM,YAAY,GAAG,YAAY,IAAI,gBAAgB,CAAC,EAAE,CAAC;QACzD,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,0BAA0B,GAAgE;gBAC9F,GAAG,gBAAgB;gBACnB,IAAI,EAAE,aAAa;gBACnB,GAAG,EAAE,oBAAoB;gBACzB,IAAI,EAAE,aAAa;gBACnB,cAAc,EAAE,gBAAgB;gBAChC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,cAAc,CAAC;gBACtD,EAAE,EAAE,cAAc;gBAClB,EAAE,uCAA6B;aAChC,CAAC;YACF,MAAM,cAAc,GAChB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;iBAC5D,sBAAsB,CAAgD,0BAA0B,CAAC,CAAC;YAC3G,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC3C,SAAS;QACX,CAAC;QACD,mEAAmE;QACnE,mEAAmE;QACnE,mEAAmE;QACnE,oEAAoE;QACpE,MAAM,8BAA8B,GAAyD;YAC3F,GAAG,gBAAgB;YACnB,IAAI,EAAE,aAAa;YACnB,GAAG,EAAE,kCAAkC;YACvC,EAAE,uCAA6B;YAC/B,EAAE,EAAE,cAAc;YAClB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,cAAc,CAAC;YACtD,cAAc,EAAE,gBAAgB;SACjC,CAAC;QACF,MAAM,kBAAkB,GACpB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;aAC5D,sBAAsB,CAAyC,8BAA8B,CAAC,CAAC;QACxG,sCAAsC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,qCAAqC,CACjD,OAAiF;IACnF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,gCAAgC;YAChC,SAAS;QACX,CAAC;QAED,MAAM,uBAAuB,GAAG;YAC9B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,CAAC,CAAC,sCAA4B,CAAC;qDACD;YAC7F,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,GAAG,EAAE,MAAM,CAAC,GAAyB;YACrC,GAAG,EAAE,oBAAoB;YACzB,IAAI,EAAE,gBAAgB;YACtB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM;SAC5F,CAAC;QAEF,IAAI,KAAK,CAAC,UAAU,CAAC,wBAAwB,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChE,MAAM,eAAe,GACjB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;iBAC5D,sBAAsB,CACnB,uBAAkF,CAAC,CAAC;YAChG,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,UAAU,CAAC,4BAA4B,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC;YAChF,MAAM,mBAAmB,GACrB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE;iBAC5D,sBAAsB,CACnB,uBAAsF,CAAC,CAAC;YACpG,qBAAqB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAChD,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC5C,MAAyE;IAE3E,MAAM,YAAY,GACd,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;IAChH,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,uEAAuE;QACvE,2BAA2B;QAC3B,4DAA4D;QAC5D,+DAA+D;QAC/D,gEAAgE;QAChE,yEAAyE;QACzE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,uBAAuB,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,2EAA2E;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AACD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,+BAA+B,CAAC,SAAwC;IAEtF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IAC5C,IAAI,SAAS,KAAK,EAAE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,iEAAiE;QACjE,gEAAgE;QAChE,kDAAkD;QAClD,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAyD;QAChG,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC;QACxB,QAAQ,EAAE,aAAa;QACvB,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,WAAW;QACX,kBAAkB;QAClB,gBAAgB;QAChB,sCAAsC;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,aAAa,CAAC,CAAC;AACzB,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.\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 = new Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>();\nconst timeStampByName = new Map<string, Types.Events.ConsoleTimeStamp>();\n\nconst syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[] = [];\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n // TODO(andoli): Can we augment Renderer's entryToNode instead? To avoid the split of TimelineUIUtils's getEventSelfTime()?\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 if (!currentTimeStamp.args.data) {\n continue;\n }\n const timeStampName = String(currentTimeStamp.args.data.name ?? currentTimeStamp.args.data.message);\n timeStampByName.set(timeStampName, currentTimeStamp);\n const extensionData = extensionDataInConsoleTimeStamp(currentTimeStamp);\n const start = currentTimeStamp.args.data.start;\n const end = currentTimeStamp.args.data.end;\n if (!extensionData && !start && !end) {\n continue;\n }\n // If the start or end is a number, it's assumed to be a timestamp\n // from the tracing clock, so we use that directly, otherwise we\n // assume it's the label of a previous console timestamp, in which\n // case we use its corresponding timestamp.\n const startTimeStamp =\n typeof start === 'number' ? Types.Timing.Micro(start) : timeStampByName.get(String(start))?.ts;\n const endTimeStamp = typeof end === 'number' ? Types.Timing.Micro(end) : timeStampByName.get(String(end))?.ts;\n if (endTimeStamp !== undefined && startTimeStamp === undefined) {\n // Invalid data\n continue;\n }\n const entryStartTime = startTimeStamp ?? currentTimeStamp.ts;\n const entryEndTime = endTimeStamp ?? 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.Micro(entryEndTime - entryStartTime),\n ts: entryStartTime,\n ph: Types.Events.Phase.COMPLETE,\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.Micro(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: Array<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.Extensions.isExtensionPayloadMarker(extensionPayload) ? Types.Events.Phase.INSTANT :\n Types.Events.Phase.COMPLETE,\n pid: timing.pid,\n tid: timing.tid,\n ts: timing.ts,\n dur: timing.dur as Types.Timing.Micro,\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(\n timing: Types.Events.SyntheticUserTimingPair|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 if (!timeStamp.args.data) {\n return null;\n }\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"]}
|
|
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 = new Map<Types.Events.Event, Helpers.TreeHelpers.TraceEntryNode>();\nconst timeStampByName = new Map<string, Types.Events.ConsoleTimeStamp>();\n\nconst syntheticConsoleEntriesForTimingsTrack: Types.Events.SyntheticConsoleTimeStamp[] = [];\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n // TODO(andoli): Can we augment Renderer's entryToNode instead? To avoid the split of TimelineUIUtils's getEventSelfTime()?\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 if (!currentTimeStamp.args.data) {\n continue;\n }\n const timeStampName = String(currentTimeStamp.args.data.name ?? currentTimeStamp.args.data.message);\n timeStampByName.set(timeStampName, currentTimeStamp);\n const extensionData = extensionDataInConsoleTimeStamp(currentTimeStamp);\n const start = currentTimeStamp.args.data.start;\n const end = currentTimeStamp.args.data.end;\n if (!extensionData && !start && !end) {\n continue;\n }\n // If the start or end is a number, it's assumed to be a timestamp\n // from the tracing clock, so we use that directly, otherwise we\n // assume it's the label of a previous console timestamp, in which\n // case we use its corresponding timestamp.\n const startTimeStamp =\n typeof start === 'number' ? Types.Timing.Micro(start) : timeStampByName.get(String(start))?.ts;\n const endTimeStamp = typeof end === 'number' ? Types.Timing.Micro(end) : timeStampByName.get(String(end))?.ts;\n if (endTimeStamp !== undefined && startTimeStamp === undefined) {\n // Invalid data\n continue;\n }\n const entryStartTime = startTimeStamp ?? currentTimeStamp.ts;\n const entryEndTime = endTimeStamp ?? 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.Micro(entryEndTime - entryStartTime),\n ts: entryStartTime,\n ph: Types.Events.Phase.COMPLETE,\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.Micro(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: Array<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.Extensions.isExtensionPayloadMarker(extensionPayload) ? Types.Events.Phase.INSTANT :\n Types.Events.Phase.COMPLETE,\n pid: timing.pid,\n tid: timing.tid,\n ts: timing.ts,\n dur: timing.dur as Types.Timing.Micro,\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(\n timing: Types.Events.SyntheticUserTimingPair|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 if (!timeStamp.args.data) {\n return null;\n }\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"]}
|
|
@@ -76,13 +76,13 @@ function processNonFlowEvent(event) {
|
|
|
76
76
|
function processFlowEvent(flowPhaseEvent) {
|
|
77
77
|
const flowGroup = flowGroupTokenForFlowPhaseEvent(flowPhaseEvent);
|
|
78
78
|
switch (flowPhaseEvent.ph) {
|
|
79
|
-
case (
|
|
79
|
+
case (Types.Events.Phase.FLOW_START): {
|
|
80
80
|
const flowMetadata = { flowId: flowPhaseEvent.id, times: new Map([[flowPhaseEvent.ts, undefined]]) };
|
|
81
81
|
flowDataByGroupToken.set(flowGroup, flowPhaseEvent.id);
|
|
82
82
|
addFlowIdToEventBinding(flowPhaseEvent, flowMetadata.flowId);
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
|
-
case (
|
|
85
|
+
case (Types.Events.Phase.FLOW_STEP): {
|
|
86
86
|
const flowId = flowDataByGroupToken.get(flowGroup);
|
|
87
87
|
if (flowId === undefined) {
|
|
88
88
|
// Found non-start flow event with no corresponding start flow,
|
|
@@ -92,7 +92,7 @@ function processFlowEvent(flowPhaseEvent) {
|
|
|
92
92
|
addFlowIdToEventBinding(flowPhaseEvent, flowId);
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
|
-
case (
|
|
95
|
+
case (Types.Events.Phase.FLOW_END): {
|
|
96
96
|
const flowId = flowDataByGroupToken.get(flowGroup);
|
|
97
97
|
if (flowId === undefined) {
|
|
98
98
|
// Found non-start flow event with no corresponding start flow,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlowsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/FlowsHandler.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.\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Types from '../types/types.js';\n\n// A flow is a logic connection between trace events. We display this\n// connection as arrows between trace events belonging to the same flow.\n\n// In the trace event format, flows are represented with pairing \"flow\n// phase\" events. Each flow phase event corresponds to one trace event\n// and indicates the role a trace event plays in a flow (start, step or\n// end). For each flow, one `start` and one `end` phase events are\n// included, while the amount of `step` phase events can be >= 0.\n\n// A flow phase event is assigned to a trace event when their cat, tid,\n// pid and ts are equal (see @flowPhaseBindingTokenForEvent ).\n\n// It's possible for a single event to belong to multiple flows. In that\n// case, it will have multiple corresponding flow phase events (one\n// per flow).\n\n// To parse flows, we first handle flow phase events, by creating unique\n// flows with the timestamps of each phase. Then, we place trace events\n// in the flows where their corresponding phase events were placed (if\n// there are any corresponding flow phase events at all).\nconst flowDataByGroupToken = new Map<string, number>();\n\ninterface EventFlowData {\n flows: Set<number>;\n bindingParsed: boolean;\n}\ntype FlowBindingTuple =\n Map<Types.Timing.Micro, Map<Types.Events.ProcessID, Map<Types.Events.ThreadID, Map<string, EventFlowData>>>>;\n\n// Given a trace event's flow binding tuple (timestamp, process id,\n// thread id and category) we determine if there is any flow data bound\n// to it by using this map's content. It's built when processing flow\n// events in a trace.\n// An alternative to having a map of four levels is having single map\n// from a string token built from concatenating the binding data to the\n// corresponding flow data. However, this token would be calculated for\n// every event in a trace, resulting in a lot of memory overhead and\n// major GC triggering. So we are trading off readability for\n// performance.\nconst boundFlowData: FlowBindingTuple = new Map();\n\nconst flowsById = new Map<number, Map<Types.Timing.Micro, Types.Events.Event>>();\nconst flowEvents: Types.Events.FlowEvent[] = [];\nconst nonFlowEvents: Types.Events.Event[] = [];\nlet flows: Types.Events.Event[][] = [];\nconst ID_COMPONENT_SEPARATOR = '-$-';\nexport function reset(): void {\n flows = [];\n flowEvents.length = 0;\n nonFlowEvents.length = 0;\n flowDataByGroupToken.clear();\n boundFlowData.clear();\n flowsById.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isFlowPhaseEvent(event)) {\n flowEvents.push(event);\n return;\n }\n nonFlowEvents.push(event);\n}\n\nfunction processNonFlowEvent(event: Types.Events.Event): void {\n const flowDataForEvent = boundFlowData.get(event.ts)?.get(event.pid)?.get(event.tid)?.get(event.cat);\n if (!flowDataForEvent) {\n return;\n }\n const {flows, bindingParsed} = flowDataForEvent;\n if (bindingParsed) {\n // We only consider the first event for a given flow binding tuple.\n return;\n }\n for (const flowId of flows) {\n const flow = Platform.MapUtilities.getWithDefault(\n flowsById, flowId, () => new Map<Types.Timing.Micro, Types.Events.Event>());\n flow.set(event.ts, event);\n }\n flowDataForEvent.bindingParsed = true;\n}\n\n/**\n * Creates unique flows by tracking flow phase events. A new created\n * flow whenever a flow start phase event is detected.\n * Subsequent flow phase events with the same group token are added to\n * this flow until a flow end phase is detected.\n */\nfunction processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {\n const flowGroup = flowGroupTokenForFlowPhaseEvent(flowPhaseEvent);\n switch (flowPhaseEvent.ph) {\n case (Types.Events.Phase.FLOW_START): {\n const flowMetadata = {flowId: flowPhaseEvent.id, times: new Map([[flowPhaseEvent.ts, undefined]])};\n flowDataByGroupToken.set(flowGroup, flowPhaseEvent.id);\n addFlowIdToEventBinding(flowPhaseEvent, flowMetadata.flowId);\n return;\n }\n case (Types.Events.Phase.FLOW_STEP): {\n const flowId = flowDataByGroupToken.get(flowGroup);\n if (flowId === undefined) {\n // Found non-start flow event with no corresponding start flow,\n // start event. Quietly ignore the problematic event.\n return;\n }\n addFlowIdToEventBinding(flowPhaseEvent, flowId);\n return;\n }\n case (Types.Events.Phase.FLOW_END): {\n const flowId = flowDataByGroupToken.get(flowGroup);\n if (flowId === undefined) {\n // Found non-start flow event with no corresponding start flow,\n // start event. Quietly ignore the problematic event.\n return;\n }\n addFlowIdToEventBinding(flowPhaseEvent, flowId);\n // We don't need this data anymore as the flow has been finished,\n // so we can drop it.\n flowDataByGroupToken.delete(flowGroup);\n }\n }\n}\n\ntype MapValueType<T extends Map<unknown, unknown>> = NonNullable<ReturnType<T['get']>>;\n/**\n * A single trace event can belong to multiple flows. This method\n * tracks which flows (flowId) an event belongs to given its flow\n * binding tuple (made of its ts, pid, tid and cat).\n */\nfunction addFlowIdToEventBinding(event: Types.Events.Event, flowId: number): void {\n const flowsByPid = Platform.MapUtilities.getWithDefault<Types.Timing.Micro, MapValueType<typeof boundFlowData>>(\n boundFlowData, event.ts, () => new Map());\n const flowsByTid = Platform.MapUtilities.getWithDefault<Types.Events.ProcessID, MapValueType<typeof flowsByPid>>(\n flowsByPid, event.pid, () => new Map());\n const flowsByCat = Platform.MapUtilities.getWithDefault<Types.Events.ThreadID, MapValueType<typeof flowsByTid>>(\n flowsByTid, event.tid, () => new Map());\n const flowData =\n Platform.MapUtilities.getWithDefault(flowsByCat, event.cat, () => ({flows: new Set(), bindingParsed: false}));\n flowData.flows.add(flowId);\n}\n\n/**\n * Returns a token to group flow phase events (start, step and end)\n * belonging to the same flow. Flow phase events belonging to the same\n * flow share category, thread id, process id and name.\n *\n * Note that other phase events of other flows can share these\n * attributes too. For this reason, we group flow phase events in\n * cycles. A cycle starts on a flow start phase event and finishes on a\n * flow end phase event. For this reason, flow phase events need to be\n * handled in timestamp order.\n */\nfunction flowGroupTokenForFlowPhaseEvent(event: Types.Events.FlowEvent): string {\n return `${event.cat}${ID_COMPONENT_SEPARATOR}${event.name}${ID_COMPONENT_SEPARATOR}${event.id}`;\n}\n\nexport async function finalize(): Promise<void> {\n // Order is important: flow events need to be handled first.\n flowEvents.forEach(processFlowEvent);\n nonFlowEvents.forEach(processNonFlowEvent);\n flows = [...flowsById.values()]\n .map(flowMapping => [...flowMapping.values()])\n .map(flow => flow.filter(event => event !== undefined))\n .filter(flow => flow.length > 1);\n}\n\nexport function data(): {flows: Types.Events.Event[][]} {\n return {\n flows,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FlowsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/FlowsHandler.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.\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Types from '../types/types.js';\n\n// A flow is a logic connection between trace events. We display this\n// connection as arrows between trace events belonging to the same flow.\n\n// In the trace event format, flows are represented with pairing \"flow\n// phase\" events. Each flow phase event corresponds to one trace event\n// and indicates the role a trace event plays in a flow (start, step or\n// end). For each flow, one `start` and one `end` phase events are\n// included, while the amount of `step` phase events can be >= 0.\n\n// A flow phase event is assigned to a trace event when their cat, tid,\n// pid and ts are equal (see @flowPhaseBindingTokenForEvent ).\n\n// It's possible for a single event to belong to multiple flows. In that\n// case, it will have multiple corresponding flow phase events (one\n// per flow).\n\n// To parse flows, we first handle flow phase events, by creating unique\n// flows with the timestamps of each phase. Then, we place trace events\n// in the flows where their corresponding phase events were placed (if\n// there are any corresponding flow phase events at all).\nconst flowDataByGroupToken = new Map<string, number>();\n\ninterface EventFlowData {\n flows: Set<number>;\n bindingParsed: boolean;\n}\ntype FlowBindingTuple =\n Map<Types.Timing.Micro, Map<Types.Events.ProcessID, Map<Types.Events.ThreadID, Map<string, EventFlowData>>>>;\n\n// Given a trace event's flow binding tuple (timestamp, process id,\n// thread id and category) we determine if there is any flow data bound\n// to it by using this map's content. It's built when processing flow\n// events in a trace.\n// An alternative to having a map of four levels is having single map\n// from a string token built from concatenating the binding data to the\n// corresponding flow data. However, this token would be calculated for\n// every event in a trace, resulting in a lot of memory overhead and\n// major GC triggering. So we are trading off readability for\n// performance.\nconst boundFlowData: FlowBindingTuple = new Map();\n\nconst flowsById = new Map<number, Map<Types.Timing.Micro, Types.Events.Event>>();\nconst flowEvents: Types.Events.FlowEvent[] = [];\nconst nonFlowEvents: Types.Events.Event[] = [];\nlet flows: Types.Events.Event[][] = [];\nconst ID_COMPONENT_SEPARATOR = '-$-';\nexport function reset(): void {\n flows = [];\n flowEvents.length = 0;\n nonFlowEvents.length = 0;\n flowDataByGroupToken.clear();\n boundFlowData.clear();\n flowsById.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isFlowPhaseEvent(event)) {\n flowEvents.push(event);\n return;\n }\n nonFlowEvents.push(event);\n}\n\nfunction processNonFlowEvent(event: Types.Events.Event): void {\n const flowDataForEvent = boundFlowData.get(event.ts)?.get(event.pid)?.get(event.tid)?.get(event.cat);\n if (!flowDataForEvent) {\n return;\n }\n const {flows, bindingParsed} = flowDataForEvent;\n if (bindingParsed) {\n // We only consider the first event for a given flow binding tuple.\n return;\n }\n for (const flowId of flows) {\n const flow = Platform.MapUtilities.getWithDefault(\n flowsById, flowId, () => new Map<Types.Timing.Micro, Types.Events.Event>());\n flow.set(event.ts, event);\n }\n flowDataForEvent.bindingParsed = true;\n}\n\n/**\n * Creates unique flows by tracking flow phase events. A new created\n * flow whenever a flow start phase event is detected.\n * Subsequent flow phase events with the same group token are added to\n * this flow until a flow end phase is detected.\n */\nfunction processFlowEvent(flowPhaseEvent: Types.Events.FlowEvent): void {\n const flowGroup = flowGroupTokenForFlowPhaseEvent(flowPhaseEvent);\n switch (flowPhaseEvent.ph) {\n case (Types.Events.Phase.FLOW_START): {\n const flowMetadata = {flowId: flowPhaseEvent.id, times: new Map([[flowPhaseEvent.ts, undefined]])};\n flowDataByGroupToken.set(flowGroup, flowPhaseEvent.id);\n addFlowIdToEventBinding(flowPhaseEvent, flowMetadata.flowId);\n return;\n }\n case (Types.Events.Phase.FLOW_STEP): {\n const flowId = flowDataByGroupToken.get(flowGroup);\n if (flowId === undefined) {\n // Found non-start flow event with no corresponding start flow,\n // start event. Quietly ignore the problematic event.\n return;\n }\n addFlowIdToEventBinding(flowPhaseEvent, flowId);\n return;\n }\n case (Types.Events.Phase.FLOW_END): {\n const flowId = flowDataByGroupToken.get(flowGroup);\n if (flowId === undefined) {\n // Found non-start flow event with no corresponding start flow,\n // start event. Quietly ignore the problematic event.\n return;\n }\n addFlowIdToEventBinding(flowPhaseEvent, flowId);\n // We don't need this data anymore as the flow has been finished,\n // so we can drop it.\n flowDataByGroupToken.delete(flowGroup);\n }\n }\n}\n\ntype MapValueType<T extends Map<unknown, unknown>> = NonNullable<ReturnType<T['get']>>;\n/**\n * A single trace event can belong to multiple flows. This method\n * tracks which flows (flowId) an event belongs to given its flow\n * binding tuple (made of its ts, pid, tid and cat).\n */\nfunction addFlowIdToEventBinding(event: Types.Events.Event, flowId: number): void {\n const flowsByPid = Platform.MapUtilities.getWithDefault<Types.Timing.Micro, MapValueType<typeof boundFlowData>>(\n boundFlowData, event.ts, () => new Map());\n const flowsByTid = Platform.MapUtilities.getWithDefault<Types.Events.ProcessID, MapValueType<typeof flowsByPid>>(\n flowsByPid, event.pid, () => new Map());\n const flowsByCat = Platform.MapUtilities.getWithDefault<Types.Events.ThreadID, MapValueType<typeof flowsByTid>>(\n flowsByTid, event.tid, () => new Map());\n const flowData =\n Platform.MapUtilities.getWithDefault(flowsByCat, event.cat, () => ({flows: new Set(), bindingParsed: false}));\n flowData.flows.add(flowId);\n}\n\n/**\n * Returns a token to group flow phase events (start, step and end)\n * belonging to the same flow. Flow phase events belonging to the same\n * flow share category, thread id, process id and name.\n *\n * Note that other phase events of other flows can share these\n * attributes too. For this reason, we group flow phase events in\n * cycles. A cycle starts on a flow start phase event and finishes on a\n * flow end phase event. For this reason, flow phase events need to be\n * handled in timestamp order.\n */\nfunction flowGroupTokenForFlowPhaseEvent(event: Types.Events.FlowEvent): string {\n return `${event.cat}${ID_COMPONENT_SEPARATOR}${event.name}${ID_COMPONENT_SEPARATOR}${event.id}`;\n}\n\nexport async function finalize(): Promise<void> {\n // Order is important: flow events need to be handled first.\n flowEvents.forEach(processFlowEvent);\n nonFlowEvents.forEach(processNonFlowEvent);\n flows = [...flowsById.values()]\n .map(flowMapping => [...flowMapping.values()])\n .map(flow => flow.filter(event => event !== undefined))\n .filter(flow => flow.length > 1);\n}\n\nexport function data(): {flows: Types.Events.Event[][]} {\n return {\n flows,\n };\n}\n"]}
|