@paulirish/trace_engine 0.0.18 → 0.0.20
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/PAUL.readme.md +5 -0
- package/README.md +2 -5
- package/core/platform/StringUtilities.js +3 -3
- package/core/platform/StringUtilities.js.map +1 -1
- package/core/platform/TypedArrayUtilities.d.ts +26 -0
- package/core/platform/TypedArrayUtilities.js +111 -0
- package/core/platform/TypedArrayUtilities.js.map +1 -0
- package/core/platform/platform-tsconfig.json +1 -0
- package/core/platform/platform.d.ts +2 -1
- package/core/platform/platform.js +2 -1
- package/core/platform/platform.js.map +1 -1
- package/generated/protocol.d.ts +273 -5
- package/models/cpu_profile/CPUProfileDataModel.js +3 -3
- package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
- package/models/trace/EntriesFilter.d.ts +3 -2
- package/models/trace/EntriesFilter.js +5 -3
- package/models/trace/EntriesFilter.js.map +1 -1
- package/models/trace/LegacyTracingModel.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +1 -0
- package/models/trace/ModelImpl.js +5 -0
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.js +7 -1
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/extras/FetchNodes.d.ts +8 -0
- package/models/trace/extras/FetchNodes.js +54 -2
- package/models/trace/extras/FetchNodes.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +13 -0
- package/models/trace/handlers/ExtensionTraceDataHandler.js +93 -0
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -0
- package/models/trace/handlers/ImagePaintingHandler.d.ts +8 -0
- package/models/trace/handlers/ImagePaintingHandler.js +108 -0
- package/models/trace/handlers/ImagePaintingHandler.js.map +1 -0
- package/models/trace/handlers/InvalidationsHandler.js +9 -0
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.js +4 -2
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +3 -0
- package/models/trace/handlers/ModelHandlers.js +3 -0
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/PageFramesHandler.d.ts +7 -0
- package/models/trace/handlers/PageFramesHandler.js +41 -0
- package/models/trace/handlers/PageFramesHandler.js.map +1 -0
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +0 -7
- package/models/trace/handlers/PageLoadMetricsHandler.js +2 -21
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/handlers-tsconfig.json +3 -0
- package/models/trace/helpers/Extensions.d.ts +2 -0
- package/models/trace/helpers/Extensions.js +22 -0
- package/models/trace/helpers/Extensions.js.map +1 -0
- package/models/trace/helpers/Trace.d.ts +4 -3
- package/models/trace/helpers/Trace.js +17 -3
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/helpers-tsconfig.json +1 -0
- package/models/trace/helpers/helpers.d.ts +1 -0
- package/models/trace/helpers/helpers.js +1 -0
- package/models/trace/helpers/helpers.js.map +1 -1
- package/models/trace/root-causes/LayoutShift.d.ts +7 -1
- package/models/trace/root-causes/LayoutShift.js +19 -4
- package/models/trace/root-causes/LayoutShift.js.map +1 -1
- package/models/trace/root-causes/RootCauses.d.ts +1 -0
- package/models/trace/root-causes/RootCauses.js +1 -0
- package/models/trace/root-causes/RootCauses.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +62 -0
- package/models/trace/types/Extensions.js +38 -0
- package/models/trace/types/Extensions.js.map +1 -0
- package/models/trace/types/File.d.ts +10 -3
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +82 -14
- package/models/trace/types/TraceEvents.js +46 -9
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/types-tsconfig.json +1 -0
- package/models/trace/types/types.d.ts +1 -0
- package/models/trace/types/types.js +1 -0
- package/models/trace/types/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,6 +9,14 @@ export declare function clearCacheForTesting(): void;
|
|
|
9
9
|
* first lookup.
|
|
10
10
|
*/
|
|
11
11
|
export declare function domNodeForBackendNodeID(modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Extracts a set of NodeIds for a given event.
|
|
14
|
+
* NOTE: you probably don't want to call this and instead use
|
|
15
|
+
* `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.
|
|
16
|
+
* This method is primarily exported so we can test the logic more easily
|
|
17
|
+
* without having to mock the CDP layer.
|
|
18
|
+
**/
|
|
19
|
+
export declare function nodeIdsForEvent(modelData: Handlers.Types.TraceParseData, event: Types.TraceEvents.TraceEventData): Set<Protocol.DOM.BackendNodeId>;
|
|
12
20
|
/**
|
|
13
21
|
* Looks up for backend node ids in different types of trace events
|
|
14
22
|
* and resolves them into related DOM nodes.
|
|
@@ -33,6 +33,57 @@ export async function domNodeForBackendNodeID(modelData, nodeId) {
|
|
|
33
33
|
domLookUpSingleNodeCache.set(modelData, cacheForModel);
|
|
34
34
|
return result;
|
|
35
35
|
}
|
|
36
|
+
const nodeIdsForEventCache = new WeakMap();
|
|
37
|
+
/**
|
|
38
|
+
* Extracts a set of NodeIds for a given event.
|
|
39
|
+
* NOTE: you probably don't want to call this and instead use
|
|
40
|
+
* `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.
|
|
41
|
+
* This method is primarily exported so we can test the logic more easily
|
|
42
|
+
* without having to mock the CDP layer.
|
|
43
|
+
**/
|
|
44
|
+
export function nodeIdsForEvent(modelData, event) {
|
|
45
|
+
const fromCache = nodeIdsForEventCache.get(event);
|
|
46
|
+
if (fromCache) {
|
|
47
|
+
return fromCache;
|
|
48
|
+
}
|
|
49
|
+
const foundIds = new Set();
|
|
50
|
+
if (Types.TraceEvents.isTraceEventLayout(event)) {
|
|
51
|
+
event.args.endData.layoutRoots.forEach(root => foundIds.add(root.nodeId));
|
|
52
|
+
}
|
|
53
|
+
else if (Types.TraceEvents.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {
|
|
54
|
+
event.args.data.impacted_nodes.forEach(node => foundIds.add(node.node_id));
|
|
55
|
+
}
|
|
56
|
+
else if (Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) &&
|
|
57
|
+
typeof event.args.data?.nodeId !== 'undefined') {
|
|
58
|
+
foundIds.add(event.args.data.nodeId);
|
|
59
|
+
}
|
|
60
|
+
else if (Types.TraceEvents.isTraceEventPaint(event) && typeof event.args.data.nodeId !== 'undefined') {
|
|
61
|
+
foundIds.add(event.args.data.nodeId);
|
|
62
|
+
}
|
|
63
|
+
else if (Types.TraceEvents.isTraceEventPaintImage(event) && typeof event.args.data.nodeId !== 'undefined') {
|
|
64
|
+
foundIds.add(event.args.data.nodeId);
|
|
65
|
+
}
|
|
66
|
+
else if (Types.TraceEvents.isTraceEventScrollLayer(event) && typeof event.args.data.nodeId !== 'undefined') {
|
|
67
|
+
foundIds.add(event.args.data.nodeId);
|
|
68
|
+
}
|
|
69
|
+
else if (Types.TraceEvents.isTraceEventDecodeImage(event)) {
|
|
70
|
+
// For a DecodeImage event, we can use the ImagePaintingHandler, which has
|
|
71
|
+
// done the work to build the relationship between a DecodeImage event and
|
|
72
|
+
// the corresponding PaintImage event.
|
|
73
|
+
const paintImageEvent = modelData.ImagePainting.paintImageForEvent.get(event);
|
|
74
|
+
if (paintImageEvent && typeof paintImageEvent.args.data.nodeId !== 'undefined') {
|
|
75
|
+
foundIds.add(paintImageEvent.args.data.nodeId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(event) && event.args?.LazyPixelRef) {
|
|
79
|
+
const paintImageEvent = modelData.ImagePainting.paintImageByDrawLazyPixelRef.get(event.args.LazyPixelRef);
|
|
80
|
+
if (paintImageEvent && typeof paintImageEvent.args.data.nodeId !== 'undefined') {
|
|
81
|
+
foundIds.add(paintImageEvent.args.data.nodeId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
nodeIdsForEventCache.set(event, foundIds);
|
|
85
|
+
return foundIds;
|
|
86
|
+
}
|
|
36
87
|
/**
|
|
37
88
|
* Looks up for backend node ids in different types of trace events
|
|
38
89
|
* and resolves them into related DOM nodes.
|
|
@@ -40,8 +91,9 @@ export async function domNodeForBackendNodeID(modelData, nodeId) {
|
|
|
40
91
|
* containing node ids which we want to resolve.
|
|
41
92
|
*/
|
|
42
93
|
export async function extractRelatedDOMNodesFromEvent(modelData, event) {
|
|
43
|
-
|
|
44
|
-
|
|
94
|
+
const nodeIds = nodeIdsForEvent(modelData, event);
|
|
95
|
+
if (nodeIds.size) {
|
|
96
|
+
return domNodesForMultipleBackendNodeIds(modelData, Array.from(nodeIds));
|
|
45
97
|
}
|
|
46
98
|
return null;
|
|
47
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FetchNodes.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/FetchNodes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nconst domLookUpSingleNodeCache =\n new Map<Handlers.Types.TraceParseData, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\nconst domLookUpBatchNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Array<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>>();\n\nexport function clearCacheForTesting(): void {\n domLookUpSingleNodeCache.clear();\n domLookUpBatchNodesCache.clear();\n layoutShiftSourcesCache.clear();\n normalizedLayoutShiftNodesCache.clear();\n}\n\n/**\n * Looks up the DOM Node on the page for the given BackendNodeId. Uses the\n * provided TraceParseData as the cache and will cache the result after the\n * first lookup.\n */\nexport async function domNodeForBackendNodeID(\n modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode|null> {\n const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);\n if (fromCache !== undefined) {\n return fromCache;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return null;\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));\n const result = domNodesMap?.get(nodeId) || null;\n\n const cacheForModel =\n domLookUpSingleNodeCache.get(modelData) || new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>();\n cacheForModel.set(nodeId, result);\n domLookUpSingleNodeCache.set(modelData, cacheForModel);\n\n return result;\n}\n\n/**\n * Looks up for backend node ids in different types of trace events\n * and resolves them into related DOM nodes.\n * This method should be progressively updated to support more events\n * containing node ids which we want to resolve.\n */\nexport async function extractRelatedDOMNodesFromEvent(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventData): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>|null> {\n if (Types.TraceEvents.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {\n return domNodesForMultipleBackendNodeIds(modelData, event.args.data.impacted_nodes.map(node => node.node_id));\n }\n return null;\n}\n\n/**\n * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.\n * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.\n */\nexport async function domNodesForMultipleBackendNodeIds(\n modelData: Handlers.Types.TraceParseData,\n nodeIds: Array<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>> {\n const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);\n if (fromCache) {\n return fromCache;\n }\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return new Map();\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set(nodeIds)) || new Map();\n\n const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||\n new Map<Array<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\n cacheForModel.set(nodeIds, domNodesMap);\n domLookUpBatchNodesCache.set(modelData, cacheForModel);\n\n return domNodesMap;\n}\n\nconst layoutShiftSourcesCache = new Map<\n Handlers.Types.TraceParseData, Map<Types.TraceEvents.TraceEventLayoutShift, readonly LayoutShiftSource[]>>();\n\nconst normalizedLayoutShiftNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>>();\n\nexport interface LayoutShiftSource {\n previousRect: DOMRect;\n currentRect: DOMRect;\n node: SDK.DOMModel.DOMNode;\n}\n\n/**\n * Calculates and returns a list of sources for a LayoutShift.\n * Here, a source is considered as a node that moved and contributed to the\n * given LayoutShift existing and the score it was given. Each source returned\n * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both\n * before and now, so we can see how this node changed and how that impacted the\n * layout shift.\n *\n * This data is cached based on the provided model data and the given layout\n * shift, so it is is safe to call multiple times with the same input.\n */\nexport async function sourcesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]> {\n const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n const sources: LayoutShiftSource[] = [];\n await Promise.all(impactedNodes.map(async node => {\n const domNode = await domNodeForBackendNodeID(modelData, node.node_id);\n if (domNode) {\n sources.push({\n previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),\n currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),\n node: domNode,\n });\n }\n }));\n const cacheForModel =\n layoutShiftSourcesCache.get(modelData) || new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftSource[]>();\n cacheForModel.set(event, sources);\n layoutShiftSourcesCache.set(modelData, cacheForModel);\n return sources;\n}\n\n/**\n * Takes a LayoutShift and normalizes its node dimensions based on the device\n * pixel ratio (DPR) of the user's display.\n * This is required because the Layout Instability API is not based on CSS\n * pixels, but physical pixels. Therefore we need to map these to normalized CSS\n * pixels if we can. For example, if the user is on a device with a DPR of 2,\n * the values of the node dimensions reported by the Instability API need to be\n * divided by 2 to be accurate.\n * This function is safe to call multiple times as results are cached based on\n * the provided model data.\n * See https://crbug.com/1300309 for details.\n */\nexport async function normalizedImpactedNodesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]> {\n const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args?.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n\n let viewportScale: number|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Get the CSS-to-physical pixel ratio of the device the inspected\n // target is running at.\n const evaluateResult = await target?.runtimeAgent().invoke_evaluate({expression: 'window.devicePixelRatio'});\n if (evaluateResult?.result.type === 'number') {\n viewportScale = evaluateResult?.result.value as number ?? null;\n }\n\n if (!viewportScale) {\n // Bail and return the nodes as is.\n return impactedNodes;\n }\n\n const normalizedNodes: Types.TraceEvents.TraceImpactedNode[] = [];\n for (const impactedNode of impactedNodes) {\n const newNode = {...impactedNode};\n for (let i = 0; i < impactedNode.old_rect.length; i++) {\n newNode.old_rect[i] /= viewportScale;\n }\n for (let i = 0; i < impactedNode.new_rect.length; i++) {\n newNode.new_rect[i] /= viewportScale;\n }\n normalizedNodes.push(newNode);\n }\n\n const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||\n new Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>();\n cacheForModel.set(event, normalizedNodes);\n normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);\n\n return normalizedNodes;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FetchNodes.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/FetchNodes.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAGhD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,wBAAwB,GAC1B,IAAI,GAAG,EAA6F,CAAC;AACzG,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAEiE,CAAC;AAE1G,MAAM,UAAU,oBAAoB;IAClC,wBAAwB,CAAC,KAAK,EAAE,CAAC;IACjC,wBAAwB,CAAC,KAAK,EAAE,CAAC;IACjC,uBAAuB,CAAC,KAAK,EAAE,CAAC;IAChC,+BAA+B,CAAC,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,SAAwC,EAAE,MAAkC;IAC9E,MAAM,SAAS,GAAG,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,+BAA+B,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,MAAM,GAAG,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAEhD,MAAM,aAAa,GACf,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAyD,CAAC;IAChH,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,wBAAwB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAEvD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAAqE,CAAC;AAC9G;;;;;;IAMI;AACJ,MAAM,UAAU,eAAe,CAC3B,SAAwC,EACxC,KAAuC;IAEzC,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEvD,IAAI,KAAK,CAAC,WAAW,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5E,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC;QAC9F,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7E,CAAC;SAAM,IACH,KAAK,CAAC,WAAW,CAAC,2CAA2C,CAAC,KAAK,CAAC;QACpE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACnD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACvG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC5G,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC7G,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,0EAA0E;QAC1E,0EAA0E;QAC1E,sCAAsC;QACtC,MAAM,eAAe,GAAG,SAAS,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,eAAe,IAAI,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC/E,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QAC7F,MAAM,eAAe,GAAG,SAAS,CAAC,aAAa,CAAC,4BAA4B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1G,IAAI,eAAe,IAAI,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC/E,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,oBAAoB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACjD,SAAwC,EACxC,KAAuC;IACzC,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,iCAAiC,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACnD,SAAwC,EACxC,OAA0C;IAC5C,MAAM,SAAS,GAAG,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,+BAA+B,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;IAElG,MAAM,aAAa,GAAG,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC;QACzD,IAAI,GAAG,EAAiG,CAAC;IAC7G,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACxC,wBAAwB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAEvD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,uBAAuB,GAAG,IAAI,GAAG,EACyE,CAAC;AAEjH,MAAM,+BAA+B,GAAG,IAAI,GAAG,EAEoD,CAAC;AAQpG;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACvC,SAAwC,EACxC,KAA8C;IAChD,MAAM,SAAS,GAAG,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACrE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;IACtD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;QAC/C,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACjG,WAAW,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChG,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC,CAAC;IACJ,MAAM,aAAa,GACf,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAgE,CAAC;IACtH,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,uBAAuB,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACvD,SAAwC,EACxC,KAA8C;IAChD,MAAM,SAAS,GAAG,+BAA+B,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7E,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;IACvD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,aAAa,GAAgB,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC9E,kEAAkE;IAClE,wBAAwB;IACxB,MAAM,cAAc,GAAG,MAAM,MAAM,EAAE,YAAY,EAAE,CAAC,eAAe,CAAC,EAAC,UAAU,EAAE,yBAAyB,EAAC,CAAC,CAAC;IAC7G,IAAI,cAAc,EAAE,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7C,aAAa,GAAG,cAAc,EAAE,MAAM,CAAC,KAAe,IAAI,IAAI,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,mCAAmC;QACnC,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,eAAe,GAA0C,EAAE,CAAC;IAClE,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,EAAC,GAAG,YAAY,EAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtD,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC;QACvC,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtD,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC;QACvC,CAAC;QACD,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,aAAa,GAAG,+BAA+B,CAAC,GAAG,CAAC,SAAS,CAAC;QAChE,IAAI,GAAG,EAA2F,CAAC;IACvG,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAC1C,+BAA+B,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAE9D,OAAO,eAAe,CAAC;AACzB,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nconst domLookUpSingleNodeCache =\n new Map<Handlers.Types.TraceParseData, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\nconst domLookUpBatchNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Array<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>>();\n\nexport function clearCacheForTesting(): void {\n domLookUpSingleNodeCache.clear();\n domLookUpBatchNodesCache.clear();\n layoutShiftSourcesCache.clear();\n normalizedLayoutShiftNodesCache.clear();\n}\n\n/**\n * Looks up the DOM Node on the page for the given BackendNodeId. Uses the\n * provided TraceParseData as the cache and will cache the result after the\n * first lookup.\n */\nexport async function domNodeForBackendNodeID(\n modelData: Handlers.Types.TraceParseData, nodeId: Protocol.DOM.BackendNodeId): Promise<SDK.DOMModel.DOMNode|null> {\n const fromCache = domLookUpSingleNodeCache.get(modelData)?.get(nodeId);\n if (fromCache !== undefined) {\n return fromCache;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return null;\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));\n const result = domNodesMap?.get(nodeId) || null;\n\n const cacheForModel =\n domLookUpSingleNodeCache.get(modelData) || new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>();\n cacheForModel.set(nodeId, result);\n domLookUpSingleNodeCache.set(modelData, cacheForModel);\n\n return result;\n}\n\nconst nodeIdsForEventCache = new WeakMap<Types.TraceEvents.TraceEventData, Set<Protocol.DOM.BackendNodeId>>();\n/**\n * Extracts a set of NodeIds for a given event.\n * NOTE: you probably don't want to call this and instead use\n * `extractRelatedDOMNodesFromEvent`, which will fetch the nodes over CDP.\n * This method is primarily exported so we can test the logic more easily\n * without having to mock the CDP layer.\n **/\nexport function nodeIdsForEvent(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventData,\n ): Set<Protocol.DOM.BackendNodeId> {\n const fromCache = nodeIdsForEventCache.get(event);\n if (fromCache) {\n return fromCache;\n }\n const foundIds = new Set<Protocol.DOM.BackendNodeId>();\n\n if (Types.TraceEvents.isTraceEventLayout(event)) {\n event.args.endData.layoutRoots.forEach(root => foundIds.add(root.nodeId));\n } else if (Types.TraceEvents.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {\n event.args.data.impacted_nodes.forEach(node => foundIds.add(node.node_id));\n } else if (\n Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) &&\n typeof event.args.data?.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.TraceEvents.isTraceEventPaint(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.TraceEvents.isTraceEventPaintImage(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.TraceEvents.isTraceEventScrollLayer(event) && typeof event.args.data.nodeId !== 'undefined') {\n foundIds.add(event.args.data.nodeId);\n } else if (Types.TraceEvents.isTraceEventDecodeImage(event)) {\n // For a DecodeImage event, we can use the ImagePaintingHandler, which has\n // done the work to build the relationship between a DecodeImage event and\n // the corresponding PaintImage event.\n const paintImageEvent = modelData.ImagePainting.paintImageForEvent.get(event);\n if (paintImageEvent && typeof paintImageEvent.args.data.nodeId !== 'undefined') {\n foundIds.add(paintImageEvent.args.data.nodeId);\n }\n } else if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(event) && event.args?.LazyPixelRef) {\n const paintImageEvent = modelData.ImagePainting.paintImageByDrawLazyPixelRef.get(event.args.LazyPixelRef);\n if (paintImageEvent && typeof paintImageEvent.args.data.nodeId !== 'undefined') {\n foundIds.add(paintImageEvent.args.data.nodeId);\n }\n }\n nodeIdsForEventCache.set(event, foundIds);\n return foundIds;\n}\n\n/**\n * Looks up for backend node ids in different types of trace events\n * and resolves them into related DOM nodes.\n * This method should be progressively updated to support more events\n * containing node ids which we want to resolve.\n */\nexport async function extractRelatedDOMNodesFromEvent(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventData): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>|null> {\n const nodeIds = nodeIdsForEvent(modelData, event);\n if (nodeIds.size) {\n return domNodesForMultipleBackendNodeIds(modelData, Array.from(nodeIds));\n }\n return null;\n}\n\n/**\n * Takes a set of Protocol.DOM.BackendNodeId ids and will return a map of NodeId=>DOMNode.\n * Results are cached based on 1) the provided TraceParseData and 2) the provided set of IDs.\n */\nexport async function domNodesForMultipleBackendNodeIds(\n modelData: Handlers.Types.TraceParseData,\n nodeIds: Array<Protocol.DOM.BackendNodeId>): Promise<Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>> {\n const fromCache = domLookUpBatchNodesCache.get(modelData)?.get(nodeIds);\n if (fromCache) {\n return fromCache;\n }\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return new Map();\n }\n\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set(nodeIds)) || new Map();\n\n const cacheForModel = domLookUpBatchNodesCache.get(modelData) ||\n new Map<Array<Protocol.DOM.BackendNodeId>, Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode|null>>();\n cacheForModel.set(nodeIds, domNodesMap);\n domLookUpBatchNodesCache.set(modelData, cacheForModel);\n\n return domNodesMap;\n}\n\nconst layoutShiftSourcesCache = new Map<\n Handlers.Types.TraceParseData, Map<Types.TraceEvents.TraceEventLayoutShift, readonly LayoutShiftSource[]>>();\n\nconst normalizedLayoutShiftNodesCache = new Map<\n Handlers.Types.TraceParseData,\n Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>>();\n\nexport interface LayoutShiftSource {\n previousRect: DOMRect;\n currentRect: DOMRect;\n node: SDK.DOMModel.DOMNode;\n}\n\n/**\n * Calculates and returns a list of sources for a LayoutShift.\n * Here, a source is considered as a node that moved and contributed to the\n * given LayoutShift existing and the score it was given. Each source returned\n * contains a reference to the DOM Node, and its dimensions (as a DOMRect), both\n * before and now, so we can see how this node changed and how that impacted the\n * layout shift.\n *\n * This data is cached based on the provided model data and the given layout\n * shift, so it is is safe to call multiple times with the same input.\n */\nexport async function sourcesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly LayoutShiftSource[]> {\n const fromCache = layoutShiftSourcesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n const sources: LayoutShiftSource[] = [];\n await Promise.all(impactedNodes.map(async node => {\n const domNode = await domNodeForBackendNodeID(modelData, node.node_id);\n if (domNode) {\n sources.push({\n previousRect: new DOMRect(node.old_rect[0], node.old_rect[1], node.old_rect[2], node.old_rect[3]),\n currentRect: new DOMRect(node.new_rect[0], node.new_rect[1], node.new_rect[2], node.new_rect[3]),\n node: domNode,\n });\n }\n }));\n const cacheForModel =\n layoutShiftSourcesCache.get(modelData) || new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftSource[]>();\n cacheForModel.set(event, sources);\n layoutShiftSourcesCache.set(modelData, cacheForModel);\n return sources;\n}\n\n/**\n * Takes a LayoutShift and normalizes its node dimensions based on the device\n * pixel ratio (DPR) of the user's display.\n * This is required because the Layout Instability API is not based on CSS\n * pixels, but physical pixels. Therefore we need to map these to normalized CSS\n * pixels if we can. For example, if the user is on a device with a DPR of 2,\n * the values of the node dimensions reported by the Instability API need to be\n * divided by 2 to be accurate.\n * This function is safe to call multiple times as results are cached based on\n * the provided model data.\n * See https://crbug.com/1300309 for details.\n */\nexport async function normalizedImpactedNodesForLayoutShift(\n modelData: Handlers.Types.TraceParseData,\n event: Types.TraceEvents.TraceEventLayoutShift): Promise<readonly Types.TraceEvents.TraceImpactedNode[]> {\n const fromCache = normalizedLayoutShiftNodesCache.get(modelData)?.get(event);\n if (fromCache) {\n return fromCache;\n }\n const impactedNodes = event.args?.data?.impacted_nodes;\n if (!impactedNodes) {\n return [];\n }\n\n let viewportScale: number|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Get the CSS-to-physical pixel ratio of the device the inspected\n // target is running at.\n const evaluateResult = await target?.runtimeAgent().invoke_evaluate({expression: 'window.devicePixelRatio'});\n if (evaluateResult?.result.type === 'number') {\n viewportScale = evaluateResult?.result.value as number ?? null;\n }\n\n if (!viewportScale) {\n // Bail and return the nodes as is.\n return impactedNodes;\n }\n\n const normalizedNodes: Types.TraceEvents.TraceImpactedNode[] = [];\n for (const impactedNode of impactedNodes) {\n const newNode = {...impactedNode};\n for (let i = 0; i < impactedNode.old_rect.length; i++) {\n newNode.old_rect[i] /= viewportScale;\n }\n for (let i = 0; i < impactedNode.new_rect.length; i++) {\n newNode.new_rect[i] /= viewportScale;\n }\n normalizedNodes.push(newNode);\n }\n\n const cacheForModel = normalizedLayoutShiftNodesCache.get(modelData) ||\n new Map<Types.TraceEvents.TraceEventLayoutShift, readonly Types.TraceEvents.TraceImpactedNode[]>();\n cacheForModel.set(event, normalizedNodes);\n normalizedLayoutShiftNodesCache.set(modelData, cacheForModel);\n\n return normalizedNodes;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
import { type TraceEventHandlerName } from './types.js';
|
|
3
|
+
export interface ExtensionTraceData {
|
|
4
|
+
extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];
|
|
5
|
+
extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];
|
|
6
|
+
}
|
|
7
|
+
export declare function handleEvent(_event: Types.TraceEvents.TraceEventData): void;
|
|
8
|
+
export declare function reset(): void;
|
|
9
|
+
export declare function finalize(): Promise<void>;
|
|
10
|
+
export declare function extractExtensionEntries(timings: (Types.TraceEvents.SyntheticUserTimingPair | Types.TraceEvents.TraceEventPerformanceMark)[]): void;
|
|
11
|
+
export declare function extensionDataInTiming(timing: Types.TraceEvents.SyntheticUserTimingPair | Types.TraceEvents.TraceEventPerformanceMark): Types.Extensions.ExtensionDataPayload | null;
|
|
12
|
+
export declare function data(): ExtensionTraceData;
|
|
13
|
+
export declare function deps(): TraceEventHandlerName[];
|
|
@@ -0,0 +1,93 @@
|
|
|
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 Helpers from '../helpers/helpers.js';
|
|
5
|
+
import * as Types from '../types/types.js';
|
|
6
|
+
import { data as userTimingsData } from './UserTimingsHandler.js';
|
|
7
|
+
const extensionFlameChartEntries = [];
|
|
8
|
+
const extensionTrackData = [];
|
|
9
|
+
const extensionMarkers = [];
|
|
10
|
+
let handlerState = 1 /* HandlerState.UNINITIALIZED */;
|
|
11
|
+
export function handleEvent(_event) {
|
|
12
|
+
// Implementation not needed because data is sourced from UserTimingsHandler
|
|
13
|
+
}
|
|
14
|
+
export function reset() {
|
|
15
|
+
handlerState = 2 /* HandlerState.INITIALIZED */;
|
|
16
|
+
extensionFlameChartEntries.length = 0;
|
|
17
|
+
extensionTrackData.length = 0;
|
|
18
|
+
extensionMarkers.length = 0;
|
|
19
|
+
}
|
|
20
|
+
export async function finalize() {
|
|
21
|
+
if (handlerState !== 2 /* HandlerState.INITIALIZED */) {
|
|
22
|
+
throw new Error('ExtensionTraceData handler is not initialized');
|
|
23
|
+
}
|
|
24
|
+
createExtensionFlameChartEntries();
|
|
25
|
+
handlerState = 3 /* HandlerState.FINALIZED */;
|
|
26
|
+
}
|
|
27
|
+
function createExtensionFlameChartEntries() {
|
|
28
|
+
const pairedMeasures = userTimingsData().performanceMeasures;
|
|
29
|
+
const marks = userTimingsData().performanceMarks;
|
|
30
|
+
const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);
|
|
31
|
+
extractExtensionEntries(mergedRawExtensionEvents);
|
|
32
|
+
Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionFlameChartEntries, extensionTrackData);
|
|
33
|
+
}
|
|
34
|
+
export function extractExtensionEntries(timings) {
|
|
35
|
+
for (const timing of timings) {
|
|
36
|
+
const extensionPayload = extensionDataInTiming(timing);
|
|
37
|
+
if (!extensionPayload) {
|
|
38
|
+
// Not an extension user timing.
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const extensionName = extensionPayload.metadata.extensionName;
|
|
42
|
+
if (!extensionName) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const extensionSyntheticEntry = {
|
|
46
|
+
name: timing.name,
|
|
47
|
+
ph: "X" /* Types.TraceEvents.Phase.COMPLETE */,
|
|
48
|
+
pid: Types.TraceEvents.ProcessID(0),
|
|
49
|
+
tid: Types.TraceEvents.ThreadID(0),
|
|
50
|
+
ts: timing.ts,
|
|
51
|
+
selfTime: Types.Timing.MicroSeconds(0),
|
|
52
|
+
dur: timing.dur,
|
|
53
|
+
cat: 'devtools.extension',
|
|
54
|
+
args: extensionPayload,
|
|
55
|
+
};
|
|
56
|
+
if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {
|
|
57
|
+
extensionMarkers.push(extensionSyntheticEntry);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (Types.Extensions.isExtensionPayloadFlameChartEntry(extensionPayload)) {
|
|
61
|
+
extensionFlameChartEntries.push(extensionSyntheticEntry);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function extensionDataInTiming(timing) {
|
|
67
|
+
const timingDetail = Types.TraceEvents.isTraceEventPerformanceMark(timing) ? timing.args.data?.detail :
|
|
68
|
+
timing.args.data.beginEvent.args.detail;
|
|
69
|
+
if (!timingDetail) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const detailObj = JSON.parse(timingDetail);
|
|
73
|
+
if (!('devtools' in detailObj)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (!('metadata' in detailObj['devtools'])) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return detailObj.devtools;
|
|
80
|
+
}
|
|
81
|
+
export function data() {
|
|
82
|
+
if (handlerState !== 3 /* HandlerState.FINALIZED */) {
|
|
83
|
+
throw new Error('ExtensionTraceData handler is not finalized');
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
extensionTrackData: [...extensionTrackData],
|
|
87
|
+
extensionMarkers: [...extensionMarkers],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export function deps() {
|
|
91
|
+
return ['UserTimings'];
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=ExtensionTraceDataHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\nimport {data as userTimingsData} from './UserTimingsHandler.js';\n\nconst extensionFlameChartEntries: Types.Extensions.SyntheticExtensionFlameChartEntry[] = [];\nconst extensionTrackData: Types.Extensions.ExtensionTrackData[] = [];\nconst extensionMarkers: Types.Extensions.SyntheticExtensionMarker[] = [];\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function handleEvent(_event: Types.TraceEvents.TraceEventData): void {\n // Implementation not needed because data is sourced from UserTimingsHandler\n}\n\nexport function reset(): void {\n handlerState = HandlerState.INITIALIZED;\n extensionFlameChartEntries.length = 0;\n extensionTrackData.length = 0;\n extensionMarkers.length = 0;\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('ExtensionTraceData handler is not initialized');\n }\n createExtensionFlameChartEntries();\n handlerState = HandlerState.FINALIZED;\n}\n\nfunction createExtensionFlameChartEntries(): void {\n const pairedMeasures: readonly Types.TraceEvents.SyntheticUserTimingPair[] = userTimingsData().performanceMeasures;\n const marks: readonly Types.TraceEvents.TraceEventPerformanceMark[] = userTimingsData().performanceMarks;\n const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);\n\n extractExtensionEntries(mergedRawExtensionEvents);\n Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionFlameChartEntries, extensionTrackData);\n}\n\nexport function extractExtensionEntries(\n timings: (Types.TraceEvents.SyntheticUserTimingPair|Types.TraceEvents.TraceEventPerformanceMark)[]): void {\n for (const timing of timings) {\n const extensionPayload = extensionDataInTiming(timing);\n if (!extensionPayload) {\n // Not an extension user timing.\n continue;\n }\n const extensionName = extensionPayload.metadata.extensionName;\n if (!extensionName) {\n continue;\n }\n const extensionSyntheticEntry = {\n name: timing.name,\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid: Types.TraceEvents.ProcessID(0),\n tid: Types.TraceEvents.ThreadID(0),\n ts: timing.ts,\n selfTime: Types.Timing.MicroSeconds(0),\n dur: timing.dur as Types.Timing.MicroSeconds,\n cat: 'devtools.extension',\n args: extensionPayload,\n };\n if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {\n extensionMarkers.push(extensionSyntheticEntry as Types.Extensions.SyntheticExtensionMarker);\n continue;\n }\n if (Types.Extensions.isExtensionPayloadFlameChartEntry(extensionPayload)) {\n extensionFlameChartEntries.push(extensionSyntheticEntry as Types.Extensions.SyntheticExtensionFlameChartEntry);\n continue;\n }\n }\n}\n\nexport function extensionDataInTiming(timing: Types.TraceEvents.SyntheticUserTimingPair|\n Types.TraceEvents.TraceEventPerformanceMark):\n Types.Extensions.ExtensionDataPayload|null {\n const timingDetail = Types.TraceEvents.isTraceEventPerformanceMark(timing) ? timing.args.data?.detail :\n timing.args.data.beginEvent.args.detail;\n if (!timingDetail) {\n return null;\n }\n const detailObj = JSON.parse(timingDetail);\n if (!('devtools' in detailObj)) {\n return null;\n }\n if (!('metadata' in detailObj['devtools'])) {\n return null;\n }\n return detailObj.devtools;\n}\n\nexport function data(): ExtensionTraceData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('ExtensionTraceData handler is not finalized');\n }\n\n return {\n extensionTrackData: [...extensionTrackData],\n extensionMarkers: [...extensionMarkers],\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['UserTimings'];\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Types from '../types/types.js';
|
|
2
|
+
export declare function reset(): void;
|
|
3
|
+
export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
|
|
4
|
+
export interface ImagePaintData {
|
|
5
|
+
paintImageByDrawLazyPixelRef: Map<number, Types.TraceEvents.TraceEventPaintImage>;
|
|
6
|
+
paintImageForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventPaintImage>;
|
|
7
|
+
}
|
|
8
|
+
export declare function data(): ImagePaintData;
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
* This handler is responsible for the relationships between:
|
|
7
|
+
* DecodeImage/ResizeImage, PaintImage and DrawLazyPixelRef events.
|
|
8
|
+
*
|
|
9
|
+
* When we get a DecodeImage event, we want to associate it to a PaintImage
|
|
10
|
+
* event, primarily so we can determine the NodeID of the image that was
|
|
11
|
+
* decoded.
|
|
12
|
+
* We can do this in two ways:
|
|
13
|
+
*
|
|
14
|
+
* 1. If there is a PaintImage event on the same thread, use that
|
|
15
|
+
* (if there are multiple, use the latest one).
|
|
16
|
+
*
|
|
17
|
+
* 2. If not, we can find the DecodeLazyPixelRef event on the same thread, and
|
|
18
|
+
* use the PaintImage event associated with it via the `LazyPixelRef` key.
|
|
19
|
+
*/
|
|
20
|
+
// Track paintImageEvents across threads.
|
|
21
|
+
const paintImageEvents = new Map();
|
|
22
|
+
const decodeLazyPixelRefEvents = new Map();
|
|
23
|
+
// A DrawLazyPixelRef event will contain a numerical reference in
|
|
24
|
+
// args.LazyPixelRef. As we parse each DrawLazyPixelRef, we can assign it to a
|
|
25
|
+
// paint event. Later we want to look up paint events by this reference, so we
|
|
26
|
+
// store them in this map.
|
|
27
|
+
const paintImageByLazyPixelRef = new Map();
|
|
28
|
+
// When we find events that we want to tie to a particular PaintImage event, we add them to this map.
|
|
29
|
+
// These are currently only DecodeImage and ResizeImage events, but the type is
|
|
30
|
+
// deliberately generic as in the future we might want to add more events that
|
|
31
|
+
// have a relationship to a individual PaintImage event.
|
|
32
|
+
const eventToPaintImage = new Map();
|
|
33
|
+
export function reset() {
|
|
34
|
+
paintImageEvents.clear();
|
|
35
|
+
decodeLazyPixelRefEvents.clear();
|
|
36
|
+
paintImageByLazyPixelRef.clear();
|
|
37
|
+
eventToPaintImage.clear();
|
|
38
|
+
}
|
|
39
|
+
export function handleEvent(event) {
|
|
40
|
+
if (Types.TraceEvents.isTraceEventPaintImage(event)) {
|
|
41
|
+
const forProcess = paintImageEvents.get(event.pid) ||
|
|
42
|
+
new Map();
|
|
43
|
+
const forThread = forProcess.get(event.tid) || [];
|
|
44
|
+
forThread.push(event);
|
|
45
|
+
forProcess.set(event.tid, forThread);
|
|
46
|
+
paintImageEvents.set(event.pid, forProcess);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (Types.TraceEvents.isTraceEventDecodeLazyPixelRef(event) && typeof event.args?.LazyPixelRef !== 'undefined') {
|
|
50
|
+
// Store these because we use them to tie DecodeImage to a PaintEvent.
|
|
51
|
+
const forProcess = decodeLazyPixelRefEvents.get(event.pid) ||
|
|
52
|
+
new Map();
|
|
53
|
+
const forThread = forProcess.get(event.tid) || [];
|
|
54
|
+
forThread.push(event);
|
|
55
|
+
forProcess.set(event.tid, forThread);
|
|
56
|
+
decodeLazyPixelRefEvents.set(event.pid, forProcess);
|
|
57
|
+
}
|
|
58
|
+
// If we see a DrawLazyPixelRef event, we need to find the last PaintImage
|
|
59
|
+
// event on the thread and associate it to the LazyPixelRef that is supplied
|
|
60
|
+
// in the DrawLazyPixelRef event.
|
|
61
|
+
// This means that later on if we see a DecodeLazyPixelRef event with the
|
|
62
|
+
// same LazyPixelRef key, we can find its associated PaintImage event by
|
|
63
|
+
// looking it up.
|
|
64
|
+
if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(event) && typeof event.args?.LazyPixelRef !== 'undefined') {
|
|
65
|
+
const lastPaintEvent = paintImageEvents.get(event.pid)?.get(event.tid)?.at(-1);
|
|
66
|
+
if (!lastPaintEvent) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
paintImageByLazyPixelRef.set(event.args.LazyPixelRef, lastPaintEvent);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (Types.TraceEvents.isTraceEventDecodeImage(event)) {
|
|
73
|
+
// When we see a DecodeImage, we want to associate it to a PaintImage
|
|
74
|
+
// event. We try two approaches:
|
|
75
|
+
//
|
|
76
|
+
// 1. If the thread of the DecodeImage event has a previous PaintImage
|
|
77
|
+
// event, that is the associated event.
|
|
78
|
+
//
|
|
79
|
+
// 2. If that is false, we then look on the thread for a DecodeLazyPixelRef
|
|
80
|
+
// event. If we find that, we then look for its associated PaintImage
|
|
81
|
+
// event, which we associate via DrawLazyPixelRef events (the code block
|
|
82
|
+
// above this one)
|
|
83
|
+
//
|
|
84
|
+
// 1. Find a PaintImage event on the same thread. If we find it, that's our association done.
|
|
85
|
+
const lastPaintImageEventOnThread = paintImageEvents.get(event.pid)?.get(event.tid)?.at(-1);
|
|
86
|
+
if (lastPaintImageEventOnThread) {
|
|
87
|
+
eventToPaintImage.set(event, lastPaintImageEventOnThread);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// 2. Find the last DecodeLazyPixelRef event and, if we find it, find its associated PaintImage event.
|
|
91
|
+
const lastDecodeLazyPixelRef = decodeLazyPixelRefEvents.get(event.pid)?.get(event.tid)?.at(-1);
|
|
92
|
+
if (!lastDecodeLazyPixelRef || typeof lastDecodeLazyPixelRef.args?.LazyPixelRef === 'undefined') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const paintEvent = paintImageByLazyPixelRef.get(lastDecodeLazyPixelRef.args.LazyPixelRef);
|
|
96
|
+
if (!paintEvent) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
eventToPaintImage.set(event, paintEvent);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function data() {
|
|
103
|
+
return {
|
|
104
|
+
paintImageByDrawLazyPixelRef: paintImageByLazyPixelRef,
|
|
105
|
+
paintImageForEvent: eventToPaintImage,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=ImagePaintingHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImagePaintingHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ImagePaintingHandler.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 Types from '../types/types.js';\n\n/**\n * This handler is responsible for the relationships between:\n * DecodeImage/ResizeImage, PaintImage and DrawLazyPixelRef events.\n *\n * When we get a DecodeImage event, we want to associate it to a PaintImage\n * event, primarily so we can determine the NodeID of the image that was\n * decoded.\n * We can do this in two ways:\n *\n * 1. If there is a PaintImage event on the same thread, use that\n * (if there are multiple, use the latest one).\n *\n * 2. If not, we can find the DecodeLazyPixelRef event on the same thread, and\n * use the PaintImage event associated with it via the `LazyPixelRef` key.\n */\n\n// Track paintImageEvents across threads.\nconst paintImageEvents:\n Map<Types.TraceEvents.ProcessID, Map<Types.TraceEvents.ThreadID, Types.TraceEvents.TraceEventPaintImage[]>> =\n new Map();\nconst decodeLazyPixelRefEvents:\n Map<Types.TraceEvents.ProcessID,\n Map<Types.TraceEvents.ThreadID, Types.TraceEvents.TraceEventDecodeLazyPixelRef[]>> = new Map();\n\n// A DrawLazyPixelRef event will contain a numerical reference in\n// args.LazyPixelRef. As we parse each DrawLazyPixelRef, we can assign it to a\n// paint event. Later we want to look up paint events by this reference, so we\n// store them in this map.\nconst paintImageByLazyPixelRef: Map<number, Types.TraceEvents.TraceEventPaintImage> = new Map();\n\n// When we find events that we want to tie to a particular PaintImage event, we add them to this map.\n// These are currently only DecodeImage and ResizeImage events, but the type is\n// deliberately generic as in the future we might want to add more events that\n// have a relationship to a individual PaintImage event.\nconst eventToPaintImage: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventPaintImage> = new Map();\n\nexport function reset(): void {\n paintImageEvents.clear();\n decodeLazyPixelRefEvents.clear();\n paintImageByLazyPixelRef.clear();\n eventToPaintImage.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventPaintImage(event)) {\n const forProcess = paintImageEvents.get(event.pid) ||\n new Map<Types.TraceEvents.ThreadID, Types.TraceEvents.TraceEventPaintImage[]>();\n const forThread = forProcess.get(event.tid) || [];\n forThread.push(event);\n forProcess.set(event.tid, forThread);\n paintImageEvents.set(event.pid, forProcess);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventDecodeLazyPixelRef(event) && typeof event.args?.LazyPixelRef !== 'undefined') {\n // Store these because we use them to tie DecodeImage to a PaintEvent.\n const forProcess = decodeLazyPixelRefEvents.get(event.pid) ||\n new Map<Types.TraceEvents.ThreadID, Types.TraceEvents.TraceEventDecodeLazyPixelRef[]>();\n const forThread = forProcess.get(event.tid) || [];\n forThread.push(event);\n forProcess.set(event.tid, forThread);\n decodeLazyPixelRefEvents.set(event.pid, forProcess);\n }\n\n // If we see a DrawLazyPixelRef event, we need to find the last PaintImage\n // event on the thread and associate it to the LazyPixelRef that is supplied\n // in the DrawLazyPixelRef event.\n // This means that later on if we see a DecodeLazyPixelRef event with the\n // same LazyPixelRef key, we can find its associated PaintImage event by\n // looking it up.\n if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(event) && typeof event.args?.LazyPixelRef !== 'undefined') {\n const lastPaintEvent = paintImageEvents.get(event.pid)?.get(event.tid)?.at(-1);\n if (!lastPaintEvent) {\n return;\n }\n paintImageByLazyPixelRef.set(event.args.LazyPixelRef, lastPaintEvent);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventDecodeImage(event)) {\n // When we see a DecodeImage, we want to associate it to a PaintImage\n // event. We try two approaches:\n //\n // 1. If the thread of the DecodeImage event has a previous PaintImage\n // event, that is the associated event.\n //\n // 2. If that is false, we then look on the thread for a DecodeLazyPixelRef\n // event. If we find that, we then look for its associated PaintImage\n // event, which we associate via DrawLazyPixelRef events (the code block\n // above this one)\n //\n // 1. Find a PaintImage event on the same thread. If we find it, that's our association done.\n const lastPaintImageEventOnThread = paintImageEvents.get(event.pid)?.get(event.tid)?.at(-1);\n if (lastPaintImageEventOnThread) {\n eventToPaintImage.set(event, lastPaintImageEventOnThread);\n return;\n }\n\n // 2. Find the last DecodeLazyPixelRef event and, if we find it, find its associated PaintImage event.\n const lastDecodeLazyPixelRef = decodeLazyPixelRefEvents.get(event.pid)?.get(event.tid)?.at(-1);\n if (!lastDecodeLazyPixelRef || typeof lastDecodeLazyPixelRef.args?.LazyPixelRef === 'undefined') {\n return;\n }\n\n const paintEvent = paintImageByLazyPixelRef.get(lastDecodeLazyPixelRef.args.LazyPixelRef);\n if (!paintEvent) {\n return;\n }\n eventToPaintImage.set(event, paintEvent);\n }\n}\n\nexport interface ImagePaintData {\n paintImageByDrawLazyPixelRef: Map<number, Types.TraceEvents.TraceEventPaintImage>;\n paintImageForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventPaintImage>;\n}\n\nexport function data(): ImagePaintData {\n return {\n paintImageByDrawLazyPixelRef: paintImageByLazyPixelRef,\n paintImageForEvent: eventToPaintImage,\n };\n}\n"]}
|
|
@@ -43,6 +43,15 @@ function addInvalidationToEvent(event, invalidation) {
|
|
|
43
43
|
invalidationsForEvent.set(event, existingInvalidations);
|
|
44
44
|
}
|
|
45
45
|
export function handleEvent(event) {
|
|
46
|
+
if (Types.TraceEvents.isStyleRecalcSelectorStats(event) && lastRecalcStyleEvent) {
|
|
47
|
+
if (!lastRecalcStyleEvent.args.selector_stats) {
|
|
48
|
+
lastRecalcStyleEvent.args.selector_stats = event.args.selector_stats;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
lastRecalcStyleEvent.args.selector_stats.selector_timings.push(...event.args.selector_stats?.selector_timings ?? []);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
46
55
|
if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {
|
|
47
56
|
lastRecalcStyleEvent = event;
|
|
48
57
|
// Associate any prior invalidations with this recalc event.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvalidationsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InvalidationsHandler.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 Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst invalidationsForEvent = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>();\n\nlet lastRecalcStyleEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\n// Used to track paints so we track invalidations correctly per paint.\nlet hasPainted = false;\n\nconst allInvalidationTrackingEvents:\n Array<Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|Types.TraceEvents\n .TraceEventStyleInvalidatorInvalidationTracking|Types.TraceEvents.TraceEventLayoutInvalidationTracking> =\n [];\n\nexport function reset(): void {\n handlerState = HandlerState.UNINITIALIZED;\n invalidationsForEvent.clear();\n lastRecalcStyleEvent = null;\n allInvalidationTrackingEvents.length = 0;\n hasPainted = false;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InvalidationsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction addInvalidationToEvent(\n event: Types.TraceEvents.TraceEventData,\n invalidation: Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|\n Types.TraceEvents.TraceEventStyleInvalidatorInvalidationTracking|\n Types.TraceEvents.TraceEventLayoutInvalidationTracking): void {\n const existingInvalidations = invalidationsForEvent.get(event) || [];\n\n const syntheticInvalidation: Types.TraceEvents.SyntheticInvalidation = {\n ...invalidation,\n name: 'SyntheticInvalidation',\n frame: invalidation.args.data.frame,\n nodeId: invalidation.args.data.nodeId,\n rawEvent: invalidation,\n };\n\n if (invalidation.args.data.nodeName) {\n syntheticInvalidation.nodeName = invalidation.args.data.nodeName;\n }\n if (invalidation.args.data.reason) {\n syntheticInvalidation.reason = invalidation.args.data.reason;\n }\n if (invalidation.args.data.stackTrace) {\n syntheticInvalidation.stackTrace = invalidation.args.data.stackTrace;\n }\n\n existingInvalidations.push(syntheticInvalidation);\n invalidationsForEvent.set(event, existingInvalidations);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastRecalcStyleEvent = event;\n\n // Associate any prior invalidations with this recalc event.\n for (const invalidation of allInvalidationTrackingEvents) {\n if (Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n // LayoutInvalidation events cannot be associated with a LayoutTree\n // event.\n continue;\n }\n\n const recalcFrameId = lastRecalcStyleEvent.args.beginData?.frame;\n\n if (recalcFrameId && invalidation.args.data.frame === recalcFrameId) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(event)) {\n if (hasPainted) {\n // If we have painted, then we can clear out the list of all existing\n // invalidations, as we cannot associate them across frames.\n allInvalidationTrackingEvents.length = 0;\n lastRecalcStyleEvent = null;\n hasPainted = false;\n }\n\n // Style invalidation events can occur before and during recalc styles. When we get a recalc style event (aka TraceEventUpdateLayoutTree), we check and associate any prior invalidations with it.\n // But any invalidations that occur during a TraceEventUpdateLayoutTree\n // event would be reported in trace events after. So each time we get an\n // invalidation that might be due to a style recalc, we check if the\n // timings overlap and if so associate them.\n if (lastRecalcStyleEvent &&\n (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event))) {\n const recalcEndTime = lastRecalcStyleEvent.ts + (lastRecalcStyleEvent.dur || 0);\n if (event.ts >= lastRecalcStyleEvent.ts && event.ts <= recalcEndTime &&\n lastRecalcStyleEvent.args.beginData?.frame === event.args.data.frame) {\n addInvalidationToEvent(lastRecalcStyleEvent, event);\n }\n }\n\n allInvalidationTrackingEvents.push(event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventPaint(event)) {\n // Used to ensure that we do not create relationships across frames.\n hasPainted = true;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventLayout(event)) {\n const layoutFrame = event.args.beginData.frame;\n for (const invalidation of allInvalidationTrackingEvents) {\n // The only invalidations that cause a Layout are LayoutInvalidations :)\n if (!Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n continue;\n }\n\n if (invalidation.args.data.frame === layoutFrame) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InvalidationsHandler is not initialized');\n }\n\n handlerState = HandlerState.FINALIZED;\n}\n\ninterface InvalidationsData {\n invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>;\n}\n\nexport function data(): InvalidationsData {\n return {\n invalidationsForEvent,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InvalidationsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InvalidationsHandler.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 Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst invalidationsForEvent = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>();\n\nlet lastRecalcStyleEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\n// Used to track paints so we track invalidations correctly per paint.\nlet hasPainted = false;\n\nconst allInvalidationTrackingEvents:\n Array<Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|Types.TraceEvents\n .TraceEventStyleInvalidatorInvalidationTracking|Types.TraceEvents.TraceEventLayoutInvalidationTracking> =\n [];\n\nexport function reset(): void {\n handlerState = HandlerState.UNINITIALIZED;\n invalidationsForEvent.clear();\n lastRecalcStyleEvent = null;\n allInvalidationTrackingEvents.length = 0;\n hasPainted = false;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InvalidationsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction addInvalidationToEvent(\n event: Types.TraceEvents.TraceEventData,\n invalidation: Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|\n Types.TraceEvents.TraceEventStyleInvalidatorInvalidationTracking|\n Types.TraceEvents.TraceEventLayoutInvalidationTracking): void {\n const existingInvalidations = invalidationsForEvent.get(event) || [];\n\n const syntheticInvalidation: Types.TraceEvents.SyntheticInvalidation = {\n ...invalidation,\n name: 'SyntheticInvalidation',\n frame: invalidation.args.data.frame,\n nodeId: invalidation.args.data.nodeId,\n rawEvent: invalidation,\n };\n\n if (invalidation.args.data.nodeName) {\n syntheticInvalidation.nodeName = invalidation.args.data.nodeName;\n }\n if (invalidation.args.data.reason) {\n syntheticInvalidation.reason = invalidation.args.data.reason;\n }\n if (invalidation.args.data.stackTrace) {\n syntheticInvalidation.stackTrace = invalidation.args.data.stackTrace;\n }\n\n existingInvalidations.push(syntheticInvalidation);\n invalidationsForEvent.set(event, existingInvalidations);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isStyleRecalcSelectorStats(event) && lastRecalcStyleEvent) {\n if (!lastRecalcStyleEvent.args.selector_stats) {\n lastRecalcStyleEvent.args.selector_stats = event.args.selector_stats;\n } else {\n lastRecalcStyleEvent.args.selector_stats.selector_timings.push(\n ...event.args.selector_stats?.selector_timings ?? []);\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastRecalcStyleEvent = event;\n\n // Associate any prior invalidations with this recalc event.\n for (const invalidation of allInvalidationTrackingEvents) {\n if (Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n // LayoutInvalidation events cannot be associated with a LayoutTree\n // event.\n continue;\n }\n\n const recalcFrameId = lastRecalcStyleEvent.args.beginData?.frame;\n\n if (recalcFrameId && invalidation.args.data.frame === recalcFrameId) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(event)) {\n if (hasPainted) {\n // If we have painted, then we can clear out the list of all existing\n // invalidations, as we cannot associate them across frames.\n allInvalidationTrackingEvents.length = 0;\n lastRecalcStyleEvent = null;\n hasPainted = false;\n }\n\n // Style invalidation events can occur before and during recalc styles. When we get a recalc style event (aka TraceEventUpdateLayoutTree), we check and associate any prior invalidations with it.\n // But any invalidations that occur during a TraceEventUpdateLayoutTree\n // event would be reported in trace events after. So each time we get an\n // invalidation that might be due to a style recalc, we check if the\n // timings overlap and if so associate them.\n if (lastRecalcStyleEvent &&\n (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event))) {\n const recalcEndTime = lastRecalcStyleEvent.ts + (lastRecalcStyleEvent.dur || 0);\n if (event.ts >= lastRecalcStyleEvent.ts && event.ts <= recalcEndTime &&\n lastRecalcStyleEvent.args.beginData?.frame === event.args.data.frame) {\n addInvalidationToEvent(lastRecalcStyleEvent, event);\n }\n }\n\n allInvalidationTrackingEvents.push(event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventPaint(event)) {\n // Used to ensure that we do not create relationships across frames.\n hasPainted = true;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventLayout(event)) {\n const layoutFrame = event.args.beginData.frame;\n for (const invalidation of allInvalidationTrackingEvents) {\n // The only invalidations that cause a Layout are LayoutInvalidations :)\n if (!Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n continue;\n }\n\n if (invalidation.args.data.frame === layoutFrame) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InvalidationsHandler is not initialized');\n }\n\n handlerState = HandlerState.FINALIZED;\n}\n\ninterface InvalidationsData {\n invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>;\n}\n\nexport function data(): InvalidationsData {\n return {\n invalidationsForEvent,\n };\n}\n"]}
|
|
@@ -174,8 +174,10 @@ export function handleEvent(event) {
|
|
|
174
174
|
if (frame.parent) {
|
|
175
175
|
continue;
|
|
176
176
|
}
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
if (frame.url) {
|
|
178
|
+
mainFrameId = frame.frame;
|
|
179
|
+
mainFrameURL = frame.url;
|
|
180
|
+
}
|
|
179
181
|
topLevelRendererIds.add(frame.processId);
|
|
180
182
|
}
|
|
181
183
|
return;
|