@paulirish/trace_engine 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PAUL.readme.md +5 -0
- package/core/platform/StringUtilities.js +3 -3
- package/core/platform/StringUtilities.js.map +1 -1
- package/core/platform/TypedArrayUtilities.d.ts +26 -0
- package/core/platform/TypedArrayUtilities.js +111 -0
- package/core/platform/TypedArrayUtilities.js.map +1 -0
- package/core/platform/platform-tsconfig.json +1 -0
- package/core/platform/platform.d.ts +2 -1
- package/core/platform/platform.js +2 -1
- package/core/platform/platform.js.map +1 -1
- package/generated/protocol.d.ts +63 -1
- package/models/trace/EntriesFilter.d.ts +3 -2
- package/models/trace/EntriesFilter.js +5 -3
- package/models/trace/EntriesFilter.js.map +1 -1
- package/models/trace/LegacyTracingModel.js.map +1 -1
- package/models/trace/Processor.js +7 -1
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.d.ts +13 -0
- package/models/trace/handlers/ExtensionTraceDataHandler.js +93 -0
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -0
- package/models/trace/handlers/InvalidationsHandler.js +9 -0
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.js +4 -2
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +1 -0
- package/models/trace/handlers/ModelHandlers.js +1 -0
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +0 -7
- package/models/trace/handlers/PageLoadMetricsHandler.js +2 -21
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/handlers-tsconfig.json +1 -0
- package/models/trace/helpers/Extensions.d.ts +2 -0
- package/models/trace/helpers/Extensions.js +22 -0
- package/models/trace/helpers/Extensions.js.map +1 -0
- package/models/trace/helpers/Trace.d.ts +4 -3
- package/models/trace/helpers/Trace.js +17 -3
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/helpers-tsconfig.json +1 -0
- package/models/trace/helpers/helpers.d.ts +1 -0
- package/models/trace/helpers/helpers.js +1 -0
- package/models/trace/helpers/helpers.js.map +1 -1
- package/models/trace/root-causes/LayoutShift.d.ts +7 -1
- package/models/trace/root-causes/LayoutShift.js +19 -4
- package/models/trace/root-causes/LayoutShift.js.map +1 -1
- package/models/trace/root-causes/RootCauses.d.ts +1 -0
- package/models/trace/root-causes/RootCauses.js +1 -0
- package/models/trace/root-causes/RootCauses.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +62 -0
- package/models/trace/types/Extensions.js +38 -0
- package/models/trace/types/Extensions.js.map +1 -0
- package/models/trace/types/File.d.ts +10 -3
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +32 -13
- package/models/trace/types/TraceEvents.js +31 -9
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/types-tsconfig.json +1 -0
- package/models/trace/types/types.d.ts +1 -0
- package/models/trace/types/types.js +1 -0
- package/models/trace/types/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -147,6 +147,19 @@ export function makeProfileCall(node, ts, pid, tid) {
|
|
|
147
147
|
callFrame: node.callFrame,
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
+
export function makeSyntheticTraceEntry(name, ts, pid, tid) {
|
|
151
|
+
return {
|
|
152
|
+
cat: '',
|
|
153
|
+
name,
|
|
154
|
+
args: {},
|
|
155
|
+
ph: "X" /* Types.TraceEvents.Phase.COMPLETE */,
|
|
156
|
+
pid,
|
|
157
|
+
tid,
|
|
158
|
+
ts,
|
|
159
|
+
dur: Types.Timing.MicroSeconds(0),
|
|
160
|
+
selfTime: Types.Timing.MicroSeconds(0),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
150
163
|
export function matchBeginningAndEndEvents(unpairedEvents) {
|
|
151
164
|
// map to store begin and end of the event
|
|
152
165
|
const matchedPairs = new Map();
|
|
@@ -177,7 +190,7 @@ function getSyntheticId(event) {
|
|
|
177
190
|
const id = extractId(event);
|
|
178
191
|
return id && `${event.cat}:${id}:${event.name}`;
|
|
179
192
|
}
|
|
180
|
-
export function createSortedSyntheticEvents(matchedPairs) {
|
|
193
|
+
export function createSortedSyntheticEvents(matchedPairs, syntheticEventCallback) {
|
|
181
194
|
const syntheticEvents = [];
|
|
182
195
|
for (const [id, eventsPair] of matchedPairs.entries()) {
|
|
183
196
|
const beginEvent = eventsPair.begin;
|
|
@@ -218,13 +231,14 @@ export function createSortedSyntheticEvents(matchedPairs) {
|
|
|
218
231
|
// crbug.com/1472375
|
|
219
232
|
continue;
|
|
220
233
|
}
|
|
234
|
+
syntheticEventCallback?.(event);
|
|
221
235
|
syntheticEvents.push(event);
|
|
222
236
|
}
|
|
223
237
|
return syntheticEvents.sort((a, b) => a.ts - b.ts);
|
|
224
238
|
}
|
|
225
|
-
export function createMatchedSortedSyntheticEvents(unpairedAsyncEvents) {
|
|
239
|
+
export function createMatchedSortedSyntheticEvents(unpairedAsyncEvents, syntheticEventCallback) {
|
|
226
240
|
const matchedPairs = matchBeginningAndEndEvents(unpairedAsyncEvents);
|
|
227
|
-
const syntheticEvents = createSortedSyntheticEvents(matchedPairs);
|
|
241
|
+
const syntheticEvents = createSortedSyntheticEvents(matchedPairs, syntheticEventCallback);
|
|
228
242
|
return syntheticEvents;
|
|
229
243
|
}
|
|
230
244
|
//# sourceMappingURL=Trace.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Trace.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\ntype MatchedPairType<T extends Types.TraceEvents.TraceEventPairableAsync> = Types.TraceEvents.SyntheticEventPair<T>;\nexport function stackTraceForEvent(event: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventCallFrame[]|\n null {\n if (Types.TraceEvents.isSyntheticInvalidation(event)) {\n return event.stackTrace || null;\n }\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n return null;\n}\n\nexport function extractOriginFromTrace(firstNavigationURL: string): string|null {\n const url = new URL(firstNavigationURL);\n if (url) {\n // We do this to save some space in the toolbar - seeing the `www` is less\n // useful than seeing `foo.com` if it's truncated at narrow widths\n if (url.host.startsWith('www.')) {\n return url.host.slice(4);\n }\n return url.host;\n }\n return null;\n}\n\nexport type EventsInThread<T extends Types.TraceEvents.TraceEventData> = Map<Types.TraceEvents.ThreadID, T[]>;\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nexport function addEventToProcessThread<T extends Types.TraceEvents.TraceEventData>(\n event: T,\n eventsInProcessThread: Map<Types.TraceEvents.ProcessID, EventsInThread<T>>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map<Types.TraceEvents.ThreadID, T[]>();\n }\n\n let events = eventsInThread.get(tid);\n if (!events) {\n events = [];\n }\n\n events.push(event);\n eventsInThread.set(event.tid, events);\n eventsInProcessThread.set(event.pid, eventsInThread);\n}\n\ntype TimeSpan = {\n ts: Types.Timing.MicroSeconds,\n dur?: Types.Timing.MicroSeconds,\n};\nfunction eventTimeComparator(a: TimeSpan, b: TimeSpan): -1|0|1 {\n const aBeginTime = a.ts;\n const bBeginTime = b.ts;\n if (aBeginTime < bBeginTime) {\n return -1;\n }\n if (aBeginTime > bBeginTime) {\n return 1;\n }\n const aDuration = a.dur ?? 0;\n const bDuration = b.dur ?? 0;\n const aEndTime = aBeginTime + aDuration;\n const bEndTime = bBeginTime + bDuration;\n if (aEndTime > bEndTime) {\n return -1;\n }\n if (aEndTime < bEndTime) {\n return 1;\n }\n return 0;\n}\n/**\n * Sorts all the events in place, in order, by their start time. If they have\n * the same start time, orders them by longest first.\n */\nexport function sortTraceEventsInPlace(events: {ts: Types.Timing.MicroSeconds, dur?: Types.Timing.MicroSeconds}[]):\n void {\n events.sort(eventTimeComparator);\n}\n\n/**\n * Returns an array of ordered events that results after merging the two\n * ordered input arrays.\n */\nexport function\nmergeEventsInOrder<T1 extends Types.TraceEvents.TraceEventData, T2 extends Types.TraceEvents.TraceEventData>(\n eventsArray1: T1[], eventsArray2: T2[]): (T1|T2)[] {\n const result = [];\n let i = 0;\n let j = 0;\n while (i < eventsArray1.length && j < eventsArray2.length) {\n const event1 = eventsArray1[i];\n const event2 = eventsArray2[j];\n const compareValue = eventTimeComparator(event1, event2);\n if (compareValue <= 0) {\n result.push(event1);\n i++;\n }\n if (compareValue === 1) {\n result.push(event2);\n j++;\n }\n }\n while (i < eventsArray1.length) {\n result.push(eventsArray1[i++]);\n }\n while (j < eventsArray2.length) {\n result.push(eventsArray2[j++]);\n }\n return result;\n}\n\nexport function getNavigationForTraceEvent(\n event: Types.TraceEvents.TraceEventData,\n eventFrameId: string,\n navigationsByFrameId: Map<string, Types.TraceEvents.TraceEventNavigationStart[]>,\n ): Types.TraceEvents.TraceEventNavigationStart|null {\n const navigations = navigationsByFrameId.get(eventFrameId);\n if (!navigations || eventFrameId === '') {\n // This event's navigation has been filtered out by the meta handler as a noise event\n // or contains an empty frameId.\n return null;\n }\n\n const eventNavigationIndex =\n Platform.ArrayUtilities.nearestIndexFromEnd(navigations, navigation => navigation.ts <= event.ts);\n\n if (eventNavigationIndex === null) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigations[eventNavigationIndex];\n}\n\nexport function extractId(event: Types.TraceEvents.TraceEventPairableAsync|\n MatchedPairType<Types.TraceEvents.TraceEventPairableAsync>): string|undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.MicroSeconds,\n rendererProcessesByFrame:\n Map<string,\n Map<Types.TraceEvents.ProcessID,\n {frame: Types.TraceEvents.TraceFrame, window: Types.Timing.TraceWindowMicroSeconds}[]>>): string|null {\n const processData = rendererProcessesByFrame.get(frameId);\n if (!processData) {\n return null;\n }\n for (const processes of processData.values()) {\n for (const processInfo of processes) {\n if (processInfo.window.min > time || processInfo.window.max < time) {\n continue;\n }\n return processInfo.frame.url;\n }\n }\n return null;\n}\n\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, ts: Types.Timing.MicroSeconds, pid: Types.TraceEvents.ProcessID,\n tid: Types.TraceEvents.ThreadID): Types.TraceEvents.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.MicroSeconds(0),\n selfTime: Types.Timing.MicroSeconds(0),\n callFrame: node.callFrame,\n };\n}\n\nexport function matchBeginningAndEndEvents(unpairedEvents: Types.TraceEvents.TraceEventPairableAsync[]): Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n}> {\n // map to store begin and end of the event\n const matchedPairs: Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n }> = new Map();\n\n // looking for start and end\n for (const event of unpairedEvents) {\n const syntheticId = getSyntheticId(event);\n if (syntheticId === undefined) {\n continue;\n }\n // Create a synthetic id to prevent collisions across categories.\n // Console timings can be dispatched with the same id, so use the\n // event name as well to generate unique ids.\n const otherEventsWithID = Platform.MapUtilities.getWithDefault(matchedPairs, syntheticId, () => {\n return {begin: null, end: null};\n });\n\n const isStartEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_END;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.TraceEvents.TraceEventPairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.TraceEvents.TraceEventPairableAsyncEnd;\n }\n }\n\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.TraceEvents.TraceEventPairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents<T extends Types.TraceEvents.TraceEventPairableAsync>(\n matchedPairs: Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n }>): MatchedPairType<T>[] {\n const syntheticEvents: MatchedPairType<T>[] = [];\n for (const [id, eventsPair] of matchedPairs.entries()) {\n const beginEvent = eventsPair.begin;\n const endEvent = eventsPair.end;\n if (!beginEvent || !endEvent) {\n // This should never happen, the backend only creates the events once it\n // has them both, so we should never get into this state.\n // If we do, something is very wrong, so let's just drop that problematic event.\n continue;\n }\n const pair = {beginEvent, endEvent};\n function eventsArePairable(data: {\n beginEvent: Types.TraceEvents.TraceEventPairableAsyncBegin,\n endEvent: Types.TraceEvents.TraceEventPairableAsyncEnd,\n }): data is MatchedPairType<T>['args']['data'] {\n return Boolean(getSyntheticId(data.beginEvent)) &&\n getSyntheticId(data.beginEvent) === getSyntheticId(data.endEvent);\n }\n if (!eventsArePairable(pair)) {\n continue;\n }\n const event: MatchedPairType<T> = {\n cat: endEvent.cat,\n ph: endEvent.ph,\n pid: endEvent.pid,\n tid: endEvent.tid,\n id,\n // Both events have the same name, so it doesn't matter which we pick to\n // use as the description\n name: beginEvent.name,\n dur: Types.Timing.MicroSeconds(endEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: pair,\n },\n };\n\n if (event.dur < 0) {\n // We have seen in the backend that sometimes animation events get\n // generated with multiple begin entries, or multiple end entries, and this\n // can cause invalid data on the performance panel, so we drop them.\n // crbug.com/1472375\n continue;\n }\n syntheticEvents.push(event);\n }\n return syntheticEvents.sort((a, b) => a.ts - b.ts);\n}\n\nexport function createMatchedSortedSyntheticEvents<T extends Types.TraceEvents.TraceEventPairableAsync>(\n unpairedAsyncEvents: T[]): MatchedPairType<T>[] {\n const matchedPairs = matchBeginningAndEndEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents<T>(matchedPairs);\n return syntheticEvents;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Trace.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\ntype MatchedPairType<T extends Types.TraceEvents.TraceEventPairableAsync> = Types.TraceEvents.SyntheticEventPair<T>;\nexport function stackTraceForEvent(event: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventCallFrame[]|\n null {\n if (Types.TraceEvents.isSyntheticInvalidation(event)) {\n return event.stackTrace || null;\n }\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n return null;\n}\n\nexport function extractOriginFromTrace(firstNavigationURL: string): string|null {\n const url = new URL(firstNavigationURL);\n if (url) {\n // We do this to save some space in the toolbar - seeing the `www` is less\n // useful than seeing `foo.com` if it's truncated at narrow widths\n if (url.host.startsWith('www.')) {\n return url.host.slice(4);\n }\n return url.host;\n }\n return null;\n}\n\nexport type EventsInThread<T extends Types.TraceEvents.TraceEventData> = Map<Types.TraceEvents.ThreadID, T[]>;\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nexport function addEventToProcessThread<T extends Types.TraceEvents.TraceEventData>(\n event: T,\n eventsInProcessThread: Map<Types.TraceEvents.ProcessID, EventsInThread<T>>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map<Types.TraceEvents.ThreadID, T[]>();\n }\n\n let events = eventsInThread.get(tid);\n if (!events) {\n events = [];\n }\n\n events.push(event);\n eventsInThread.set(event.tid, events);\n eventsInProcessThread.set(event.pid, eventsInThread);\n}\n\ntype TimeSpan = {\n ts: Types.Timing.MicroSeconds,\n dur?: Types.Timing.MicroSeconds,\n};\nfunction eventTimeComparator(a: TimeSpan, b: TimeSpan): -1|0|1 {\n const aBeginTime = a.ts;\n const bBeginTime = b.ts;\n if (aBeginTime < bBeginTime) {\n return -1;\n }\n if (aBeginTime > bBeginTime) {\n return 1;\n }\n const aDuration = a.dur ?? 0;\n const bDuration = b.dur ?? 0;\n const aEndTime = aBeginTime + aDuration;\n const bEndTime = bBeginTime + bDuration;\n if (aEndTime > bEndTime) {\n return -1;\n }\n if (aEndTime < bEndTime) {\n return 1;\n }\n return 0;\n}\n/**\n * Sorts all the events in place, in order, by their start time. If they have\n * the same start time, orders them by longest first.\n */\nexport function sortTraceEventsInPlace(events: {ts: Types.Timing.MicroSeconds, dur?: Types.Timing.MicroSeconds}[]):\n void {\n events.sort(eventTimeComparator);\n}\n\n/**\n * Returns an array of ordered events that results after merging the two\n * ordered input arrays.\n */\nexport function\nmergeEventsInOrder<T1 extends Types.TraceEvents.TraceEventData, T2 extends Types.TraceEvents.TraceEventData>(\n eventsArray1: readonly T1[], eventsArray2: readonly T2[]): (T1|T2)[] {\n const result = [];\n let i = 0;\n let j = 0;\n while (i < eventsArray1.length && j < eventsArray2.length) {\n const event1 = eventsArray1[i];\n const event2 = eventsArray2[j];\n const compareValue = eventTimeComparator(event1, event2);\n if (compareValue <= 0) {\n result.push(event1);\n i++;\n }\n if (compareValue === 1) {\n result.push(event2);\n j++;\n }\n }\n while (i < eventsArray1.length) {\n result.push(eventsArray1[i++]);\n }\n while (j < eventsArray2.length) {\n result.push(eventsArray2[j++]);\n }\n return result;\n}\n\nexport function getNavigationForTraceEvent(\n event: Types.TraceEvents.TraceEventData,\n eventFrameId: string,\n navigationsByFrameId: Map<string, Types.TraceEvents.TraceEventNavigationStart[]>,\n ): Types.TraceEvents.TraceEventNavigationStart|null {\n const navigations = navigationsByFrameId.get(eventFrameId);\n if (!navigations || eventFrameId === '') {\n // This event's navigation has been filtered out by the meta handler as a noise event\n // or contains an empty frameId.\n return null;\n }\n\n const eventNavigationIndex =\n Platform.ArrayUtilities.nearestIndexFromEnd(navigations, navigation => navigation.ts <= event.ts);\n\n if (eventNavigationIndex === null) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigations[eventNavigationIndex];\n}\n\nexport function extractId(event: Types.TraceEvents.TraceEventPairableAsync|\n MatchedPairType<Types.TraceEvents.TraceEventPairableAsync>): string|undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.MicroSeconds,\n rendererProcessesByFrame:\n Map<string,\n Map<Types.TraceEvents.ProcessID,\n {frame: Types.TraceEvents.TraceFrame, window: Types.Timing.TraceWindowMicroSeconds}[]>>): string|null {\n const processData = rendererProcessesByFrame.get(frameId);\n if (!processData) {\n return null;\n }\n for (const processes of processData.values()) {\n for (const processInfo of processes) {\n if (processInfo.window.min > time || processInfo.window.max < time) {\n continue;\n }\n return processInfo.frame.url;\n }\n }\n return null;\n}\n\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, ts: Types.Timing.MicroSeconds, pid: Types.TraceEvents.ProcessID,\n tid: Types.TraceEvents.ThreadID): Types.TraceEvents.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.MicroSeconds(0),\n selfTime: Types.Timing.MicroSeconds(0),\n callFrame: node.callFrame,\n };\n}\n\nexport function makeSyntheticTraceEntry(\n name: string, ts: Types.Timing.MicroSeconds, pid: Types.TraceEvents.ProcessID,\n tid: Types.TraceEvents.ThreadID): Types.TraceEvents.SyntheticTraceEntry {\n return {\n cat: '',\n name,\n args: {},\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.MicroSeconds(0),\n selfTime: Types.Timing.MicroSeconds(0),\n };\n}\n\nexport function matchBeginningAndEndEvents(unpairedEvents: Types.TraceEvents.TraceEventPairableAsync[]): Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n}> {\n // map to store begin and end of the event\n const matchedPairs: Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n }> = new Map();\n\n // looking for start and end\n for (const event of unpairedEvents) {\n const syntheticId = getSyntheticId(event);\n if (syntheticId === undefined) {\n continue;\n }\n // Create a synthetic id to prevent collisions across categories.\n // Console timings can be dispatched with the same id, so use the\n // event name as well to generate unique ids.\n const otherEventsWithID = Platform.MapUtilities.getWithDefault(matchedPairs, syntheticId, () => {\n return {begin: null, end: null};\n });\n\n const isStartEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_END;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.TraceEvents.TraceEventPairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.TraceEvents.TraceEventPairableAsyncEnd;\n }\n }\n\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.TraceEvents.TraceEventPairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents<T extends Types.TraceEvents.TraceEventPairableAsync>(\n matchedPairs: Map<string, {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd | null,\n }>,\n syntheticEventCallback?: (syntheticEvent: MatchedPairType<T>) => void,\n ): MatchedPairType<T>[] {\n const syntheticEvents: MatchedPairType<T>[] = [];\n for (const [id, eventsPair] of matchedPairs.entries()) {\n const beginEvent = eventsPair.begin;\n const endEvent = eventsPair.end;\n if (!beginEvent || !endEvent) {\n // This should never happen, the backend only creates the events once it\n // has them both, so we should never get into this state.\n // If we do, something is very wrong, so let's just drop that problematic event.\n continue;\n }\n const pair = {beginEvent, endEvent};\n function eventsArePairable(data: {\n beginEvent: Types.TraceEvents.TraceEventPairableAsyncBegin,\n endEvent: Types.TraceEvents.TraceEventPairableAsyncEnd,\n }): data is MatchedPairType<T>['args']['data'] {\n return Boolean(getSyntheticId(data.beginEvent)) &&\n getSyntheticId(data.beginEvent) === getSyntheticId(data.endEvent);\n }\n if (!eventsArePairable(pair)) {\n continue;\n }\n const event: MatchedPairType<T> = {\n cat: endEvent.cat,\n ph: endEvent.ph,\n pid: endEvent.pid,\n tid: endEvent.tid,\n id,\n // Both events have the same name, so it doesn't matter which we pick to\n // use as the description\n name: beginEvent.name,\n dur: Types.Timing.MicroSeconds(endEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: pair,\n },\n };\n\n if (event.dur < 0) {\n // We have seen in the backend that sometimes animation events get\n // generated with multiple begin entries, or multiple end entries, and this\n // can cause invalid data on the performance panel, so we drop them.\n // crbug.com/1472375\n continue;\n }\n syntheticEventCallback?.(event);\n syntheticEvents.push(event);\n }\n return syntheticEvents.sort((a, b) => a.ts - b.ts);\n}\n\nexport function createMatchedSortedSyntheticEvents<T extends Types.TraceEvents.TraceEventPairableAsync>(\n unpairedAsyncEvents: T[],\n syntheticEventCallback?: (syntheticEvent: MatchedPairType<T>) => void): MatchedPairType<T>[] {\n const matchedPairs = matchBeginningAndEndEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents<T>(matchedPairs, syntheticEventCallback);\n return syntheticEvents;\n}\n"]}
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"useUnknownInCatchVariables": false
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
+
"../../../../../../../front_end/models/trace/helpers/Extensions.ts",
|
|
32
33
|
"../../../../../../../front_end/models/trace/helpers/SamplesIntegrator.ts",
|
|
33
34
|
"../../../../../../../front_end/models/trace/helpers/Timing.ts",
|
|
34
35
|
"../../../../../../../front_end/models/trace/helpers/Trace.ts",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2022 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
|
+
export * as Extensions from './Extensions.js';
|
|
4
5
|
export * as SamplesIntegrator from './SamplesIntegrator.js';
|
|
5
6
|
export * as Timing from './Timing.js';
|
|
6
7
|
export * as Trace from './Trace.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/helpers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as SamplesIntegrator from './SamplesIntegrator.js';\nexport * as Timing from './Timing.js';\nexport * as Trace from './Trace.js';\nexport * as TreeHelpers from './TreeHelpers.js';\n"]}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/helpers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Extensions from './Extensions.js';\nexport * as SamplesIntegrator from './SamplesIntegrator.js';\nexport * as Timing from './Timing.js';\nexport * as Trace from './Trace.js';\nexport * as TreeHelpers from './TreeHelpers.js';\n"]}
|
|
@@ -31,9 +31,13 @@ export interface LayoutShiftRootCausesData {
|
|
|
31
31
|
renderBlockingRequests: RenderBlockingRequest[];
|
|
32
32
|
scriptStackTrace: Types.TraceEvents.TraceEventCallFrame[];
|
|
33
33
|
}
|
|
34
|
+
interface Options {
|
|
35
|
+
/** Checking iframe root causes can be an expensive operation, so it is disabled by default. */
|
|
36
|
+
enableIframeRootCauses?: boolean;
|
|
37
|
+
}
|
|
34
38
|
export declare class LayoutShiftRootCauses {
|
|
35
39
|
#private;
|
|
36
|
-
constructor(protocolInterface: RootCauseProtocolInterface);
|
|
40
|
+
constructor(protocolInterface: RootCauseProtocolInterface, options?: Options);
|
|
37
41
|
/**
|
|
38
42
|
* Calculates the potential root causes for a given layout shift event. Once
|
|
39
43
|
* calculated, this data is cached.
|
|
@@ -73,6 +77,7 @@ export declare class LayoutShiftRootCauses {
|
|
|
73
77
|
* because a node, which is an ancestor to an iframe, was injected.
|
|
74
78
|
*/
|
|
75
79
|
getIframeRootCause(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe | null>;
|
|
80
|
+
getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node | null>;
|
|
76
81
|
/**
|
|
77
82
|
* Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a
|
|
78
83
|
* 500ms window before the layout invalidation.
|
|
@@ -117,3 +122,4 @@ export declare class LayoutShiftRootCauses {
|
|
|
117
122
|
*/
|
|
118
123
|
getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions>;
|
|
119
124
|
}
|
|
125
|
+
export {};
|
|
@@ -40,8 +40,11 @@ function networkRequestIsRenderBlockingInFrame(event, frameId) {
|
|
|
40
40
|
export class LayoutShiftRootCauses {
|
|
41
41
|
#protocolInterface;
|
|
42
42
|
#rootCauseCacheMap = new Map();
|
|
43
|
-
|
|
43
|
+
#nodeDetailsCache = new Map();
|
|
44
|
+
#iframeRootCausesEnabled;
|
|
45
|
+
constructor(protocolInterface, options) {
|
|
44
46
|
this.#protocolInterface = protocolInterface;
|
|
47
|
+
this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Calculates the potential root causes for a given layout shift event. Once
|
|
@@ -217,7 +220,7 @@ export class LayoutShiftRootCauses {
|
|
|
217
220
|
if (layoutInvalidation.args.data.reason !== "Size changed" /* Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED */) {
|
|
218
221
|
return null;
|
|
219
222
|
}
|
|
220
|
-
const layoutInvalidationNode = await this
|
|
223
|
+
const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);
|
|
221
224
|
if (!layoutInvalidationNode) {
|
|
222
225
|
return null;
|
|
223
226
|
}
|
|
@@ -238,12 +241,15 @@ export class LayoutShiftRootCauses {
|
|
|
238
241
|
* because a node, which is an ancestor to an iframe, was injected.
|
|
239
242
|
*/
|
|
240
243
|
async getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId) {
|
|
241
|
-
if (
|
|
244
|
+
if (!this.#iframeRootCausesEnabled) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&
|
|
242
248
|
layoutInvalidation.args.data.reason !== "Style changed" /* Types.TraceEvents.LayoutInvalidationReason.STYLE_CHANGED */ &&
|
|
243
249
|
layoutInvalidation.args.data.reason !== "Added to layout" /* Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT */) {
|
|
244
250
|
return null;
|
|
245
251
|
}
|
|
246
|
-
const layoutInvalidationNode = await this
|
|
252
|
+
const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);
|
|
247
253
|
if (!layoutInvalidationNode) {
|
|
248
254
|
return null;
|
|
249
255
|
}
|
|
@@ -253,6 +259,15 @@ export class LayoutShiftRootCauses {
|
|
|
253
259
|
}
|
|
254
260
|
return { iframe };
|
|
255
261
|
}
|
|
262
|
+
async getNodeDetails(nodeId) {
|
|
263
|
+
let nodeDetails = this.#nodeDetailsCache.get(nodeId);
|
|
264
|
+
if (nodeDetails !== undefined) {
|
|
265
|
+
return nodeDetails;
|
|
266
|
+
}
|
|
267
|
+
nodeDetails = await this.#protocolInterface.getNode(nodeId);
|
|
268
|
+
this.#nodeDetailsCache.set(nodeId, nodeDetails);
|
|
269
|
+
return nodeDetails;
|
|
270
|
+
}
|
|
256
271
|
/**
|
|
257
272
|
* Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a
|
|
258
273
|
* 500ms window before the layout invalidation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.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 Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport {type TraceParseData} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type RootCauseProtocolInterface} from './RootCauses.js';\n\nexport type CSSDimensions = {\n width?: string,\n height?: string,\n aspectRatio?: string,\n};\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.TraceEvents.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.TraceEvents.TraceEventCallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, FontChange[]|null>();\nconst renderBlocksByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, RenderBlockingRequest[]|null>();\n\nfunction setDefaultValue(\n map: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>,\n shift: Types.TraceEvents.TraceEventLayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\n// Important: we purposefully treat `potentially_blocking` as\n// non-render-blocking here because:\n// 1. An async script can run on the main thread at any point, including before\n// the page is loaded\n// 2. An async script will never block the parsing and rendering process of the\n// browser.\n// 3. Therefore, from a developer's point of view, there is nothing more they\n// can do if they've put `async` on, and within the context of Insights, we\n// shouldn't report an async script as render blocking.\n// In the future we may want to consider suggesting the use of `defer` over\n// `async`, as it doesn't have this concern, but for now we'll allow `async`\n// and not report it as an issue.\nconst NON_RENDER_BLOCKING_VALUES = new Set<Types.TraceEvents.RenderBlocking>([\n 'non_blocking',\n 'potentially_blocking',\n]);\nfunction networkRequestIsRenderBlockingInFrame(\n event: Types.TraceEvents.SyntheticNetworkRequest, frameId: string): boolean {\n const isRenderBlocking = !NON_RENDER_BLOCKING_VALUES.has(event.args.data.renderBlocking);\n return isRenderBlocking && event.args.data.frame === frameId;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>();\n\n constructor(protocolInterface: RootCauseProtocolInterface) {\n this.#protocolInterface = protocolInterface;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift):\n Promise<Readonly<LayoutShiftRootCausesData>|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n modelData: TraceParseData,\n ): Promise<void> {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): Promise<void> {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation: Array<Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking> =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map<Protocol.DOM.BackendNodeId, Protocol.DOM.NodeId>();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined &&\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.TraceEvents.KnownEventName;\n return knownName === Types.TraceEvents.KnownEventName.Layout;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<UnsizedMedia|null> {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.#protocolInterface.getNode(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe|null> {\n if (layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.#protocolInterface.getNode(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n modelData: TraceParseData): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions> {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map<string, string>): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map<string, string>): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map<string, string>): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map<string, string>): Promise<boolean> {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAG/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAuC3C,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA2D,CAAC;AAClG,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAsE,CAAC;AAE7G,SAAS,eAAe,CACpB,GAA4E,EAC5E,KAA8C;IAChD,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;QACpD,OAAO;YACL,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,WAAW,EAAE,EAAE;YACf,sBAAsB,EAAE,EAAE;YAC1B,gBAAgB,EAAE,EAAE;SACrB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6DAA6D;AAC7D,oCAAoC;AACpC,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAC/E,cAAc;AACd,6EAA6E;AAC7E,8EAA8E;AAC9E,0DAA0D;AAC1D,2EAA2E;AAC3E,4EAA4E;AAC5E,iCAAiC;AACjC,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAmC;IAC3E,cAAc;IACd,sBAAsB;CACvB,CAAC,CAAC;AACH,SAAS,qCAAqC,CAC1C,KAAgD,EAAE,OAAe;IACnE,MAAM,gBAAgB,GAAG,CAAC,0BAA0B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzF,OAAO,gBAAgB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC;AAC/D,CAAC;AAOD,MAAM,OAAO,qBAAqB;IAChC,kBAAkB,CAA6B;IAC/C,kBAAkB,GAAG,IAAI,GAAG,EAAsE,CAAC;IACnG,iBAAiB,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,wBAAwB,CAAU;IAElC,YAAY,iBAA6C,EAAE,OAAiB;QAC1E,IAAI,CAAC,kBAAkB,GAAG,iBAAiB,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,OAAO,EAAE,sBAAsB,IAAI,KAAK,CAAC;IAC3E,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAyB,EAAE,KAA8C;QAEhG,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3F,sFAAsF;QACtF,oFAAoF;QACpF,uDAAuD;QACvD,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;QAElF,qBAAqB;QACrB,MAAM,IAAI,CAAC,WAAW,CAClB,eAAe,EACf,SAAS,CACZ,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,kDAAkD;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACb,YAAuD,EACvD,SAAyB;QAE3B,MAAM,IAAI,CAAC,+BAA+B,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,wBAAwB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,+BAA+B,CACjC,YAAuD,EAAE,SAAyB;QACpF,MAAM,EAAC,cAAc,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,cAAc,EAAC,GAC7F,SAAS,CAAC,YAAY,CAAC;QAE3B,mEAAmE;QACnE,iDAAiD;QACjD,uEAAuE;QACvE,6BAA6B;QAC7B,MAAM,2BAA2B,GAE7B,CAAC,GAAG,wBAAwB,EAAE,GAAG,+BAA+B,CAAC,CAAC;QAEtE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,cAAc,CAAC,CAAC;QAC5F,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAmD,CAAC;QACzF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,qBAAqB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,sEAAsE;QACtE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QACjF,KAAK,MAAM,kBAAkB,IAAI,2BAA2B,EAAE,CAAC;YAC7D,yFAAyF;YACzF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACrG,MAAM,oBAAoB,GAAG,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACvG,MAAM,wBAAwB,GAAG,qBAAqB,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChG,IAAI,qBAAqB,GAAsB,IAAI,CAAC;YACpD,IAAI,eAAe,GAAwB,IAAI,CAAC;YAChD,IAAI,wBAAwB,KAAK,SAAS;gBACtC,KAAK,CAAC,WAAW,CAAC,sCAAsC,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACjF,qBAAqB,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;gBAC1G,eAAe,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;YAChG,CAAC;YAED,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,IAAI,CAAC,mBAAmB,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAChG,SAAS;YACX,CAAC;YAED,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,qBAAqB;oBACrB,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,qBAAqB,EAAE,IAAI,CAAC,MAAM,CAAC;oBACxG,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC5D,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;gBAC9D,CAAC;gBACD,IAAI,eAAe;oBACf,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAC5B,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3F,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,mBAAmB,EAAE,CAAC;oBACxB,0EAA0E;oBAC1E,yEAAyE;oBACzE,SAAS;oBACT,kBAAkB,CAAC,WAAW,GAAG,mBAAmB,CAAC;gBACvD,CAAC;gBACD,IAAI,oBAAoB,EAAE,CAAC;oBACzB,kBAAkB,CAAC,sBAAsB,GAAG,oBAAoB,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,wBAAwB,CAAC,YAAuD,EAAE,SAAyB;QACzG,MAAM,EAAC,cAAc,EAAC,GAAG,SAAS,CAAC,YAAY,CAAC;QAChD,sEAAsE;QACtE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAEjF,MAAM,mBAAmB,GAAG,CAAC,EAAC,IAAI,EAAiB,EAAW,EAAE;YAC9D,MAAM,SAAS,GAAG,IAAwC,CAAC;YAC3D,OAAO,SAAS,2DAA4C,CAAC;QAC/D,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpF,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,6EAA6E;YAC7E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClG,MAAM,UAAU,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC;YACrD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrD,kBAAkB,CAAC,gBAAgB,GAAG,UAAU,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC1B,kBAA0E,EAC1E,wBAA6C;QAC/C,iCAAiC;QACjC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,iFAA4D,EAAE,CAAC;YACpG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,cAAc,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YAC1F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;QACxF,IAAI,qBAAqB,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3F,OAAO,EAAC,IAAI,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,EAAC,CAAC;IAChF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CACpB,kBAA0E,EAC1E,wBAA6C;QAC/C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC;YAC5D,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,mFAA6D;YAChG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,uFAA+D,EAAE,CAAC;YACvG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAC,MAAM,EAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAA2B;QAC9C,IAAI,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,4BAA4B,CACxB,kBAC6D,EAC7D,SAAyB;QAC3B,MAAM,uBAAuB,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACnF,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,OAAO,WAAW,GAAG,WAAW,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAChE,uBAAuB,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC1F,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,MAAM,4BAA4B,GAAuB,EAAE,CAAC;QAE5D,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,eAAe,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,sBAAsB,GAAG,eAAe,CAAC,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC;YACxE,IAAI,kBAAkB,CAAC,EAAE,GAAG,sBAAsB,GAAG,0BAA0B,EAAE,CAAC;gBAChF,MAAM,2BAA2B,GAAqB,EAAC,OAAO,EAAE,eAAe,EAAC,CAAC;gBAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,CAC5D,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC,CAAC;gBACtE,2BAA2B,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,CAAC;gBAC/D,4BAA4B,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,2CAA2C;gBAC3C,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,4BAA4B,CAAC;IACtC,CAAC;IAED;;;;;;;;OAQG;IACH,sBAAsB,CAClB,kBAC6D,EAC7D,YAAkD,EAAE,SAAyB;QAC/E,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,mFAA6D,EAAE,CAAC;YACrG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mFAAmF;QACnF,MAAM,uBAAuB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACzE,IAAI,uBAAuB,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,uBAAuB,CAAC;QACjC,CAAC;QAED,MAAM,0BAA0B,GAC5B,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QAC/G,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,mCAAmC,CAAC,4BAAgD;QAClF,MAAM,YAAY,GAAiB,EAAE,CAAC;QAEtC,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAe,CAAC;YAClE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9F,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBACrD,iEAAiE;gBACjE,oEAAoE;gBACpE,uCAAuC;gBACvC,SAAS;YACX,CAAC;YACD,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,uBAAuB,CACnB,kBAC6D,EAC7D,YAAkD,EAAE,SAAyB;QAC/E,mFAAmF;QACnF,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACxE,IAAI,sBAAsB,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,sBAAsB,CAAC;QAChC,CAAC;QAED,MAAM,0BAA0B,GAC5B,0CAA0C,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QACjH,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,+BAA+B,CAAC,IAAuB;QAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,SAAS,sBAAsB,CAAC,WAAmB;YACjD,IAAI,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,QAAQ,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;gBACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;gBAC9E,IAAI,IAAI,EAAE,CAAC;oBACT,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,IAAI,GAAG,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,yBAAyB,CAAC,IAAuB;QACrD,MAAM,kBAAkB,GAAkB,EAAE,CAAC;QAE7C,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC3B,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,UAAU,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,EAAC,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpG,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QAElG,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;QAElF,IAAI,UAAU,IAAI,SAAS,IAAI,sBAAsB,EAAE,CAAC;YACtD,OAAO,EAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;QACjG,CAAC;QAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;QAC/D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;QAC7D,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;IACnF,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,0CAA0C,CAAC,4BAAgD;IAElG,MAAM,sBAAsB,GAA4B,EAAE,CAAC;IAE3D,qDAAqD;IACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5E,IAAI,CAAC,qCAAqC,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YACjG,SAAS;QACX,CAAC;QACD,sBAAsB,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAA0B,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAuB;IACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,aAAa,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,aAAqB;IACvD,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAqB;IACpD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,8BAA8B,CAAC,aAAkC;IACxE,MAAM,aAAa,GAAG,oBAAoB,CAAC;IAC3C,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9D,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,6BAA6B,CAAC,aAAkC;IACvE,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,UAAU,CAAC;AACzD,CAAC;AAED,SAAS,yBAAyB,CAAC,aAAkC;IACnE,MAAM,kBAAkB,GAAkB,EAAE,CAAC;IAC7C,kBAAkB,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,kBAAkB,CAAC,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,kBAAkB,CAAC,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnE,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,IAAuB,EAAE,aAAkC;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACjC,MAAM,iBAAiB,GAAG,8BAA8B,CAAC,aAAa,CAAC,CAAC;IACxE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvE,uBAAuB;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;IAC7D,OAAO,CAAC,OAAO,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,UAAyB;IACtD,MAAM,EAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAC,GAAG,UAAU,CAAC;IAEhD,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,IAAI,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,IAAI,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,IAAI,0BAA0B,CAAC,WAAW,CAAC,CAAC,CAAC;IAE5F,MAAM,cAAc,GAAG,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,mBAAmB,CAAC;IAChF,OAAO,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,cAAc,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAC9B,YAAuD,EACvD,cAAsD;IAExD,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAmF,CAAC;IAEpH,wDAAwD;IACxD,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;QAC3G,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7B,mEAAmE;YACnE,SAAS;QACX,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACrF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACpD,8DAA8D;gBAC9D,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,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 Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport {type TraceParseData} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type RootCauseProtocolInterface} from './RootCauses.js';\n\nexport type CSSDimensions = {\n width?: string,\n height?: string,\n aspectRatio?: string,\n};\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.TraceEvents.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.TraceEvents.TraceEventCallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, FontChange[]|null>();\nconst renderBlocksByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, RenderBlockingRequest[]|null>();\n\nfunction setDefaultValue(\n map: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>,\n shift: Types.TraceEvents.TraceEventLayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\n// Important: we purposefully treat `potentially_blocking` as\n// non-render-blocking here because:\n// 1. An async script can run on the main thread at any point, including before\n// the page is loaded\n// 2. An async script will never block the parsing and rendering process of the\n// browser.\n// 3. Therefore, from a developer's point of view, there is nothing more they\n// can do if they've put `async` on, and within the context of Insights, we\n// shouldn't report an async script as render blocking.\n// In the future we may want to consider suggesting the use of `defer` over\n// `async`, as it doesn't have this concern, but for now we'll allow `async`\n// and not report it as an issue.\nconst NON_RENDER_BLOCKING_VALUES = new Set<Types.TraceEvents.RenderBlocking>([\n 'non_blocking',\n 'potentially_blocking',\n]);\nfunction networkRequestIsRenderBlockingInFrame(\n event: Types.TraceEvents.SyntheticNetworkRequest, frameId: string): boolean {\n const isRenderBlocking = !NON_RENDER_BLOCKING_VALUES.has(event.args.data.renderBlocking);\n return isRenderBlocking && event.args.data.frame === frameId;\n}\n\ninterface Options {\n /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */\n enableIframeRootCauses?: boolean;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>();\n #nodeDetailsCache = new Map<Protocol.DOM.NodeId, Protocol.DOM.Node|null>();\n #iframeRootCausesEnabled: boolean;\n\n constructor(protocolInterface: RootCauseProtocolInterface, options?: Options) {\n this.#protocolInterface = protocolInterface;\n this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift):\n Promise<Readonly<LayoutShiftRootCausesData>|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n modelData: TraceParseData,\n ): Promise<void> {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): Promise<void> {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation: Array<Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking> =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map<Protocol.DOM.BackendNodeId, Protocol.DOM.NodeId>();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined &&\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.TraceEvents.KnownEventName;\n return knownName === Types.TraceEvents.KnownEventName.Layout;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<UnsizedMedia|null> {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe|null> {\n if (!this.#iframeRootCausesEnabled) {\n return null;\n }\n\n if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n async getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node|null> {\n let nodeDetails = this.#nodeDetailsCache.get(nodeId);\n if (nodeDetails !== undefined) {\n return nodeDetails;\n }\n\n nodeDetails = await this.#protocolInterface.getNode(nodeId);\n this.#nodeDetailsCache.set(nodeId, nodeDetails);\n\n return nodeDetails;\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n modelData: TraceParseData): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions> {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map<string, string>): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map<string, string>): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map<string, string>): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map<string, string>): Promise<boolean> {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RootCauses.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/RootCauses.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAWvD,MAAM,OAAO,UAAU;IACZ,YAAY,CAAwB;IAE7C,YAAY,iBAA6C;QACvD,IAAI,CAAC,YAAY,GAAG,IAAI,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;IACnE,CAAC;CACF","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 type * as Protocol from '../../../generated/protocol.js';\n\nimport {LayoutShiftRootCauses} from './LayoutShift.js';\n\nexport type RootCauseProtocolInterface = {\n getInitiatorForRequest(url: string): Protocol.Network.Initiator|null,\n pushNodesByBackendIdsToFrontend(backendNodeIds: Protocol.DOM.BackendNodeId[]): Promise<Protocol.DOM.NodeId[]>,\n getNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node|null>,\n getComputedStyleForNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.CSS.CSSComputedStyleProperty[]>,\n getMatchedStylesForNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.CSS.GetMatchedStylesForNodeResponse>,\n fontFaceForSource(url: string): Protocol.CSS.FontFace|undefined,\n};\n\nexport class RootCauses {\n readonly layoutShifts: LayoutShiftRootCauses;\n\n constructor(protocolInterface: RootCauseProtocolInterface) {\n this.layoutShifts = new LayoutShiftRootCauses(protocolInterface);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RootCauses.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/RootCauses.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAWvD,MAAM,OAAO,UAAU;IACZ,YAAY,CAAwB;IAE7C,YAAY,iBAA6C;QACvD,IAAI,CAAC,YAAY,GAAG,IAAI,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;IACnE,CAAC;CACF;AAED,OAAO,EAAC,qBAAqB,EAAC,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\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {LayoutShiftRootCauses} from './LayoutShift.js';\n\nexport type RootCauseProtocolInterface = {\n getInitiatorForRequest(url: string): Protocol.Network.Initiator|null,\n pushNodesByBackendIdsToFrontend(backendNodeIds: Protocol.DOM.BackendNodeId[]): Promise<Protocol.DOM.NodeId[]>,\n getNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node|null>,\n getComputedStyleForNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.CSS.CSSComputedStyleProperty[]>,\n getMatchedStylesForNode(nodeId: Protocol.DOM.NodeId): Promise<Protocol.CSS.GetMatchedStylesForNodeResponse>,\n fontFaceForSource(url: string): Protocol.CSS.FontFace|undefined,\n};\n\nexport class RootCauses {\n readonly layoutShifts: LayoutShiftRootCauses;\n\n constructor(protocolInterface: RootCauseProtocolInterface) {\n this.layoutShifts = new LayoutShiftRootCauses(protocolInterface);\n }\n}\n\nexport {LayoutShiftRootCauses} from './LayoutShift.js';\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type SyntheticTraceEntry, type TraceEventArgs, type TraceEventData } from './TraceEvents.js';
|
|
2
|
+
export declare const enum ExtensionEntryType {
|
|
3
|
+
TRACK_ENTRY = "track-entry",
|
|
4
|
+
MARKER = "marker"
|
|
5
|
+
}
|
|
6
|
+
declare const extensionPalette: readonly ["primary", "primary-light", "primary-dark", "secondary", "secondary-light", "secondary-dark", "tertiary", "tertiary-light", "tertiary-dark", "error"];
|
|
7
|
+
export type ExtensionColorFromPalette = typeof extensionPalette[number];
|
|
8
|
+
export declare function colorIsValid(color: string): boolean;
|
|
9
|
+
export interface ExtensionDataPayload {
|
|
10
|
+
metadata: {
|
|
11
|
+
dataType: ExtensionEntryType;
|
|
12
|
+
extensionName: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface ExtensionFlameChartEntryPayload extends ExtensionDataPayload {
|
|
16
|
+
metadata: ExtensionDataPayload['metadata'] & {
|
|
17
|
+
dataType: ExtensionEntryType.TRACK_ENTRY;
|
|
18
|
+
};
|
|
19
|
+
color: ExtensionColorFromPalette;
|
|
20
|
+
track: string;
|
|
21
|
+
detailsPairs?: [string, string][];
|
|
22
|
+
hintText?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ExtensionMarkerPayload extends ExtensionDataPayload {
|
|
25
|
+
metadata: ExtensionDataPayload['metadata'] & {
|
|
26
|
+
dataType: ExtensionEntryType.MARKER;
|
|
27
|
+
};
|
|
28
|
+
color: ExtensionColorFromPalette;
|
|
29
|
+
detailsPairs?: [string, string][];
|
|
30
|
+
hintText?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SyntheticExtensionFlameChartEntry extends SyntheticTraceEntry {
|
|
33
|
+
args: TraceEventArgs & ExtensionFlameChartEntryPayload;
|
|
34
|
+
}
|
|
35
|
+
export interface SyntheticExtensionMarker extends SyntheticTraceEntry {
|
|
36
|
+
args: TraceEventArgs & ExtensionMarkerPayload;
|
|
37
|
+
}
|
|
38
|
+
export type SyntheticExtensionEntry = SyntheticExtensionFlameChartEntry | SyntheticExtensionMarker;
|
|
39
|
+
export declare function validateColorInPayload(payload: ExtensionDataPayload): boolean;
|
|
40
|
+
export declare function isExtensionPayloadMarker(payload: ExtensionDataPayload): payload is ExtensionMarkerPayload;
|
|
41
|
+
export declare function isExtensionPayloadFlameChartEntry(payload: ExtensionDataPayload): payload is ExtensionFlameChartEntryPayload;
|
|
42
|
+
export declare function isSyntheticExtensionEntry(entry: TraceEventData): entry is SyntheticExtensionEntry;
|
|
43
|
+
/**
|
|
44
|
+
* Synthetic events created for extension tracks.
|
|
45
|
+
*/
|
|
46
|
+
export interface SyntheticExtensionFlameChartEntry extends SyntheticTraceEntry {
|
|
47
|
+
args: TraceEventArgs & ExtensionFlameChartEntryPayload;
|
|
48
|
+
cat: 'devtools.extension';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Synthetic events created for extension marks.
|
|
52
|
+
*/
|
|
53
|
+
export interface SyntheticExtensionMarker extends SyntheticTraceEntry {
|
|
54
|
+
args: TraceEventArgs & ExtensionMarkerPayload;
|
|
55
|
+
cat: 'devtools.extension';
|
|
56
|
+
}
|
|
57
|
+
export interface ExtensionTrackData {
|
|
58
|
+
name: string;
|
|
59
|
+
extensionName: string;
|
|
60
|
+
flameChartEntries: SyntheticExtensionFlameChartEntry[];
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
const extensionPalette = [
|
|
5
|
+
'primary',
|
|
6
|
+
'primary-light',
|
|
7
|
+
'primary-dark',
|
|
8
|
+
'secondary',
|
|
9
|
+
'secondary-light',
|
|
10
|
+
'secondary-dark',
|
|
11
|
+
'tertiary',
|
|
12
|
+
'tertiary-light',
|
|
13
|
+
'tertiary-dark',
|
|
14
|
+
'error',
|
|
15
|
+
];
|
|
16
|
+
export function colorIsValid(color) {
|
|
17
|
+
return extensionPalette.includes(color);
|
|
18
|
+
}
|
|
19
|
+
export function validateColorInPayload(payload) {
|
|
20
|
+
if (!('color' in payload) || !payload.color) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const color = payload['color'];
|
|
24
|
+
return colorIsValid(color);
|
|
25
|
+
}
|
|
26
|
+
export function isExtensionPayloadMarker(payload) {
|
|
27
|
+
const colorIsValid = validateColorInPayload(payload);
|
|
28
|
+
return payload.metadata.dataType === "marker" /* ExtensionEntryType.MARKER */ && colorIsValid;
|
|
29
|
+
}
|
|
30
|
+
export function isExtensionPayloadFlameChartEntry(payload) {
|
|
31
|
+
const colorIsValid = validateColorInPayload(payload);
|
|
32
|
+
const hasTrack = 'track' in payload && Boolean(payload.track);
|
|
33
|
+
return payload.metadata.dataType === "track-entry" /* ExtensionEntryType.TRACK_ENTRY */ && hasTrack && colorIsValid;
|
|
34
|
+
}
|
|
35
|
+
export function isSyntheticExtensionEntry(entry) {
|
|
36
|
+
return entry.cat === 'devtools.extension';
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=Extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAa7B,MAAM,gBAAgB,GAAG;IACvB,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;CACC,CAAC;AAIX,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AA8BD,MAAM,UAAU,sBAAsB,CAAC,OAA6B;IAClE,IAAI,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAA8B,CAAC;IAC5D,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAA6B;IACpE,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,6CAA8B,IAAI,YAAY,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,OAA6B;IAE7E,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,uDAAmC,IAAI,QAAQ,IAAI,YAAY,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAqB;IAC7D,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,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 {\n type SyntheticTraceEntry,\n type TraceEventArgs,\n type TraceEventData,\n} from './TraceEvents.js';\n\nexport const enum ExtensionEntryType {\n TRACK_ENTRY = 'track-entry',\n MARKER = 'marker',\n}\n\nconst extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport function colorIsValid(color: string): boolean {\n return (extensionPalette as readonly string[]).includes(color);\n}\n\nexport interface ExtensionDataPayload {\n metadata: {dataType: ExtensionEntryType, extensionName: string};\n}\nexport interface ExtensionFlameChartEntryPayload extends ExtensionDataPayload {\n metadata: ExtensionDataPayload['metadata']&{dataType: ExtensionEntryType.TRACK_ENTRY};\n color: ExtensionColorFromPalette;\n track: string;\n detailsPairs?: [string, string][];\n hintText?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayload {\n metadata: ExtensionDataPayload['metadata']&{dataType: ExtensionEntryType.MARKER};\n color: ExtensionColorFromPalette;\n detailsPairs?: [string, string][];\n hintText?: string;\n}\n\nexport interface SyntheticExtensionFlameChartEntry extends SyntheticTraceEntry {\n args: TraceEventArgs&ExtensionFlameChartEntryPayload;\n}\n\nexport interface SyntheticExtensionMarker extends SyntheticTraceEntry {\n args: TraceEventArgs&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionFlameChartEntry|SyntheticExtensionMarker;\n\nexport function validateColorInPayload(payload: ExtensionDataPayload): boolean {\n if (!('color' in payload) || !payload.color) {\n return false;\n }\n const color = payload['color'] as ExtensionColorFromPalette;\n return colorIsValid(color);\n}\n\nexport function isExtensionPayloadMarker(payload: ExtensionDataPayload): payload is ExtensionMarkerPayload {\n const colorIsValid = validateColorInPayload(payload);\n return payload.metadata.dataType === ExtensionEntryType.MARKER && colorIsValid;\n}\n\nexport function isExtensionPayloadFlameChartEntry(payload: ExtensionDataPayload):\n payload is ExtensionFlameChartEntryPayload {\n const colorIsValid = validateColorInPayload(payload);\n const hasTrack = 'track' in payload && Boolean(payload.track);\n return payload.metadata.dataType === ExtensionEntryType.TRACK_ENTRY && hasTrack && colorIsValid;\n}\n\nexport function isSyntheticExtensionEntry(entry: TraceEventData): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionFlameChartEntry extends SyntheticTraceEntry {\n args: TraceEventArgs&ExtensionFlameChartEntryPayload;\n cat: 'devtools.extension';\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticTraceEntry {\n args: TraceEventArgs&ExtensionMarkerPayload;\n cat: 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n name: string;\n extensionName: string;\n flameChartEntries: SyntheticExtensionFlameChartEntry[];\n}\n"]}
|