@paulirish/trace_engine 0.0.22 → 0.0.23
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/generated/protocol.d.ts +12 -2
- package/models/trace/TracingManager.js.map +1 -1
- package/models/trace/handlers/AuctionWorkletsHandler.js +1 -0
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.js +18 -5
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.js +2 -1
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.js +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/ScreenshotsHandler.js +1 -0
- package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.js +1 -0
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/helpers/Extensions.js +4 -0
- package/models/trace/helpers/Extensions.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +2 -0
- package/models/trace/helpers/Trace.js +19 -1
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/TreeHelpers.d.ts +20 -0
- package/models/trace/helpers/TreeHelpers.js +50 -0
- package/models/trace/helpers/TreeHelpers.js.map +1 -1
- package/models/trace/insights/RenderBlocking.js +14 -0
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/trace-tsconfig.json +0 -1
- package/models/trace/trace.d.ts +1 -2
- package/models/trace/trace.js +1 -4
- package/models/trace/trace.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +27 -6
- package/models/trace/types/TraceEvents.js +20 -0
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
|
@@ -87,4 +87,24 @@ export declare function walkTreeFromEntry(entryToNode: Map<Types.TraceEvents.Syn
|
|
|
87
87
|
*
|
|
88
88
|
*/
|
|
89
89
|
export declare function walkEntireTree(entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>, tree: TraceEntryTree, onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void, onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void, traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds, minDuration?: Types.Timing.MicroSeconds): void;
|
|
90
|
+
/**
|
|
91
|
+
* Determines if the given events, which are assumed to be ordered can
|
|
92
|
+
* be organized into tree structures.
|
|
93
|
+
* This condition is met if there is *not* a pair of async events
|
|
94
|
+
* e1 and e2 where:
|
|
95
|
+
*
|
|
96
|
+
* e1.startTime < e2.startTime && e1.endTime > e2.startTime && e1.endTime < e2.endTime.
|
|
97
|
+
* or, graphically:
|
|
98
|
+
* |------- e1 ------|
|
|
99
|
+
* |------- e2 --------|
|
|
100
|
+
*
|
|
101
|
+
* Because a parent-child relationship cannot be made from the example
|
|
102
|
+
* above, a tree cannot be made from the set of events.
|
|
103
|
+
*
|
|
104
|
+
* Sync events from the same thread are tree-able by definition.
|
|
105
|
+
*
|
|
106
|
+
* Note that this will also return true if multiple trees can be
|
|
107
|
+
* built, for example if none of the events overlap with each other.
|
|
108
|
+
*/
|
|
109
|
+
export declare function canBuildTreesFromEvents(events: readonly Types.TraceEvents.TraceEventData[]): boolean;
|
|
90
110
|
export {};
|
|
@@ -219,4 +219,54 @@ function treeNodeIsInWindow(node, traceWindow) {
|
|
|
219
219
|
}
|
|
220
220
|
return false;
|
|
221
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Determines if the given events, which are assumed to be ordered can
|
|
224
|
+
* be organized into tree structures.
|
|
225
|
+
* This condition is met if there is *not* a pair of async events
|
|
226
|
+
* e1 and e2 where:
|
|
227
|
+
*
|
|
228
|
+
* e1.startTime < e2.startTime && e1.endTime > e2.startTime && e1.endTime < e2.endTime.
|
|
229
|
+
* or, graphically:
|
|
230
|
+
* |------- e1 ------|
|
|
231
|
+
* |------- e2 --------|
|
|
232
|
+
*
|
|
233
|
+
* Because a parent-child relationship cannot be made from the example
|
|
234
|
+
* above, a tree cannot be made from the set of events.
|
|
235
|
+
*
|
|
236
|
+
* Sync events from the same thread are tree-able by definition.
|
|
237
|
+
*
|
|
238
|
+
* Note that this will also return true if multiple trees can be
|
|
239
|
+
* built, for example if none of the events overlap with each other.
|
|
240
|
+
*/
|
|
241
|
+
export function canBuildTreesFromEvents(events) {
|
|
242
|
+
const stack = [];
|
|
243
|
+
for (const event of events) {
|
|
244
|
+
const startTime = event.ts;
|
|
245
|
+
const endTime = event.ts + (event.dur || 0);
|
|
246
|
+
let parent = stack.at(-1);
|
|
247
|
+
if (parent === undefined) {
|
|
248
|
+
stack.push(event);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
let parentEndTime = parent.ts + (parent.dur || 0);
|
|
252
|
+
// Discard events that are not parents for this event. The parent
|
|
253
|
+
// is one whose end time is after this event start time.
|
|
254
|
+
while (stack.length && startTime >= parentEndTime) {
|
|
255
|
+
stack.pop();
|
|
256
|
+
parent = stack.at(-1);
|
|
257
|
+
if (parent === undefined) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
parentEndTime = parent.ts + (parent.dur || 0);
|
|
261
|
+
}
|
|
262
|
+
if (stack.length && endTime > parentEndTime) {
|
|
263
|
+
// If such an event exists but its end time is before this
|
|
264
|
+
// event's end time, then a tree cannot be made using this
|
|
265
|
+
// events.
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
stack.push(event);
|
|
269
|
+
}
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
222
272
|
//# sourceMappingURL=TreeHelpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeHelpers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/TreeHelpers.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\nlet nodeIdCount = 0;\nexport const makeTraceEntryNodeId = (): TraceEntryNodeId => (++nodeIdCount) as TraceEntryNodeId;\n\nexport const makeEmptyTraceEntryTree = (): TraceEntryTree => ({\n roots: new Set(),\n maxDepth: 0,\n});\n\nexport const makeEmptyTraceEntryNode =\n (entry: Types.TraceEvents.SyntheticTraceEntry, id: TraceEntryNodeId): TraceEntryNode => ({\n entry,\n id,\n parent: null,\n children: [],\n depth: 0,\n });\n\nexport interface TraceEntryTree {\n roots: Set<TraceEntryNode>;\n maxDepth: number;\n}\n\nexport interface TraceEntryNode {\n entry: Types.TraceEvents.SyntheticTraceEntry;\n depth: number;\n id: TraceEntryNodeId;\n parent: TraceEntryNode|null;\n children: TraceEntryNode[];\n}\n\nclass TraceEntryNodeIdTag {\n /* eslint-disable-next-line no-unused-private-class-members */\n readonly #tag: (symbol|undefined);\n}\nexport type TraceEntryNodeId = number&TraceEntryNodeIdTag;\n\n/**\n * Builds a hierarchy of the entries (trace events and profile calls) in\n * a particular thread of a particular process, assuming that they're\n * sorted, by iterating through all of the events in order.\n *\n * The approach is analogous to how a parser would be implemented. A\n * stack maintains local context. A scanner peeks and pops from the data\n * stream. Various \"tokens\" (events) are treated as \"whitespace\"\n * (ignored).\n *\n * The tree starts out empty and is populated as the hierarchy is built.\n * The nodes are also assumed to be created empty, with no known parent\n * or children.\n *\n * Complexity: O(n), where n = number of events\n */\nexport function treify(entries: Types.TraceEvents.SyntheticTraceEntry[], options?: {\n filter: {has: (name: Types.TraceEvents.KnownEventName) => boolean},\n}): {tree: TraceEntryTree, entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>} {\n // As we construct the tree, store a map of each entry to its node. This\n // means if you are iterating over a list of RendererEntry events you can\n // easily look up that node in the tree.\n const entryToNode = new Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>();\n\n const stack = [];\n // Reset the node id counter for every new renderer.\n nodeIdCount = -1;\n const tree = makeEmptyTraceEntryTree();\n\n for (let i = 0; i < entries.length; i++) {\n const event = entries[i];\n // If the current event should not be part of the tree, then simply proceed\n // with the next event.\n if (options && !options.filter.has(event.name as Types.TraceEvents.KnownEventName)) {\n continue;\n }\n\n const duration = event.dur || 0;\n const nodeId = makeTraceEntryNodeId();\n const node = makeEmptyTraceEntryNode(event, nodeId);\n\n // If the parent stack is empty, then the current event is a root. Create a\n // node for it, mark it as a root, then proceed with the next event.\n if (stack.length === 0) {\n tree.roots.add(node);\n event.selfTime = Types.Timing.MicroSeconds(duration);\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n continue;\n }\n\n const parentNode = stack.at(-1);\n if (parentNode === undefined) {\n throw new Error('Impossible: no parent node found in the stack');\n }\n\n const parentEvent = parentNode.entry;\n\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const end = begin + duration;\n const parentEnd = parentBegin + parentDuration;\n // Check the relationship between the parent event at the top of the stack,\n // and the current event being processed. There are only 4 distinct\n // possiblities, only 2 of them actually valid, given the assumed sorting:\n // 1. Current event starts before the parent event, ends whenever. (invalid)\n // 2. Current event starts after the parent event, ends whenever. (valid)\n // 3. Current event starts during the parent event, ends after. (invalid)\n // 4. Current event starts and ends during the parent event. (valid)\n\n // 1. If the current event starts before the parent event, then the data is\n // not sorted properly, messed up some way, or this logic is incomplete.\n const startsBeforeParent = begin < parentBegin;\n if (startsBeforeParent) {\n throw new Error('Impossible: current event starts before the parent event');\n }\n\n // 2. If the current event starts after the parent event, then it's a new\n // parent. Pop, then handle current event again.\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n stack.pop();\n i--;\n // The last created node has been discarded, so discard this id.\n nodeIdCount--;\n continue;\n }\n // 3. If the current event starts during the parent event, but ends\n // after it, then the data is messed up some way, for example a\n // profile call was sampled too late after its start, ignore the\n // problematic event.\n const endsAfterParent = end > parentEnd;\n if (endsAfterParent) {\n continue;\n }\n\n // 4. The only remaining case is the common case, where the current event is\n // contained within the parent event. Create a node for the current\n // event, establish the parent/child relationship, then proceed with the\n // next event.\n node.depth = stack.length;\n node.parent = parentNode;\n parentNode.children.push(node);\n event.selfTime = Types.Timing.MicroSeconds(duration);\n if (parentEvent.selfTime !== undefined) {\n parentEvent.selfTime = Types.Timing.MicroSeconds(parentEvent.selfTime - (event.dur || 0));\n }\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n }\n return {tree, entryToNode};\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n */\nexport function walkTreeFromEntry(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n rootEntry: Types.TraceEvents.SyntheticTraceEntry,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n ): void {\n const startNode = entryToNode.get(rootEntry);\n if (!startNode) {\n return;\n }\n walkTreeByNode(entryToNode, startNode, onEntryStart, onEntryEnd);\n}\n\n/**\n * Given a Helpers.TreeHelpers.RendererTree, this will iterates events in hierarchically, visiting\n * each root node and working from top to bottom, calling back on every event's\n * start and end in the order as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n * 10. Start E\n * 11. End E\n *\n */\n\nexport function walkEntireTree(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n tree: TraceEntryTree,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n for (const rootNode of tree.roots) {\n walkTreeByNode(entryToNode, rootNode, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n}\n\nfunction walkTreeByNode(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n rootNode: TraceEntryNode,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n if (traceWindowToInclude && !treeNodeIsInWindow(rootNode, traceWindowToInclude)) {\n // If this node is not within the provided window, we can skip it. We also\n // can skip all its children too, as we know they won't be in the window if\n // their parent is not.\n return;\n }\n\n if (typeof minDuration !== 'undefined') {\n const duration = Types.Timing.MicroSeconds(\n rootNode.entry.ts + Types.Timing.MicroSeconds(rootNode.entry.dur || 0),\n );\n if (duration < minDuration) {\n return;\n }\n }\n\n onEntryStart(rootNode.entry);\n for (const child of rootNode.children) {\n walkTreeByNode(entryToNode, child, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n onEntryEnd(rootNode.entry);\n}\n\n/**\n * Returns true if the provided node is partially or fully within the trace\n * window. The entire node does not have to fit inside the window, but it does\n * have to partially intersect it.\n */\nfunction treeNodeIsInWindow(node: TraceEntryNode, traceWindow: Types.Timing.TraceWindowMicroSeconds): boolean {\n const startTime = node.entry.ts;\n const endTime = node.entry.ts + (node.entry.dur || 0);\n\n // Min ======= startTime ========= Max => node is within window\n if (startTime >= traceWindow.min && startTime < traceWindow.max) {\n return true;\n }\n\n // Min ======= endTime ========= Max => node is within window\n if (endTime > traceWindow.min && endTime <= traceWindow.max) {\n return true;\n }\n\n // startTime ==== Min ======== Max === endTime => node spans greater than the window so is in it.\n if (startTime <= traceWindow.min && endTime >= traceWindow.max) {\n return true;\n }\n\n return false;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TreeHelpers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/TreeHelpers.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\nlet nodeIdCount = 0;\nexport const makeTraceEntryNodeId = (): TraceEntryNodeId => (++nodeIdCount) as TraceEntryNodeId;\n\nexport const makeEmptyTraceEntryTree = (): TraceEntryTree => ({\n roots: new Set(),\n maxDepth: 0,\n});\n\nexport const makeEmptyTraceEntryNode =\n (entry: Types.TraceEvents.SyntheticTraceEntry, id: TraceEntryNodeId): TraceEntryNode => ({\n entry,\n id,\n parent: null,\n children: [],\n depth: 0,\n });\n\nexport interface TraceEntryTree {\n roots: Set<TraceEntryNode>;\n maxDepth: number;\n}\n\nexport interface TraceEntryNode {\n entry: Types.TraceEvents.SyntheticTraceEntry;\n depth: number;\n id: TraceEntryNodeId;\n parent: TraceEntryNode|null;\n children: TraceEntryNode[];\n}\n\nclass TraceEntryNodeIdTag {\n /* eslint-disable-next-line no-unused-private-class-members */\n readonly #tag: (symbol|undefined);\n}\nexport type TraceEntryNodeId = number&TraceEntryNodeIdTag;\n\n/**\n * Builds a hierarchy of the entries (trace events and profile calls) in\n * a particular thread of a particular process, assuming that they're\n * sorted, by iterating through all of the events in order.\n *\n * The approach is analogous to how a parser would be implemented. A\n * stack maintains local context. A scanner peeks and pops from the data\n * stream. Various \"tokens\" (events) are treated as \"whitespace\"\n * (ignored).\n *\n * The tree starts out empty and is populated as the hierarchy is built.\n * The nodes are also assumed to be created empty, with no known parent\n * or children.\n *\n * Complexity: O(n), where n = number of events\n */\nexport function treify(entries: Types.TraceEvents.SyntheticTraceEntry[], options?: {\n filter: {has: (name: Types.TraceEvents.KnownEventName) => boolean},\n}): {tree: TraceEntryTree, entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>} {\n // As we construct the tree, store a map of each entry to its node. This\n // means if you are iterating over a list of RendererEntry events you can\n // easily look up that node in the tree.\n const entryToNode = new Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>();\n\n const stack = [];\n // Reset the node id counter for every new renderer.\n nodeIdCount = -1;\n const tree = makeEmptyTraceEntryTree();\n\n for (let i = 0; i < entries.length; i++) {\n const event = entries[i];\n // If the current event should not be part of the tree, then simply proceed\n // with the next event.\n if (options && !options.filter.has(event.name as Types.TraceEvents.KnownEventName)) {\n continue;\n }\n\n const duration = event.dur || 0;\n const nodeId = makeTraceEntryNodeId();\n const node = makeEmptyTraceEntryNode(event, nodeId);\n\n // If the parent stack is empty, then the current event is a root. Create a\n // node for it, mark it as a root, then proceed with the next event.\n if (stack.length === 0) {\n tree.roots.add(node);\n event.selfTime = Types.Timing.MicroSeconds(duration);\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n continue;\n }\n\n const parentNode = stack.at(-1);\n if (parentNode === undefined) {\n throw new Error('Impossible: no parent node found in the stack');\n }\n\n const parentEvent = parentNode.entry;\n\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const end = begin + duration;\n const parentEnd = parentBegin + parentDuration;\n // Check the relationship between the parent event at the top of the stack,\n // and the current event being processed. There are only 4 distinct\n // possiblities, only 2 of them actually valid, given the assumed sorting:\n // 1. Current event starts before the parent event, ends whenever. (invalid)\n // 2. Current event starts after the parent event, ends whenever. (valid)\n // 3. Current event starts during the parent event, ends after. (invalid)\n // 4. Current event starts and ends during the parent event. (valid)\n\n // 1. If the current event starts before the parent event, then the data is\n // not sorted properly, messed up some way, or this logic is incomplete.\n const startsBeforeParent = begin < parentBegin;\n if (startsBeforeParent) {\n throw new Error('Impossible: current event starts before the parent event');\n }\n\n // 2. If the current event starts after the parent event, then it's a new\n // parent. Pop, then handle current event again.\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n stack.pop();\n i--;\n // The last created node has been discarded, so discard this id.\n nodeIdCount--;\n continue;\n }\n // 3. If the current event starts during the parent event, but ends\n // after it, then the data is messed up some way, for example a\n // profile call was sampled too late after its start, ignore the\n // problematic event.\n const endsAfterParent = end > parentEnd;\n if (endsAfterParent) {\n continue;\n }\n\n // 4. The only remaining case is the common case, where the current event is\n // contained within the parent event. Create a node for the current\n // event, establish the parent/child relationship, then proceed with the\n // next event.\n node.depth = stack.length;\n node.parent = parentNode;\n parentNode.children.push(node);\n event.selfTime = Types.Timing.MicroSeconds(duration);\n if (parentEvent.selfTime !== undefined) {\n parentEvent.selfTime = Types.Timing.MicroSeconds(parentEvent.selfTime - (event.dur || 0));\n }\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n }\n return {tree, entryToNode};\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n */\nexport function walkTreeFromEntry(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n rootEntry: Types.TraceEvents.SyntheticTraceEntry,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n ): void {\n const startNode = entryToNode.get(rootEntry);\n if (!startNode) {\n return;\n }\n walkTreeByNode(entryToNode, startNode, onEntryStart, onEntryEnd);\n}\n\n/**\n * Given a Helpers.TreeHelpers.RendererTree, this will iterates events in hierarchically, visiting\n * each root node and working from top to bottom, calling back on every event's\n * start and end in the order as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n * 10. Start E\n * 11. End E\n *\n */\n\nexport function walkEntireTree(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n tree: TraceEntryTree,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n for (const rootNode of tree.roots) {\n walkTreeByNode(entryToNode, rootNode, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n}\n\nfunction walkTreeByNode(\n entryToNode: Map<Types.TraceEvents.SyntheticTraceEntry, TraceEntryNode>,\n rootNode: TraceEntryNode,\n onEntryStart: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n onEntryEnd: (entry: Types.TraceEvents.SyntheticTraceEntry) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n if (traceWindowToInclude && !treeNodeIsInWindow(rootNode, traceWindowToInclude)) {\n // If this node is not within the provided window, we can skip it. We also\n // can skip all its children too, as we know they won't be in the window if\n // their parent is not.\n return;\n }\n\n if (typeof minDuration !== 'undefined') {\n const duration = Types.Timing.MicroSeconds(\n rootNode.entry.ts + Types.Timing.MicroSeconds(rootNode.entry.dur || 0),\n );\n if (duration < minDuration) {\n return;\n }\n }\n\n onEntryStart(rootNode.entry);\n for (const child of rootNode.children) {\n walkTreeByNode(entryToNode, child, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n onEntryEnd(rootNode.entry);\n}\n\n/**\n * Returns true if the provided node is partially or fully within the trace\n * window. The entire node does not have to fit inside the window, but it does\n * have to partially intersect it.\n */\nfunction treeNodeIsInWindow(node: TraceEntryNode, traceWindow: Types.Timing.TraceWindowMicroSeconds): boolean {\n const startTime = node.entry.ts;\n const endTime = node.entry.ts + (node.entry.dur || 0);\n\n // Min ======= startTime ========= Max => node is within window\n if (startTime >= traceWindow.min && startTime < traceWindow.max) {\n return true;\n }\n\n // Min ======= endTime ========= Max => node is within window\n if (endTime > traceWindow.min && endTime <= traceWindow.max) {\n return true;\n }\n\n // startTime ==== Min ======== Max === endTime => node spans greater than the window so is in it.\n if (startTime <= traceWindow.min && endTime >= traceWindow.max) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Determines if the given events, which are assumed to be ordered can\n * be organized into tree structures.\n * This condition is met if there is *not* a pair of async events\n * e1 and e2 where:\n *\n * e1.startTime < e2.startTime && e1.endTime > e2.startTime && e1.endTime < e2.endTime.\n * or, graphically:\n * |------- e1 ------|\n * |------- e2 --------|\n *\n * Because a parent-child relationship cannot be made from the example\n * above, a tree cannot be made from the set of events.\n *\n * Sync events from the same thread are tree-able by definition.\n *\n * Note that this will also return true if multiple trees can be\n * built, for example if none of the events overlap with each other.\n */\nexport function canBuildTreesFromEvents(events: readonly Types.TraceEvents.TraceEventData[]): boolean {\n const stack: Types.TraceEvents.TraceEventData[] = [];\n for (const event of events) {\n const startTime = event.ts;\n const endTime = event.ts + (event.dur || 0);\n let parent = stack.at(-1);\n if (parent === undefined) {\n stack.push(event);\n continue;\n }\n let parentEndTime = parent.ts + (parent.dur || 0);\n // Discard events that are not parents for this event. The parent\n // is one whose end time is after this event start time.\n while (stack.length && startTime >= parentEndTime) {\n stack.pop();\n parent = stack.at(-1);\n\n if (parent === undefined) {\n break;\n }\n parentEndTime = parent.ts + (parent.dur || 0);\n }\n if (stack.length && endTime > parentEndTime) {\n // If such an event exists but its end time is before this\n // event's end time, then a tree cannot be made using this\n // events.\n return false;\n }\n stack.push(event);\n }\n return true;\n}\n"]}
|
|
@@ -29,6 +29,20 @@ export function generateInsight(traceParsedData, context) {
|
|
|
29
29
|
if (req.args.data.syntheticData.finishTime > firstPaintTs) {
|
|
30
30
|
continue;
|
|
31
31
|
}
|
|
32
|
+
// If a resource is marked `in_body_parser_blocking` it should only be considered render blocking if it is a
|
|
33
|
+
// high enough priority. Some resources (e.g. scripts) are not marked as high priority if they are fetched
|
|
34
|
+
// after a non-preloaded image. (See "early" definition in https://web.dev/articles/fetch-priority)
|
|
35
|
+
//
|
|
36
|
+
// There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation
|
|
37
|
+
// of render blocking resources in the document body.
|
|
38
|
+
if (req.args.data.renderBlocking === 'in_body_parser_blocking') {
|
|
39
|
+
const priority = req.args.data.priority;
|
|
40
|
+
const isScript = req.args.data.resourceType === "Script" /* Protocol.Network.ResourceType.Script */;
|
|
41
|
+
const isBlockingScript = isScript && priority === "High" /* Protocol.Network.ResourcePriority.High */;
|
|
42
|
+
if (priority !== "VeryHigh" /* Protocol.Network.ResourcePriority.VeryHigh */ && !isBlockingScript) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
32
46
|
const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);
|
|
33
47
|
if (navigation?.args.data?.navigationId !== context.navigationId) {
|
|
34
48
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;
|
|
1
|
+
{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAqB,cAAc,EAAmD,MAAM,YAAY,CAAC;AAEhH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,eAA0C,EAAE,OAAiC;IAE3G,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QACtE,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;QAC3B,EAAE,GAAG,iEAAsD;QAC3D,EAAE,KAAK,EAAE,EAAE,CAAC;IACrC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL,sBAAsB,EAAE,EAAE;YAC1B,QAAQ,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,sBAAsB,GAAG,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,yBAAyB,EAAE,CAAC;YAC9G,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,GAAG,YAAY,EAAE,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,4GAA4G;QAC5G,0GAA0G;QAC1G,mGAAmG;QACnG,EAAE;QACF,qGAAqG;QACrG,qDAAqD;QACrD,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,yBAAyB,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,wDAAyC,CAAC;YACrF,MAAM,gBAAgB,GAAG,QAAQ,IAAI,QAAQ,wDAA2C,CAAC;YACzF,IAAI,QAAQ,gEAA+C,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACjF,SAAS;YACX,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9G,IAAI,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACjE,SAAS;QACX,CAAC;QAED,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACL,sBAAsB;KACvB,CAAC;AACJ,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 Protocol from '../../../generated/protocol.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics'] {\n return ['NetworkRequests', 'PageLoadMetrics'];\n}\n\nexport function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext):\n InsightResult<{renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[]}> {\n const firstPaintTs = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)\n ?.get(context.navigationId)\n ?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)\n ?.event?.ts;\n if (!firstPaintTs) {\n return {\n renderBlockingRequests: [],\n warnings: [InsightWarning.NO_FP],\n };\n }\n\n const renderBlockingRequests = [];\n for (const req of traceParsedData.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n if (req.args.data.renderBlocking !== 'blocking' && req.args.data.renderBlocking !== 'in_body_parser_blocking') {\n continue;\n }\n\n if (req.args.data.syntheticData.finishTime > firstPaintTs) {\n continue;\n }\n\n // If a resource is marked `in_body_parser_blocking` it should only be considered render blocking if it is a\n // high enough priority. Some resources (e.g. scripts) are not marked as high priority if they are fetched\n // after a non-preloaded image. (See \"early\" definition in https://web.dev/articles/fetch-priority)\n //\n // There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation\n // of render blocking resources in the document body.\n if (req.args.data.renderBlocking === 'in_body_parser_blocking') {\n const priority = req.args.data.priority;\n const isScript = req.args.data.resourceType === Protocol.Network.ResourceType.Script;\n const isBlockingScript = isScript && priority === Protocol.Network.ResourcePriority.High;\n if (priority !== Protocol.Network.ResourcePriority.VeryHigh && !isBlockingScript) {\n continue;\n }\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n if (navigation?.args.data?.navigationId !== context.navigationId) {\n continue;\n }\n\n renderBlockingRequests.push(req);\n }\n\n return {\n renderBlockingRequests,\n };\n}\n"]}
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"../../../../../../front_end/models/trace/EntriesFilter.ts",
|
|
33
|
-
"../../../../../../front_end/models/trace/LegacyTracingModel.ts",
|
|
34
33
|
"../../../../../../front_end/models/trace/ModelImpl.ts",
|
|
35
34
|
"../../../../../../front_end/models/trace/Processor.ts",
|
|
36
35
|
"../../../../../../front_end/models/trace/TracingManager.ts",
|
package/models/trace/trace.d.ts
CHANGED
|
@@ -3,10 +3,9 @@ import * as Extras from './extras/extras.js';
|
|
|
3
3
|
import * as Handlers from './handlers/handlers.js';
|
|
4
4
|
import * as Helpers from './helpers/helpers.js';
|
|
5
5
|
import * as Insights from './insights/insights.js';
|
|
6
|
-
import * as Legacy from './LegacyTracingModel.js';
|
|
7
6
|
import * as TraceModel from './ModelImpl.js';
|
|
8
7
|
import * as Processor from './Processor.js';
|
|
9
8
|
import * as RootCauses from './root-causes/root-causes.js';
|
|
10
9
|
import * as TracingManager from './TracingManager.js';
|
|
11
10
|
import * as Types from './types/types.js';
|
|
12
|
-
export { EntriesFilter, Extras, Handlers, Helpers, Insights,
|
|
11
|
+
export { EntriesFilter, Extras, Handlers, Helpers, Insights, Processor, RootCauses, TraceModel, TracingManager, Types, };
|
package/models/trace/trace.js
CHANGED
|
@@ -6,13 +6,10 @@ import * as Extras from './extras/extras.js';
|
|
|
6
6
|
import * as Handlers from './handlers/handlers.js';
|
|
7
7
|
import * as Helpers from './helpers/helpers.js';
|
|
8
8
|
import * as Insights from './insights/insights.js';
|
|
9
|
-
// Purposefully use a shorter name here so references to this are
|
|
10
|
-
// Legacy.TracingModel.
|
|
11
|
-
import * as Legacy from './LegacyTracingModel.js';
|
|
12
9
|
import * as TraceModel from './ModelImpl.js';
|
|
13
10
|
import * as Processor from './Processor.js';
|
|
14
11
|
import * as RootCauses from './root-causes/root-causes.js';
|
|
15
12
|
import * as TracingManager from './TracingManager.js';
|
|
16
13
|
import * as Types from './types/types.js';
|
|
17
|
-
export { EntriesFilter, Extras, Handlers, Helpers, Insights,
|
|
14
|
+
export { EntriesFilter, Extras, Handlers, Helpers, Insights, Processor, RootCauses, TraceModel, TracingManager, Types, };
|
|
18
15
|
//# sourceMappingURL=trace.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/trace.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,
|
|
1
|
+
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/trace.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EACL,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,EACd,KAAK,GACN,CAAC","sourcesContent":["// Copyright 2022 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 EntriesFilter from './EntriesFilter.js';\nimport * as Extras from './extras/extras.js';\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as TraceModel from './ModelImpl.js';\nimport * as Processor from './Processor.js';\nimport * as RootCauses from './root-causes/root-causes.js';\nimport * as TracingManager from './TracingManager.js';\nimport * as Types from './types/types.js';\n\nexport {\n EntriesFilter,\n Extras,\n Handlers,\n Helpers,\n Insights,\n Processor,\n RootCauses,\n TraceModel,\n TracingManager,\n Types,\n};\n"]}
|
|
@@ -63,6 +63,7 @@ export interface TraceEventCallFrame {
|
|
|
63
63
|
lineNumber: number;
|
|
64
64
|
url: string;
|
|
65
65
|
}
|
|
66
|
+
export declare function objectIsTraceEventCallFrame(object: {}): object is TraceEventCallFrame;
|
|
66
67
|
export interface TraceFrame {
|
|
67
68
|
frame: string;
|
|
68
69
|
name: string;
|
|
@@ -78,7 +79,7 @@ export interface TraceEventSample extends TraceEventData {
|
|
|
78
79
|
* A fake trace event created to support CDP.Profiler.Profiles in the
|
|
79
80
|
* trace engine.
|
|
80
81
|
*/
|
|
81
|
-
export interface SyntheticCpuProfile extends TraceEventInstant {
|
|
82
|
+
export interface SyntheticCpuProfile extends TraceEventInstant, SyntheticEvent<Phase.INSTANT> {
|
|
82
83
|
name: 'CpuProfile';
|
|
83
84
|
args: TraceEventArgs & {
|
|
84
85
|
data: TraceEventArgsData & {
|
|
@@ -119,6 +120,10 @@ export interface TraceEventComplete extends TraceEventData {
|
|
|
119
120
|
ph: Phase.COMPLETE;
|
|
120
121
|
dur: MicroSeconds;
|
|
121
122
|
}
|
|
123
|
+
export interface TraceEventRunTask extends TraceEventComplete {
|
|
124
|
+
name: KnownEventName.RunTask;
|
|
125
|
+
}
|
|
126
|
+
export declare function isTraceEventRunTask(event: TraceEventData): event is TraceEventRunTask;
|
|
122
127
|
export interface TraceEventFireIdleCallback extends TraceEventComplete {
|
|
123
128
|
name: KnownEventName.FireIdleCallback;
|
|
124
129
|
args: TraceEventArgs & {
|
|
@@ -242,7 +247,8 @@ interface SyntheticArgsData {
|
|
|
242
247
|
totalTime: MicroSeconds;
|
|
243
248
|
waiting: MicroSeconds;
|
|
244
249
|
}
|
|
245
|
-
export interface SyntheticNetworkRequest extends TraceEventComplete {
|
|
250
|
+
export interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticEvent<Phase.COMPLETE> {
|
|
251
|
+
rawSourceEvent: TraceEventData;
|
|
246
252
|
args: TraceEventArgs & {
|
|
247
253
|
data: TraceEventArgsData & {
|
|
248
254
|
syntheticData: SyntheticArgsData;
|
|
@@ -300,7 +306,8 @@ export declare const enum AuctionWorkletType {
|
|
|
300
306
|
SELLER = "seller",
|
|
301
307
|
UNKNOWN = "unknown"
|
|
302
308
|
}
|
|
303
|
-
export interface SyntheticAuctionWorkletEvent extends TraceEventInstant {
|
|
309
|
+
export interface SyntheticAuctionWorkletEvent extends TraceEventInstant, SyntheticEvent<Phase.INSTANT> {
|
|
310
|
+
rawSourceEvent: TraceEventData;
|
|
304
311
|
name: 'SyntheticAuctionWorkletEvent';
|
|
305
312
|
pid: ProcessID;
|
|
306
313
|
host: string;
|
|
@@ -363,7 +370,8 @@ export interface TraceEventScreenshot extends TraceEventData {
|
|
|
363
370
|
ph: Phase.OBJECT_SNAPSHOT;
|
|
364
371
|
}
|
|
365
372
|
export declare function isTraceEventScreenshot(event: TraceEventData): event is TraceEventScreenshot;
|
|
366
|
-
export interface SyntheticScreenshot extends TraceEventData {
|
|
373
|
+
export interface SyntheticScreenshot extends TraceEventData, SyntheticEvent {
|
|
374
|
+
rawSourceEvent: TraceEventScreenshot;
|
|
367
375
|
/** This is the correct presentation timestamp. */
|
|
368
376
|
ts: MicroSeconds;
|
|
369
377
|
args: TraceEventArgs & {
|
|
@@ -620,7 +628,9 @@ export interface LayoutShiftParsedData {
|
|
|
620
628
|
cumulativeWeightedScoreInWindow: number;
|
|
621
629
|
sessionWindowData: LayoutShiftSessionWindowData;
|
|
622
630
|
}
|
|
623
|
-
export interface SyntheticLayoutShift extends TraceEventLayoutShift {
|
|
631
|
+
export interface SyntheticLayoutShift extends TraceEventLayoutShift, SyntheticEvent<Phase.INSTANT> {
|
|
632
|
+
name: 'LayoutShift';
|
|
633
|
+
rawSourceEvent: TraceEventLayoutShift;
|
|
624
634
|
args: TraceEventArgs & {
|
|
625
635
|
frame: string;
|
|
626
636
|
data?: LayoutShiftData & {
|
|
@@ -994,7 +1004,13 @@ export interface TraceEventPipelineReporter extends TraceEventData {
|
|
|
994
1004
|
};
|
|
995
1005
|
}
|
|
996
1006
|
export declare function isTraceEventPipelineReporter(event: TraceEventData): event is TraceEventPipelineReporter;
|
|
997
|
-
|
|
1007
|
+
interface SyntheticEvent<Ph extends Phase = Phase> extends TraceEventData {
|
|
1008
|
+
ph: Ph;
|
|
1009
|
+
rawSourceEvent: TraceEventData;
|
|
1010
|
+
}
|
|
1011
|
+
export declare function isSyntheticEvent(event: TraceEventData): event is SyntheticEvent;
|
|
1012
|
+
export interface SyntheticEventPair<T extends TraceEventPairableAsync = TraceEventPairableAsync> extends SyntheticEvent {
|
|
1013
|
+
rawSourceEvent: TraceEventData;
|
|
998
1014
|
name: T['name'];
|
|
999
1015
|
cat: T['cat'];
|
|
1000
1016
|
id?: string;
|
|
@@ -1757,4 +1773,9 @@ export declare const enum KnownEventName {
|
|
|
1757
1773
|
SchedulePostMessage = "SchedulePostMessage",
|
|
1758
1774
|
HandlePostMessage = "HandlePostMessage"
|
|
1759
1775
|
}
|
|
1776
|
+
export declare const Categories: {
|
|
1777
|
+
readonly Console: "blink.console";
|
|
1778
|
+
readonly UserTiming: "blink.user_timing";
|
|
1779
|
+
readonly Loading: "loading";
|
|
1780
|
+
};
|
|
1760
1781
|
export {};
|
|
@@ -12,6 +12,16 @@ export function isAsyncPhase(phase) {
|
|
|
12
12
|
export function isFlowPhase(phase) {
|
|
13
13
|
return phase === "s" /* Phase.FLOW_START */ || phase === "t" /* Phase.FLOW_STEP */ || phase === "f" /* Phase.FLOW_END */;
|
|
14
14
|
}
|
|
15
|
+
export function objectIsTraceEventCallFrame(object) {
|
|
16
|
+
return ('functionName' in object && typeof object.functionName === 'string') &&
|
|
17
|
+
('scriptId' in object && (typeof object.scriptId === 'string' || typeof object.scriptId === 'number')) &&
|
|
18
|
+
('columnNumber' in object && typeof object.columnNumber === 'number') &&
|
|
19
|
+
('lineNumber' in object && typeof object.lineNumber === 'number') &&
|
|
20
|
+
('url' in object && typeof object.url === 'string');
|
|
21
|
+
}
|
|
22
|
+
export function isTraceEventRunTask(event) {
|
|
23
|
+
return event.name === "RunTask" /* KnownEventName.RunTask */;
|
|
24
|
+
}
|
|
15
25
|
export function isTraceEventAuctionWorkletRunningInProcess(event) {
|
|
16
26
|
return event.name === 'AuctionWorkletRunningInProcess';
|
|
17
27
|
}
|
|
@@ -61,6 +71,9 @@ export function isTraceEventScheduleStyleRecalculation(event) {
|
|
|
61
71
|
export function isTraceEventPipelineReporter(event) {
|
|
62
72
|
return event.name === "PipelineReporter" /* KnownEventName.PipelineReporter */;
|
|
63
73
|
}
|
|
74
|
+
export function isSyntheticEvent(event) {
|
|
75
|
+
return 'rawSourceEvent' in event;
|
|
76
|
+
}
|
|
64
77
|
export function isSyntheticInteractionEvent(event) {
|
|
65
78
|
return Boolean('interactionId' in event && event.args?.data && 'beginEvent' in event.args.data && 'endEvent' in event.args.data);
|
|
66
79
|
}
|
|
@@ -435,4 +448,11 @@ export function isJSInvocationEvent(event) {
|
|
|
435
448
|
}
|
|
436
449
|
return false;
|
|
437
450
|
}
|
|
451
|
+
// NOT AN EXHAUSTIVE LIST: just some categories we use and refer
|
|
452
|
+
// to in multiple places.
|
|
453
|
+
export const Categories = {
|
|
454
|
+
Console: 'blink.console',
|
|
455
|
+
UserTiming: 'blink.user_timing',
|
|
456
|
+
Loading: 'loading',
|
|
457
|
+
};
|
|
438
458
|
//# sourceMappingURL=TraceEvents.js.map
|