@paulirish/trace_engine 0.0.23 → 0.0.24
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 +48 -2
- package/models/trace/EntriesFilter.d.ts +14 -13
- package/models/trace/EntriesFilter.js +40 -38
- package/models/trace/EntriesFilter.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +6 -4
- package/models/trace/ModelImpl.js +13 -4
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.js +6 -1
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/extras/FetchNodes.js +1 -1
- package/models/trace/extras/FetchNodes.js.map +1 -1
- package/models/trace/extras/URLForEntry.d.ts +4 -0
- package/models/trace/extras/URLForEntry.js +35 -0
- package/models/trace/extras/URLForEntry.js.map +1 -0
- package/models/trace/extras/extras-tsconfig.json +1 -0
- package/models/trace/extras/extras.js.map +1 -1
- package/models/trace/handlers/AuctionWorkletsHandler.js +4 -2
- package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
- package/models/trace/handlers/InitiatorsHandler.js +1 -12
- package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.js +10 -2
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.js +4 -3
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/RendererHandler.d.ts +1 -0
- package/models/trace/handlers/RendererHandler.js +2 -0
- package/models/trace/handlers/RendererHandler.js.map +1 -1
- package/models/trace/handlers/ScreenshotsHandler.js +3 -2
- package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.js +3 -2
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/helpers/SyntheticEvents.d.ts +30 -0
- package/models/trace/helpers/SyntheticEvents.js +87 -0
- package/models/trace/helpers/SyntheticEvents.js.map +1 -0
- package/models/trace/helpers/Trace.js +4 -2
- 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/insights/CumulativeLayoutShift.d.ts +7 -2
- package/models/trace/insights/CumulativeLayoutShift.js +130 -2
- package/models/trace/insights/CumulativeLayoutShift.js.map +1 -1
- package/models/trace/types/File.d.ts +11 -6
- package/models/trace/types/File.js +0 -3
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +85 -12
- package/models/trace/types/TraceEvents.js +27 -3
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
|
@@ -140,7 +140,12 @@ export class TraceProcessor extends EventTarget {
|
|
|
140
140
|
}
|
|
141
141
|
// Finalize.
|
|
142
142
|
for (const handler of sortedHandlers) {
|
|
143
|
-
|
|
143
|
+
if (handler.finalize) {
|
|
144
|
+
// Yield to the UI because finalize() calls can be expensive
|
|
145
|
+
// TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`
|
|
146
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
147
|
+
await handler.finalize();
|
|
148
|
+
}
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
get traceParsedData() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.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.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor<EnabledModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler}> extends\n EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Handlers.Types.HandlersWithMeta<EnabledModelHandlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null = null;\n #insights: Insights.Types.TraceInsightData<EnabledModelHandlers>|null = null;\n\n static createWithAllHandlers(): TraceProcessor<typeof Handlers.ModelHandlers> {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n constructor(traceHandlers: EnabledModelHandlers, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: EnabledModelHandlers): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n for (const depName of (handler.deps?.() || [])) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#parse(traceEvents, freshRecording);\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n async #parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean): Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n this.dispatchEvent(new TraceParseProgressEvent({index: i, total: traceEvents.length}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n await handler.finalize?.();\n }\n }\n\n get traceParsedData(): Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n if (this.#data) {\n return this.#data;\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const traceParsedData = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(traceParsedData, {[name]: data});\n }\n\n this.#data = traceParsedData as Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>;\n return this.#data;\n }\n\n #getEnabledInsightRunners(traceParsedData: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>):\n Insights.Types.EnabledInsightRunners<EnabledModelHandlers> {\n const enabledInsights = {} as Insights.Types.EnabledInsightRunners<EnabledModelHandlers>;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !traceParsedData[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight.generateInsight});\n }\n return enabledInsights;\n }\n\n get insights(): Insights.Types.TraceInsightData<EnabledModelHandlers>|null {\n if (!this.traceParsedData) {\n return null;\n }\n\n if (this.#insights) {\n return this.#insights;\n }\n\n this.#insights = new Map();\n\n const enabledInsightRunners = this.#getEnabledInsightRunners(this.traceParsedData);\n\n for (const nav of this.traceParsedData.Meta.mainFrameNavigations) {\n if (!nav.args.frame || !nav.args.data?.navigationId) {\n continue;\n }\n\n const context = {\n frameId: nav.args.frame,\n navigationId: nav.args.data.navigationId,\n };\n\n const navInsightData = {} as Insights.Types.NavigationInsightData<EnabledModelHandlers>;\n for (const [name, generateInsight] of Object.entries(enabledInsightRunners)) {\n let insightResult;\n try {\n insightResult = generateInsight(this.traceParsedData, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(navInsightData, {[name]: insightResult});\n }\n\n this.#insights.set(context.navigationId, navInsightData);\n }\n\n return this.#insights;\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.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.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor<EnabledModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler}> extends\n EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Handlers.Types.HandlersWithMeta<EnabledModelHandlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null = null;\n #insights: Insights.Types.TraceInsightData<EnabledModelHandlers>|null = null;\n\n static createWithAllHandlers(): TraceProcessor<typeof Handlers.ModelHandlers> {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n constructor(traceHandlers: EnabledModelHandlers, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: EnabledModelHandlers): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n for (const depName of (handler.deps?.() || [])) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#parse(traceEvents, freshRecording);\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n async #parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean): Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n this.dispatchEvent(new TraceParseProgressEvent({index: i, total: traceEvents.length}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n if (handler.finalize) {\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize();\n }\n }\n }\n\n get traceParsedData(): Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n if (this.#data) {\n return this.#data;\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const traceParsedData = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(traceParsedData, {[name]: data});\n }\n\n this.#data = traceParsedData as Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>;\n return this.#data;\n }\n\n #getEnabledInsightRunners(traceParsedData: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>):\n Insights.Types.EnabledInsightRunners<EnabledModelHandlers> {\n const enabledInsights = {} as Insights.Types.EnabledInsightRunners<EnabledModelHandlers>;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !traceParsedData[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight.generateInsight});\n }\n return enabledInsights;\n }\n\n get insights(): Insights.Types.TraceInsightData<EnabledModelHandlers>|null {\n if (!this.traceParsedData) {\n return null;\n }\n\n if (this.#insights) {\n return this.#insights;\n }\n\n this.#insights = new Map();\n\n const enabledInsightRunners = this.#getEnabledInsightRunners(this.traceParsedData);\n\n for (const nav of this.traceParsedData.Meta.mainFrameNavigations) {\n if (!nav.args.frame || !nav.args.data?.navigationId) {\n continue;\n }\n\n const context = {\n frameId: nav.args.frame,\n navigationId: nav.args.data.navigationId,\n };\n\n const navInsightData = {} as Insights.Types.NavigationInsightData<EnabledModelHandlers>;\n for (const [name, generateInsight] of Object.entries(enabledInsightRunners)) {\n let insightResult;\n try {\n insightResult = generateInsight(this.traceParsedData, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(navInsightData, {[name]: insightResult});\n }\n\n this.#insights.set(context.navigationId, navInsightData);\n }\n\n return this.#insights;\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
@@ -48,7 +48,7 @@ export function nodeIdsForEvent(modelData, event) {
|
|
|
48
48
|
}
|
|
49
49
|
const foundIds = new Set();
|
|
50
50
|
if (Types.TraceEvents.isTraceEventLayout(event)) {
|
|
51
|
-
event.args.endData
|
|
51
|
+
event.args.endData?.layoutRoots.forEach(root => foundIds.add(root.nodeId));
|
|
52
52
|
}
|
|
53
53
|
else if (Types.TraceEvents.isSyntheticLayoutShift(event) && event.args.data?.impacted_nodes) {
|
|
54
54
|
event.args.data.impacted_nodes.forEach(node => foundIds.add(node.node_id));
|
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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\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,4 @@
|
|
|
1
|
+
import type * as Platform from '../../../core/platform/platform.js';
|
|
2
|
+
import type * as Handlers from '../handlers/handlers.js';
|
|
3
|
+
import * as Types from '../types/types.js';
|
|
4
|
+
export declare function get(traceParsedData: Handlers.Types.TraceParseData, entry: Types.TraceEvents.TraceEventData): Platform.DevToolsPath.UrlString | null;
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
export function get(traceParsedData, entry) {
|
|
6
|
+
if (Types.TraceEvents.isProfileCall(entry)) {
|
|
7
|
+
return entry.callFrame.url;
|
|
8
|
+
}
|
|
9
|
+
if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {
|
|
10
|
+
return entry.args.data.stackTrace[0].url;
|
|
11
|
+
}
|
|
12
|
+
if (Types.TraceEvents.isSyntheticNetworkRequestDetailsEvent(entry)) {
|
|
13
|
+
return entry.args.data.url;
|
|
14
|
+
}
|
|
15
|
+
// DecodeImage events use the URL from the relevant PaintImage event.
|
|
16
|
+
if (Types.TraceEvents.isTraceEventDecodeImage(entry)) {
|
|
17
|
+
const paintEvent = traceParsedData.ImagePainting.paintImageForEvent.get(entry);
|
|
18
|
+
return paintEvent ? get(traceParsedData, paintEvent) : null;
|
|
19
|
+
}
|
|
20
|
+
// DrawLazyPixelRef events use the URL from the relevant PaintImage event.
|
|
21
|
+
if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(entry) && entry.args?.LazyPixelRef) {
|
|
22
|
+
const paintEvent = traceParsedData.ImagePainting.paintImageByDrawLazyPixelRef.get(entry.args.LazyPixelRef);
|
|
23
|
+
return paintEvent ? get(traceParsedData, paintEvent) : null;
|
|
24
|
+
}
|
|
25
|
+
// ParseHTML events store the URL under beginData, not data.
|
|
26
|
+
if (Types.TraceEvents.isTraceEventParseHTML(entry)) {
|
|
27
|
+
return entry.args.beginData.url;
|
|
28
|
+
}
|
|
29
|
+
// For all other events, try to see if the URL is provided, else return null.
|
|
30
|
+
if (entry.args?.data?.url) {
|
|
31
|
+
return entry.args.data.url;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=URLForEntry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"URLForEntry.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/URLForEntry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,UAAU,GAAG,CAAC,eAA8C,EAAE,KAAuC;IAEzG,IAAI,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,SAAS,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAsC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,qCAAqC,CAAC,KAAK,CAAC,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,CAAC,WAAW,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/E,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,0EAA0E;IAC1E,IAAI,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QACtF,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,4BAA4B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3G,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,4DAA4D;IAC5D,IAAI,KAAK,CAAC,WAAW,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAsC,CAAC;IACrE,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nexport function get(traceParsedData: Handlers.Types.TraceParseData, entry: Types.TraceEvents.TraceEventData):\n Platform.DevToolsPath.UrlString|null {\n if (Types.TraceEvents.isProfileCall(entry)) {\n return entry.callFrame.url as Platform.DevToolsPath.UrlString;\n }\n\n if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {\n return entry.args.data.stackTrace[0].url as Platform.DevToolsPath.UrlString;\n }\n\n if (Types.TraceEvents.isSyntheticNetworkRequestDetailsEvent(entry)) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n // DecodeImage events use the URL from the relevant PaintImage event.\n if (Types.TraceEvents.isTraceEventDecodeImage(entry)) {\n const paintEvent = traceParsedData.ImagePainting.paintImageForEvent.get(entry);\n return paintEvent ? get(traceParsedData, paintEvent) : null;\n }\n\n // DrawLazyPixelRef events use the URL from the relevant PaintImage event.\n if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(entry) && entry.args?.LazyPixelRef) {\n const paintEvent = traceParsedData.ImagePainting.paintImageByDrawLazyPixelRef.get(entry.args.LazyPixelRef);\n return paintEvent ? get(traceParsedData, paintEvent) : null;\n }\n\n // ParseHTML events store the URL under beginData, not data.\n if (Types.TraceEvents.isTraceEventParseHTML(entry)) {\n return entry.args.beginData.url as Platform.DevToolsPath.UrlString;\n }\n\n // For all other events, try to see if the URL is provided, else return null.\n if (entry.args?.data?.url) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n return null;\n}\n"]}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"../../../../../../../front_end/models/trace/extras/FilmStrip.ts",
|
|
34
34
|
"../../../../../../../front_end/models/trace/extras/MainThreadActivity.ts",
|
|
35
35
|
"../../../../../../../front_end/models/trace/extras/Metadata.ts",
|
|
36
|
+
"../../../../../../../front_end/models/trace/extras/URLForEntry.ts",
|
|
36
37
|
"../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
37
38
|
"../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
38
39
|
"../../../../../../../front_end/global_typings/request_idle_callback.d.ts",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extras.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/extras.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,QAAQ,MAAM,eAAe,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\nexport * as FetchNodes from './FetchNodes.js';\nexport * as FilmStrip from './FilmStrip.js';\nexport * as MainThreadActivity from './MainThreadActivity.js';\nexport * as Metadata from './Metadata.js';\n"]}
|
|
1
|
+
{"version":3,"file":"extras.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/extras.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,WAAW,MAAM,kBAAkB,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\nexport * as FetchNodes from './FetchNodes.js';\nexport * as FilmStrip from './FilmStrip.js';\nexport * as MainThreadActivity from './MainThreadActivity.js';\nexport * as Metadata from './Metadata.js';\nexport * as URLForEntry from './URLForEntry.js';\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2023 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
+
import * as Helpers from '../helpers/helpers.js';
|
|
4
5
|
import * as Types from '../types/types.js';
|
|
5
6
|
/**
|
|
6
7
|
* There are two metadata events that we care about.
|
|
@@ -83,7 +84,8 @@ function workletType(input) {
|
|
|
83
84
|
* regardless of the type of event.
|
|
84
85
|
*/
|
|
85
86
|
function makeSyntheticEventBase(event) {
|
|
86
|
-
return
|
|
87
|
+
return Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()
|
|
88
|
+
.registerSyntheticBasedEvent({
|
|
87
89
|
rawSourceEvent: event,
|
|
88
90
|
name: 'SyntheticAuctionWorkletEvent',
|
|
89
91
|
s: "t" /* Types.TraceEvents.TraceEventScope.THREAD */,
|
|
@@ -95,7 +97,7 @@ function makeSyntheticEventBase(event) {
|
|
|
95
97
|
host: event.args.data.host,
|
|
96
98
|
target: event.args.data.target,
|
|
97
99
|
type: workletType(event.args.data.type),
|
|
98
|
-
};
|
|
100
|
+
});
|
|
99
101
|
}
|
|
100
102
|
export async function finalize() {
|
|
101
103
|
// Loop through the utility threads we found to create the worklet events. We
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorkletEvents as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess> = new Map();\nconst doneWithProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess> = new Map();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent> =\n new Map();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\nconst v8HelperThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.TraceEvents.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.TraceEvents.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.TraceEvents.AuctionWorkletType.BIDDER;\n default:\n return Types.TraceEvents.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess|\n Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess):\n Omit<Types.TraceEvents.SyntheticAuctionWorkletEvent, 'args'> {\n return {\n rawSourceEvent: event,\n name: 'SyntheticAuctionWorkletEvent',\n s: Types.TraceEvents.TraceEventScope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.TraceEvents.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n };\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.TraceEvents.SyntheticAuctionWorkletEvent|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AuctionWorkletsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\n/**\n * There are two metadata events that we care about.\n * => AuctionWorkletRunningInProcess tells us which process the Auction Worklet\n * has taken to run in.\n * => AuctionWorkletDoneWithProcess tells us when the worklet is done with that\n * process. This is less useful - but in the future we might want to surface\n * this information so we still parse and return the event.\n *\n * It is important to note that the top level PID on these events is NOT the\n * PID that the worklet is running on; instead we have to look at its\n * args.data.pid property, which is the PID of the process that it is running\n * on.\n *\n * For any given RunningInProcess event, we would typically expect to see a\n * DoneWithProcess event, however this is not guaranteed, especially as users\n * can record any chunk of time in DevTools.\n *\n * Similarly, it is also possible to see a DoneWithProcess event without a\n * RunningInProcess event, if the user started recording after the auction\n * worklets started. Therefore we are happy to create\n * SyntheticAuctionWorkletEvents as long as we see just one of these events.\n *\n * If we do get two events and need to pair them, we can use the\n * args.data.target property, which is a string ID shared by both\n * events.\n */\nconst runningInProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess> = new Map();\nconst doneWithProcessEvents:\n Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess> = new Map();\n\n// Keyed by the PID defined in `args.data.pid` on AuctionWorklet trace events..\nconst createdSyntheticEvents: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent> =\n new Map();\n\n// Each AuctonWorklet takes over a process and has 2 threads (that we care\n// about and want to show as tracks):\n// 1. A CrUtilityMain thread which is known as the \"control process\".\n// 2. A AuctionV8HelperThread which is the actual auction worklet and will be\n// either a \"Seller\" or a \"Bidder\"\n// To detect these we look for the metadata thread_name events. We key these by\n// PID so that we can easily look them up later without having to loop through.\nconst utilityThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\nconst v8HelperThreads: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.TraceEventThreadName> = new Map();\n\nexport function reset(): void {\n runningInProcessEvents.clear();\n doneWithProcessEvents.clear();\n createdSyntheticEvents.clear();\n utilityThreads.clear();\n v8HelperThreads.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventAuctionWorkletRunningInProcess(event)) {\n runningInProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventAuctionWorkletDoneWithProcess(event)) {\n doneWithProcessEvents.set(event.args.data.pid, event);\n return;\n }\n\n if (Types.TraceEvents.isThreadName(event)) {\n if (event.args.name === 'auction_worklet.CrUtilityMain') {\n utilityThreads.set(event.pid, event);\n return;\n }\n if (event.args.name === 'AuctionV8HelperThread') {\n v8HelperThreads.set(event.pid, event);\n }\n }\n}\n\nfunction workletType(input: string): Types.TraceEvents.AuctionWorkletType {\n switch (input) {\n case 'seller':\n return Types.TraceEvents.AuctionWorkletType.SELLER;\n case 'bidder':\n return Types.TraceEvents.AuctionWorkletType.BIDDER;\n default:\n return Types.TraceEvents.AuctionWorkletType.UNKNOWN;\n }\n}\n\n/**\n * We cannot make the full event without knowing the type of event, but we can\n * create everything other than the `args` field, as those are identical\n * regardless of the type of event.\n */\nfunction makeSyntheticEventBase(event: Types.TraceEvents.TraceEventAuctionWorkletDoneWithProcess|\n Types.TraceEvents.TraceEventAuctionWorkletRunningInProcess):\n Omit<Types.TraceEvents.SyntheticAuctionWorkletEvent, 'args'> {\n return Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager()\n .registerSyntheticBasedEvent<Omit<Types.TraceEvents.SyntheticAuctionWorkletEvent, 'args'>>({\n rawSourceEvent: event,\n name: 'SyntheticAuctionWorkletEvent',\n s: Types.TraceEvents.TraceEventScope.THREAD,\n cat: event.cat,\n tid: event.tid,\n ts: event.ts,\n ph: Types.TraceEvents.Phase.INSTANT,\n pid: event.args.data.pid,\n host: event.args.data.host,\n target: event.args.data.target,\n type: workletType(event.args.data.type),\n });\n}\n\nexport async function finalize(): Promise<void> {\n // Loop through the utility threads we found to create the worklet events. We\n // expect each worklet to have a utility thread, so we can use them as the\n // root of our list of worklets.\n for (const [pid, utilityThreadNameEvent] of utilityThreads) {\n const v8HelperEvent = v8HelperThreads.get(pid);\n if (!v8HelperEvent) {\n // Bad trace data - AuctionWorklets are expected to always have both threads.\n continue;\n }\n\n const runningEvent = runningInProcessEvents.get(pid);\n const doneWithEvent = doneWithProcessEvents.get(pid);\n\n // We can create a worklet from either the runningEvent or doneWithEvent -\n // we do not need both. We cannot express that to TypeScript with an early\n // return here, so instead we set the event initially to null, and then\n // create it from either the running event or the doneWith event. If it is\n // still null after this, that means neither event was found, and we drop\n // the worklet as we do not have enough information to create the synthetic\n // event.\n\n let syntheticEvent: Types.TraceEvents.SyntheticAuctionWorkletEvent|null = null;\n\n if (runningEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(runningEvent),\n args: {\n data: {\n runningInProcessEvent: runningEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (doneWithEvent) {\n syntheticEvent.args.data.doneWithProcessEvent = doneWithEvent;\n }\n } else if (doneWithEvent) {\n syntheticEvent = {\n ...makeSyntheticEventBase(doneWithEvent),\n args: {\n data: {\n doneWithProcessEvent: doneWithEvent,\n utilityThread: utilityThreadNameEvent,\n v8HelperThread: v8HelperEvent,\n },\n },\n };\n if (runningEvent) {\n syntheticEvent.args.data.runningInProcessEvent = runningEvent;\n }\n }\n if (syntheticEvent === null) {\n continue;\n }\n createdSyntheticEvents.set(pid, syntheticEvent);\n }\n}\n\nexport interface AuctionWorkletsData {\n worklets: Map<Types.TraceEvents.ProcessID, Types.TraceEvents.SyntheticAuctionWorkletEvent>;\n}\n\nexport function data(): AuctionWorkletsData {\n return {\n worklets: new Map(createdSyntheticEvents),\n };\n}\n"]}
|
|
@@ -152,18 +152,7 @@ export function handleEvent(event) {
|
|
|
152
152
|
else if (Types.TraceEvents.isTraceEventWebSocketCreate(event)) {
|
|
153
153
|
webSocketCreateEventsById.set(event.args.data.identifier, event);
|
|
154
154
|
}
|
|
155
|
-
else if (Types.TraceEvents.
|
|
156
|
-
const matchingCreateEvent = webSocketCreateEventsById.get(event.args.data.identifier);
|
|
157
|
-
if (matchingCreateEvent) {
|
|
158
|
-
storeInitiator({
|
|
159
|
-
event,
|
|
160
|
-
initiator: matchingCreateEvent,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
else if (Types.TraceEvents.isTraceEventWebSocketSendHandshakeRequest(event) ||
|
|
165
|
-
Types.TraceEvents.isTraceEventWebSocketReceiveHandshakeResponse(event) ||
|
|
166
|
-
Types.TraceEvents.isTraceEventWebSocketDestroy(event)) {
|
|
155
|
+
else if (Types.TraceEvents.isTraceEventWebSocketInfo(event) || Types.TraceEvents.isTraceEventWebSocketTransfer(event)) {
|
|
167
156
|
const matchingCreateEvent = webSocketCreateEventsById.get(event.args.data.identifier);
|
|
168
157
|
if (matchingCreateEvent) {
|
|
169
158
|
storeInitiator({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitiatorsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InitiatorsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst lastScheduleStyleRecalcByFrame = new Map<string, Types.TraceEvents.TraceEventScheduleStyleRecalculation>();\n\n// This tracks the last event that is considered to have invalidated the layout\n// for a given frame.\n// Note that although there is an InvalidateLayout event, there are also other\n// events (ScheduleStyleRecalculation) that could be the reason a layout was\n// invalidated.\nconst lastInvalidationEventForFrame = new Map<string, Types.TraceEvents.TraceEventData>();\n\n// Important: although the event is called UpdateLayoutTree, in the UI we\n// present these to the user as \"Recalculate Style\". So don't get confused!\n// These are the same - just UpdateLayoutTree is what the event from Chromium\n// is called.\nconst lastUpdateLayoutTreeByFrame = new Map<string, Types.TraceEvents.TraceEventUpdateLayoutTree>();\n\n// This tracks postmessage dispatch and handler events for creating initiator association\nconst postMessageHandlerEvents: Types.TraceEvents.TraceEventHandlePostMessage[] = [];\nconst schedulePostMessageEventByTraceId: Map<string, Types.TraceEvents.TraceEventSchedulePostMessage> = new Map();\n\n// These two maps store the same data but in different directions.\n// For a given event, tell me what its initiator was. An event can only have one initiator.\nconst eventToInitiatorMap = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData>();\n// For a given event, tell me what events it initiated. An event can initiate\n// multiple events, hence why the value for this map is an array.\nconst initiatorToEventsMap = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData[]>();\n\nconst requestAnimationFrameEventsById: Map<number, Types.TraceEvents.TraceEventRequestAnimationFrame> = new Map();\nconst timerInstallEventsById: Map<number, Types.TraceEvents.TraceEventTimerInstall> = new Map();\nconst requestIdleCallbackEventsById: Map<number, Types.TraceEvents.TraceEventRequestIdleCallback> = new Map();\nconst webSocketCreateEventsById: Map<number, Types.TraceEvents.TraceEventWebSocketCreate> = new Map();\n\nexport function reset(): void {\n lastScheduleStyleRecalcByFrame.clear();\n lastInvalidationEventForFrame.clear();\n lastUpdateLayoutTreeByFrame.clear();\n timerInstallEventsById.clear();\n eventToInitiatorMap.clear();\n initiatorToEventsMap.clear();\n requestAnimationFrameEventsById.clear();\n requestIdleCallbackEventsById.clear();\n webSocketCreateEventsById.clear();\n schedulePostMessageEventByTraceId.clear();\n postMessageHandlerEvents.length = 0;\n\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InitiatorsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction storeInitiator(data: {initiator: Types.TraceEvents.TraceEventData, event: Types.TraceEvents.TraceEventData}):\n void {\n eventToInitiatorMap.set(data.event, data.initiator);\n const eventsForInitiator = initiatorToEventsMap.get(data.initiator) || [];\n eventsForInitiator.push(data.event);\n initiatorToEventsMap.set(data.initiator, eventsForInitiator);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventScheduleStyleRecalculation(event)) {\n lastScheduleStyleRecalcByFrame.set(event.args.data.frame, event);\n } else if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n // IMPORTANT: although the trace event is called UpdateLayoutTree, this\n // represents a Styles Recalculation. This event in the timeline is shown to\n // the user as \"Recalculate Styles.\"\n if (event.args.beginData) {\n // Store the last UpdateLayout event: we use this when we see an\n // InvalidateLayout and try to figure out its initiator.\n lastUpdateLayoutTreeByFrame.set(event.args.beginData.frame, event);\n\n // If this frame has seen a ScheduleStyleRecalc event, then that event is\n // considered to be the initiator of this StylesRecalc.\n const scheduledStyleForFrame = lastScheduleStyleRecalcByFrame.get(event.args.beginData.frame);\n if (scheduledStyleForFrame) {\n storeInitiator({\n event,\n initiator: scheduledStyleForFrame,\n });\n }\n }\n } else if (Types.TraceEvents.isTraceEventInvalidateLayout(event)) {\n // By default, the InvalidateLayout event is what triggered the layout invalidation for this frame.\n let invalidationInitiator: Types.TraceEvents.TraceEventData = event;\n\n // However, if we have not had any prior invalidations for this frame, we\n // want to consider StyleRecalculation events as they might be the actual\n // cause of this layout invalidation.\n if (!lastInvalidationEventForFrame.has(event.args.data.frame)) {\n // 1. If we have not had an invalidation event for this frame\n // 2. AND we have had an UpdateLayoutTree for this frame\n // 3. AND the UpdateLayoutTree event ended AFTER the InvalidateLayout startTime\n // 4. AND we have an initiator for the UpdateLayoutTree event\n // 5. Then we set the last invalidation event for this frame to be the UpdateLayoutTree's initiator.\n const lastUpdateLayoutTreeForFrame = lastUpdateLayoutTreeByFrame.get(event.args.data.frame);\n if (lastUpdateLayoutTreeForFrame) {\n const {endTime} = Helpers.Timing.eventTimingsMicroSeconds(lastUpdateLayoutTreeForFrame);\n const initiatorOfUpdateLayout = eventToInitiatorMap.get(lastUpdateLayoutTreeForFrame);\n\n if (initiatorOfUpdateLayout && endTime && endTime > event.ts) {\n invalidationInitiator = initiatorOfUpdateLayout;\n }\n }\n }\n lastInvalidationEventForFrame.set(event.args.data.frame, invalidationInitiator);\n } else if (Types.TraceEvents.isTraceEventLayout(event)) {\n // The initiator of a Layout event is the last Invalidation event.\n const lastInvalidation = lastInvalidationEventForFrame.get(event.args.beginData.frame);\n if (lastInvalidation) {\n storeInitiator({\n event,\n initiator: lastInvalidation,\n });\n }\n // Now clear the last invalidation for the frame: the last invalidation has been linked to a Layout event, so it cannot be the initiator for any future layouts.\n lastInvalidationEventForFrame.delete(event.args.beginData.frame);\n } else if (Types.TraceEvents.isTraceEventRequestAnimationFrame(event)) {\n requestAnimationFrameEventsById.set(event.args.data.id, event);\n } else if (Types.TraceEvents.isTraceEventFireAnimationFrame(event)) {\n // If we get a fire event, that means we should have had the\n // RequestAnimationFrame event by now. If so, we can set that as the\n // initiator for the fire event.\n const matchingRequestEvent = requestAnimationFrameEventsById.get(event.args.data.id);\n if (matchingRequestEvent) {\n storeInitiator({\n event,\n initiator: matchingRequestEvent,\n });\n }\n } else if (Types.TraceEvents.isTraceEventTimerInstall(event)) {\n timerInstallEventsById.set(event.args.data.timerId, event);\n } else if (Types.TraceEvents.isTraceEventTimerFire(event)) {\n const matchingInstall = timerInstallEventsById.get(event.args.data.timerId);\n if (matchingInstall) {\n storeInitiator({event, initiator: matchingInstall});\n }\n } else if (Types.TraceEvents.isTraceEventRequestIdleCallback(event)) {\n requestIdleCallbackEventsById.set(event.args.data.id, event);\n } else if (Types.TraceEvents.isTraceEventFireIdleCallback(event)) {\n const matchingRequestEvent = requestIdleCallbackEventsById.get(event.args.data.id);\n if (matchingRequestEvent) {\n storeInitiator({\n event,\n initiator: matchingRequestEvent,\n });\n }\n } else if (Types.TraceEvents.isTraceEventWebSocketCreate(event)) {\n webSocketCreateEventsById.set(event.args.data.identifier, event);\n } else if (Types.TraceEvents.isTraceEventWebSocketSendHandshakeRequest(event)) {\n const matchingCreateEvent = webSocketCreateEventsById.get(event.args.data.identifier);\n if (matchingCreateEvent) {\n storeInitiator({\n event,\n initiator: matchingCreateEvent,\n });\n }\n } else if (\n Types.TraceEvents.isTraceEventWebSocketSendHandshakeRequest(event) ||\n Types.TraceEvents.isTraceEventWebSocketReceiveHandshakeResponse(event) ||\n Types.TraceEvents.isTraceEventWebSocketDestroy(event)) {\n const matchingCreateEvent = webSocketCreateEventsById.get(event.args.data.identifier);\n if (matchingCreateEvent) {\n storeInitiator({\n event,\n initiator: matchingCreateEvent,\n });\n }\n }\n // Store schedulePostMessage Events by their traceIds.\n // so they can be reconciled later with matching handlePostMessage events with same traceIds.\n else if (Types.TraceEvents.isTraceEventHandlePostMessage(event)) {\n postMessageHandlerEvents.push(event);\n } else if (Types.TraceEvents.isTraceEventSchedulePostMessage(event)) {\n const traceId = event.args.data?.traceId;\n if (traceId) {\n schedulePostMessageEventByTraceId.set(traceId, event);\n }\n }\n}\n\nfunction finalizeInitiatorRelationship(): void {\n for (const handlerEvent of postMessageHandlerEvents) {\n const traceId = handlerEvent.args.data?.traceId;\n const matchingSchedulePostMesssageEvent = schedulePostMessageEventByTraceId.get(traceId);\n if (matchingSchedulePostMesssageEvent) {\n // Set schedulePostMesssage events as initiators for handler events.\n storeInitiator({event: handlerEvent, initiator: matchingSchedulePostMesssageEvent});\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InitiatorsHandler is not initialized');\n }\n\n // During event processing, we may encounter initiators before the handler events themselves\n // (e.g dispatch events on worker and handler events on the main thread)\n // we don't want to miss out on events whose initiators haven't been processed yet\n finalizeInitiatorRelationship();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport interface InitiatorsData {\n eventToInitiator: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData>;\n initiatorToEvents: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData[]>;\n}\n\nexport function data(): InitiatorsData {\n return {\n eventToInitiator: eventToInitiatorMap,\n initiatorToEvents: initiatorToEventsMap,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InitiatorsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InitiatorsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst lastScheduleStyleRecalcByFrame = new Map<string, Types.TraceEvents.TraceEventScheduleStyleRecalculation>();\n\n// This tracks the last event that is considered to have invalidated the layout\n// for a given frame.\n// Note that although there is an InvalidateLayout event, there are also other\n// events (ScheduleStyleRecalculation) that could be the reason a layout was\n// invalidated.\nconst lastInvalidationEventForFrame = new Map<string, Types.TraceEvents.TraceEventData>();\n\n// Important: although the event is called UpdateLayoutTree, in the UI we\n// present these to the user as \"Recalculate Style\". So don't get confused!\n// These are the same - just UpdateLayoutTree is what the event from Chromium\n// is called.\nconst lastUpdateLayoutTreeByFrame = new Map<string, Types.TraceEvents.TraceEventUpdateLayoutTree>();\n\n// This tracks postmessage dispatch and handler events for creating initiator association\nconst postMessageHandlerEvents: Types.TraceEvents.TraceEventHandlePostMessage[] = [];\nconst schedulePostMessageEventByTraceId: Map<string, Types.TraceEvents.TraceEventSchedulePostMessage> = new Map();\n\n// These two maps store the same data but in different directions.\n// For a given event, tell me what its initiator was. An event can only have one initiator.\nconst eventToInitiatorMap = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData>();\n// For a given event, tell me what events it initiated. An event can initiate\n// multiple events, hence why the value for this map is an array.\nconst initiatorToEventsMap = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData[]>();\n\nconst requestAnimationFrameEventsById: Map<number, Types.TraceEvents.TraceEventRequestAnimationFrame> = new Map();\nconst timerInstallEventsById: Map<number, Types.TraceEvents.TraceEventTimerInstall> = new Map();\nconst requestIdleCallbackEventsById: Map<number, Types.TraceEvents.TraceEventRequestIdleCallback> = new Map();\nconst webSocketCreateEventsById: Map<number, Types.TraceEvents.TraceEventWebSocketCreate> = new Map();\n\nexport function reset(): void {\n lastScheduleStyleRecalcByFrame.clear();\n lastInvalidationEventForFrame.clear();\n lastUpdateLayoutTreeByFrame.clear();\n timerInstallEventsById.clear();\n eventToInitiatorMap.clear();\n initiatorToEventsMap.clear();\n requestAnimationFrameEventsById.clear();\n requestIdleCallbackEventsById.clear();\n webSocketCreateEventsById.clear();\n schedulePostMessageEventByTraceId.clear();\n postMessageHandlerEvents.length = 0;\n\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InitiatorsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction storeInitiator(data: {initiator: Types.TraceEvents.TraceEventData, event: Types.TraceEvents.TraceEventData}):\n void {\n eventToInitiatorMap.set(data.event, data.initiator);\n const eventsForInitiator = initiatorToEventsMap.get(data.initiator) || [];\n eventsForInitiator.push(data.event);\n initiatorToEventsMap.set(data.initiator, eventsForInitiator);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventScheduleStyleRecalculation(event)) {\n lastScheduleStyleRecalcByFrame.set(event.args.data.frame, event);\n } else if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n // IMPORTANT: although the trace event is called UpdateLayoutTree, this\n // represents a Styles Recalculation. This event in the timeline is shown to\n // the user as \"Recalculate Styles.\"\n if (event.args.beginData) {\n // Store the last UpdateLayout event: we use this when we see an\n // InvalidateLayout and try to figure out its initiator.\n lastUpdateLayoutTreeByFrame.set(event.args.beginData.frame, event);\n\n // If this frame has seen a ScheduleStyleRecalc event, then that event is\n // considered to be the initiator of this StylesRecalc.\n const scheduledStyleForFrame = lastScheduleStyleRecalcByFrame.get(event.args.beginData.frame);\n if (scheduledStyleForFrame) {\n storeInitiator({\n event,\n initiator: scheduledStyleForFrame,\n });\n }\n }\n } else if (Types.TraceEvents.isTraceEventInvalidateLayout(event)) {\n // By default, the InvalidateLayout event is what triggered the layout invalidation for this frame.\n let invalidationInitiator: Types.TraceEvents.TraceEventData = event;\n\n // However, if we have not had any prior invalidations for this frame, we\n // want to consider StyleRecalculation events as they might be the actual\n // cause of this layout invalidation.\n if (!lastInvalidationEventForFrame.has(event.args.data.frame)) {\n // 1. If we have not had an invalidation event for this frame\n // 2. AND we have had an UpdateLayoutTree for this frame\n // 3. AND the UpdateLayoutTree event ended AFTER the InvalidateLayout startTime\n // 4. AND we have an initiator for the UpdateLayoutTree event\n // 5. Then we set the last invalidation event for this frame to be the UpdateLayoutTree's initiator.\n const lastUpdateLayoutTreeForFrame = lastUpdateLayoutTreeByFrame.get(event.args.data.frame);\n if (lastUpdateLayoutTreeForFrame) {\n const {endTime} = Helpers.Timing.eventTimingsMicroSeconds(lastUpdateLayoutTreeForFrame);\n const initiatorOfUpdateLayout = eventToInitiatorMap.get(lastUpdateLayoutTreeForFrame);\n\n if (initiatorOfUpdateLayout && endTime && endTime > event.ts) {\n invalidationInitiator = initiatorOfUpdateLayout;\n }\n }\n }\n lastInvalidationEventForFrame.set(event.args.data.frame, invalidationInitiator);\n } else if (Types.TraceEvents.isTraceEventLayout(event)) {\n // The initiator of a Layout event is the last Invalidation event.\n const lastInvalidation = lastInvalidationEventForFrame.get(event.args.beginData.frame);\n if (lastInvalidation) {\n storeInitiator({\n event,\n initiator: lastInvalidation,\n });\n }\n // Now clear the last invalidation for the frame: the last invalidation has been linked to a Layout event, so it cannot be the initiator for any future layouts.\n lastInvalidationEventForFrame.delete(event.args.beginData.frame);\n } else if (Types.TraceEvents.isTraceEventRequestAnimationFrame(event)) {\n requestAnimationFrameEventsById.set(event.args.data.id, event);\n } else if (Types.TraceEvents.isTraceEventFireAnimationFrame(event)) {\n // If we get a fire event, that means we should have had the\n // RequestAnimationFrame event by now. If so, we can set that as the\n // initiator for the fire event.\n const matchingRequestEvent = requestAnimationFrameEventsById.get(event.args.data.id);\n if (matchingRequestEvent) {\n storeInitiator({\n event,\n initiator: matchingRequestEvent,\n });\n }\n } else if (Types.TraceEvents.isTraceEventTimerInstall(event)) {\n timerInstallEventsById.set(event.args.data.timerId, event);\n } else if (Types.TraceEvents.isTraceEventTimerFire(event)) {\n const matchingInstall = timerInstallEventsById.get(event.args.data.timerId);\n if (matchingInstall) {\n storeInitiator({event, initiator: matchingInstall});\n }\n } else if (Types.TraceEvents.isTraceEventRequestIdleCallback(event)) {\n requestIdleCallbackEventsById.set(event.args.data.id, event);\n } else if (Types.TraceEvents.isTraceEventFireIdleCallback(event)) {\n const matchingRequestEvent = requestIdleCallbackEventsById.get(event.args.data.id);\n if (matchingRequestEvent) {\n storeInitiator({\n event,\n initiator: matchingRequestEvent,\n });\n }\n } else if (Types.TraceEvents.isTraceEventWebSocketCreate(event)) {\n webSocketCreateEventsById.set(event.args.data.identifier, event);\n } else if (\n Types.TraceEvents.isTraceEventWebSocketInfo(event) || Types.TraceEvents.isTraceEventWebSocketTransfer(event)) {\n const matchingCreateEvent = webSocketCreateEventsById.get(event.args.data.identifier);\n if (matchingCreateEvent) {\n storeInitiator({\n event,\n initiator: matchingCreateEvent,\n });\n }\n }\n // Store schedulePostMessage Events by their traceIds.\n // so they can be reconciled later with matching handlePostMessage events with same traceIds.\n else if (Types.TraceEvents.isTraceEventHandlePostMessage(event)) {\n postMessageHandlerEvents.push(event);\n } else if (Types.TraceEvents.isTraceEventSchedulePostMessage(event)) {\n const traceId = event.args.data?.traceId;\n if (traceId) {\n schedulePostMessageEventByTraceId.set(traceId, event);\n }\n }\n}\n\nfunction finalizeInitiatorRelationship(): void {\n for (const handlerEvent of postMessageHandlerEvents) {\n const traceId = handlerEvent.args.data?.traceId;\n const matchingSchedulePostMesssageEvent = schedulePostMessageEventByTraceId.get(traceId);\n if (matchingSchedulePostMesssageEvent) {\n // Set schedulePostMesssage events as initiators for handler events.\n storeInitiator({event: handlerEvent, initiator: matchingSchedulePostMesssageEvent});\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InitiatorsHandler is not initialized');\n }\n\n // During event processing, we may encounter initiators before the handler events themselves\n // (e.g dispatch events on worker and handler events on the main thread)\n // we don't want to miss out on events whose initiators haven't been processed yet\n finalizeInitiatorRelationship();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport interface InitiatorsData {\n eventToInitiator: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData>;\n initiatorToEvents: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.TraceEventData[]>;\n}\n\nexport function data(): InitiatorsData {\n return {\n eventToInitiator: eventToInitiatorMap,\n initiatorToEvents: initiatorToEventsMap,\n };\n}\n"]}
|
|
@@ -10,6 +10,7 @@ interface LayoutShifts {
|
|
|
10
10
|
layoutInvalidationEvents: readonly Types.TraceEvents.TraceEventLayoutInvalidationTracking[];
|
|
11
11
|
scheduleStyleInvalidationEvents: readonly Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking[];
|
|
12
12
|
styleRecalcInvalidationEvents: readonly Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking[];
|
|
13
|
+
renderFrameImplCreateChildFrameEvents: readonly Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[];
|
|
13
14
|
scoreRecords: readonly ScoreRecord[];
|
|
14
15
|
backendNodeIds: Protocol.DOM.BackendNodeId[];
|
|
15
16
|
}
|
|
@@ -24,6 +24,7 @@ const layoutShiftEvents = [];
|
|
|
24
24
|
const layoutInvalidationEvents = [];
|
|
25
25
|
const scheduleStyleInvalidationEvents = [];
|
|
26
26
|
const styleRecalcInvalidationEvents = [];
|
|
27
|
+
const renderFrameImplCreateChildFrameEvents = [];
|
|
27
28
|
const backendNodeIds = new Set();
|
|
28
29
|
// Layout shifts happen during PrePaint as part of the rendering lifecycle.
|
|
29
30
|
// We determine if a LayoutInvalidation event is a potential root cause of a layout
|
|
@@ -50,6 +51,7 @@ export function reset() {
|
|
|
50
51
|
scheduleStyleInvalidationEvents.length = 0;
|
|
51
52
|
styleRecalcInvalidationEvents.length = 0;
|
|
52
53
|
prePaintEvents.length = 0;
|
|
54
|
+
renderFrameImplCreateChildFrameEvents.length = 0;
|
|
53
55
|
backendNodeIds.clear();
|
|
54
56
|
clusters.length = 0;
|
|
55
57
|
sessionMaxScore = 0;
|
|
@@ -78,6 +80,9 @@ export function handleEvent(event) {
|
|
|
78
80
|
prePaintEvents.push(event);
|
|
79
81
|
return;
|
|
80
82
|
}
|
|
83
|
+
if (Types.TraceEvents.isTraceEventRenderFrameImplCreateChildFrame(event)) {
|
|
84
|
+
renderFrameImplCreateChildFrameEvents.push(event);
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
function traceWindowFromTime(time) {
|
|
83
88
|
return {
|
|
@@ -143,6 +148,7 @@ export async function finalize() {
|
|
|
143
148
|
layoutShiftEvents.sort((a, b) => a.ts - b.ts);
|
|
144
149
|
prePaintEvents.sort((a, b) => a.ts - b.ts);
|
|
145
150
|
layoutInvalidationEvents.sort((a, b) => a.ts - b.ts);
|
|
151
|
+
renderFrameImplCreateChildFrameEvents.sort((a, b) => a.ts - b.ts);
|
|
146
152
|
// Each function transforms the data used by the next, as such the invoke order
|
|
147
153
|
// is important.
|
|
148
154
|
await buildLayoutShiftsClusters();
|
|
@@ -218,7 +224,8 @@ async function buildLayoutShiftsClusters() {
|
|
|
218
224
|
if (!event.args.data) {
|
|
219
225
|
continue;
|
|
220
226
|
}
|
|
221
|
-
const
|
|
227
|
+
const syntheticEventsManager = Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager();
|
|
228
|
+
const shift = syntheticEventsManager.registerSyntheticBasedEvent({
|
|
222
229
|
rawSourceEvent: event,
|
|
223
230
|
...event,
|
|
224
231
|
args: {
|
|
@@ -237,7 +244,7 @@ async function buildLayoutShiftsClusters() {
|
|
|
237
244
|
// value is set when stepping through the built clusters.
|
|
238
245
|
sessionWindowData: { cumulativeWindowScore: 0, id: clusters.length },
|
|
239
246
|
},
|
|
240
|
-
};
|
|
247
|
+
});
|
|
241
248
|
currentCluster.events.push(shift);
|
|
242
249
|
updateTraceWindowMax(currentCluster.clusterWindow, event.ts);
|
|
243
250
|
lastShiftTime = event.ts;
|
|
@@ -328,6 +335,7 @@ export function data() {
|
|
|
328
335
|
layoutInvalidationEvents,
|
|
329
336
|
scheduleStyleInvalidationEvents,
|
|
330
337
|
styleRecalcInvalidationEvents: [],
|
|
338
|
+
renderFrameImplCreateChildFrameEvents,
|
|
331
339
|
scoreRecords,
|
|
332
340
|
// TODO(crbug/41484172): change the type so no need to clone
|
|
333
341
|
backendNodeIds: [...backendNodeIds],
|