@paulirish/trace_engine 0.0.48 → 0.0.49

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.
Files changed (139) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/core/platform/TypedArrayUtilities.d.ts +2 -1
  3. package/core/platform/TypedArrayUtilities.js +9 -4
  4. package/core/platform/TypedArrayUtilities.js.map +1 -1
  5. package/generated/protocol.d.ts +19 -2
  6. package/locales/af.json +229 -16
  7. package/locales/am.json +231 -18
  8. package/locales/ar.json +229 -16
  9. package/locales/as.json +231 -18
  10. package/locales/az.json +231 -18
  11. package/locales/be.json +228 -15
  12. package/locales/bg.json +229 -16
  13. package/locales/bn.json +229 -16
  14. package/locales/bs.json +229 -16
  15. package/locales/ca.json +229 -16
  16. package/locales/cs.json +228 -15
  17. package/locales/cy.json +231 -18
  18. package/locales/da.json +230 -17
  19. package/locales/de.json +228 -15
  20. package/locales/el.json +229 -16
  21. package/locales/en-GB.json +229 -16
  22. package/locales/en-US.json +30 -3
  23. package/locales/en-XL.json +30 -3
  24. package/locales/es-419.json +229 -16
  25. package/locales/es.json +228 -15
  26. package/locales/et.json +230 -17
  27. package/locales/eu.json +231 -18
  28. package/locales/fa.json +230 -17
  29. package/locales/fi.json +229 -16
  30. package/locales/fil.json +231 -18
  31. package/locales/fr-CA.json +230 -17
  32. package/locales/fr.json +230 -17
  33. package/locales/gl.json +228 -15
  34. package/locales/gu.json +230 -17
  35. package/locales/he.json +229 -16
  36. package/locales/hi.json +230 -17
  37. package/locales/hr.json +229 -16
  38. package/locales/hu.json +229 -16
  39. package/locales/hy.json +228 -15
  40. package/locales/id.json +228 -15
  41. package/locales/is.json +229 -16
  42. package/locales/it.json +232 -19
  43. package/locales/ja.json +228 -15
  44. package/locales/ka.json +230 -17
  45. package/locales/kk.json +230 -17
  46. package/locales/km.json +231 -18
  47. package/locales/kn.json +228 -15
  48. package/locales/ko.json +229 -16
  49. package/locales/ky.json +230 -17
  50. package/locales/lo.json +229 -16
  51. package/locales/lt.json +229 -16
  52. package/locales/lv.json +230 -17
  53. package/locales/mk.json +229 -16
  54. package/locales/ml.json +230 -17
  55. package/locales/mn.json +229 -16
  56. package/locales/mr.json +230 -17
  57. package/locales/ms.json +229 -16
  58. package/locales/my.json +231 -18
  59. package/locales/ne.json +229 -16
  60. package/locales/nl.json +229 -16
  61. package/locales/no.json +229 -16
  62. package/locales/or.json +231 -18
  63. package/locales/pa.json +228 -15
  64. package/locales/pl.json +230 -17
  65. package/locales/pt-PT.json +229 -16
  66. package/locales/pt.json +229 -16
  67. package/locales/ro.json +228 -15
  68. package/locales/ru.json +230 -17
  69. package/locales/si.json +231 -18
  70. package/locales/sk.json +229 -16
  71. package/locales/sl.json +230 -17
  72. package/locales/sq.json +229 -16
  73. package/locales/sr-Latn.json +229 -16
  74. package/locales/sr.json +229 -16
  75. package/locales/sv.json +229 -16
  76. package/locales/sw.json +231 -18
  77. package/locales/ta.json +230 -17
  78. package/locales/te.json +231 -18
  79. package/locales/th.json +229 -16
  80. package/locales/tr.json +230 -17
  81. package/locales/uk.json +229 -16
  82. package/locales/ur.json +230 -17
  83. package/locales/uz.json +229 -16
  84. package/locales/vi.json +230 -17
  85. package/locales/zh-HK.json +229 -16
  86. package/locales/zh-TW.json +230 -17
  87. package/locales/zh.json +228 -15
  88. package/locales/zu.json +230 -17
  89. package/models/trace/Processor.js +5 -3
  90. package/models/trace/Processor.js.map +1 -1
  91. package/models/trace/extras/ScriptDuplication.d.ts +27 -8
  92. package/models/trace/extras/ScriptDuplication.js +27 -26
  93. package/models/trace/extras/ScriptDuplication.js.map +1 -1
  94. package/models/trace/extras/StackTraceForEvent.js +7 -0
  95. package/models/trace/extras/StackTraceForEvent.js.map +1 -1
  96. package/models/trace/handlers/ExtensionTraceDataHandler.js +14 -9
  97. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  98. package/models/trace/handlers/MetaHandler.d.ts +13 -0
  99. package/models/trace/handlers/MetaHandler.js +27 -0
  100. package/models/trace/handlers/MetaHandler.js.map +1 -1
  101. package/models/trace/helpers/Network.d.ts +18 -0
  102. package/models/trace/helpers/Network.js +57 -0
  103. package/models/trace/helpers/Network.js.map +1 -1
  104. package/models/trace/helpers/SamplesIntegrator.js +1 -1
  105. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  106. package/models/trace/helpers/Trace.js +4 -0
  107. package/models/trace/helpers/Trace.js.map +1 -1
  108. package/models/trace/insights/DocumentLatency.d.ts +2 -1
  109. package/models/trace/insights/DocumentLatency.js +3 -0
  110. package/models/trace/insights/DocumentLatency.js.map +1 -1
  111. package/models/trace/insights/{DuplicateJavaScript.d.ts → DuplicatedJavaScript.d.ts} +6 -1
  112. package/models/trace/insights/{DuplicateJavaScript.js → DuplicatedJavaScript.js} +15 -6
  113. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -0
  114. package/models/trace/insights/FontDisplay.d.ts +1 -2
  115. package/models/trace/insights/FontDisplay.js.map +1 -1
  116. package/models/trace/insights/ForcedReflow.d.ts +23 -3
  117. package/models/trace/insights/ForcedReflow.js +63 -107
  118. package/models/trace/insights/ForcedReflow.js.map +1 -1
  119. package/models/trace/insights/Models.d.ts +2 -1
  120. package/models/trace/insights/Models.js +2 -1
  121. package/models/trace/insights/Models.js.map +1 -1
  122. package/models/trace/insights/NetworkDependencyTree.d.ts +2 -1
  123. package/models/trace/insights/NetworkDependencyTree.js +9 -4
  124. package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
  125. package/models/trace/insights/Statistics.d.ts +4 -0
  126. package/models/trace/insights/Statistics.js +7 -0
  127. package/models/trace/insights/Statistics.js.map +1 -1
  128. package/models/trace/insights/UseCache.d.ts +69 -0
  129. package/models/trace/insights/UseCache.js +189 -0
  130. package/models/trace/insights/UseCache.js.map +1 -0
  131. package/models/trace/insights/insights-tsconfig.json +2 -1
  132. package/models/trace/insights/types.d.ts +1 -13
  133. package/models/trace/insights/types.js.map +1 -1
  134. package/models/trace/types/TraceEvents.d.ts +16 -4
  135. package/models/trace/types/TraceEvents.js +4 -1
  136. package/models/trace/types/TraceEvents.js.map +1 -1
  137. package/package.json +1 -1
  138. package/test/test-trace-engine.mjs +2 -1
  139. package/models/trace/insights/DuplicateJavaScript.js.map +0 -1
@@ -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 Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {SyntheticEventsManager} from './SyntheticEvents.js';\nimport {eventTimingsMicroSeconds} from './Timing.js';\n\ninterface MatchingPairableAsyncEvents {\n begin: Types.Events.PairableAsyncBegin|null;\n end: Types.Events.PairableAsyncEnd|null;\n instant?: Types.Events.PairableAsyncInstant[];\n}\n\n/**\n * Extracts the raw stack trace in known trace events. Most likely than\n * not you want to use `getZeroIndexedStackTraceForEvent`, which returns\n * the stack with zero based numbering. Since some trace events are\n * one based this function can yield unexpected results when used\n * indiscriminately.\n *\n * Note: this only returns the stack trace contained in the payload of\n * an event, which only contains the synchronous portion of the call\n * stack. If you want to obtain the whole stack trace you might need to\n * use the @see Trace.Extras.StackTraceForEvent util.\n */\nexport function stackTraceInEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (event.args?.stackTrace) {\n return event.args.stackTrace;\n }\n if (Types.Events.isUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n if (Types.Events.isFunctionCall(event)) {\n const data = event.args.data;\n if (!data) {\n return null;\n }\n const {columnNumber, lineNumber, url, scriptId, functionName} = data;\n if (lineNumber === undefined || functionName === undefined || columnNumber === undefined ||\n scriptId === undefined || url === undefined) {\n return null;\n }\n return [{columnNumber, lineNumber, url, scriptId, functionName}];\n }\n if (Types.Events.isProfileCall(event)) {\n // Of type Protocol.Runtime.CallFrame, handle accordingly.\n const callFrame = event.callFrame;\n if (!callFrame) {\n return null;\n }\n const {columnNumber, lineNumber, url, scriptId, functionName} = callFrame;\n if (lineNumber === undefined || functionName === undefined || columnNumber === undefined ||\n scriptId === undefined || url === undefined) {\n return null;\n }\n return [{columnNumber, lineNumber, url, scriptId, functionName}];\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.Events.Event> = Map<Types.Events.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.Events.Event>(\n event: T,\n eventsInProcessThread: Map<Types.Events.ProcessID, EventsInThread<T>>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map<Types.Events.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\nexport interface TimeSpan {\n ts: Types.Timing.Micro;\n dur?: Types.Timing.Micro;\n}\nexport function eventTimeComparator(a: Types.Events.Event, b: Types.Events.Event): -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 // If times are equal, prioritize profile calls over trace events,\n // since an exactly equal timestamp with a trace event is likely\n // indicates that the SamplesIntegrator meant to parent the trace\n // event with the profile call.\n if (Types.Events.isProfileCall(a) && !Types.Events.isProfileCall(b)) {\n return -1;\n }\n if (Types.Events.isProfileCall(b) && !Types.Events.isProfileCall(a)) {\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: Types.Events.Event[]): 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 mergeEventsInOrder<T1 extends Types.Events.Event, T2 extends Types.Events.Event>(\n eventsArray1: readonly T1[], eventsArray2: readonly T2[]): Array<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.Events.Event,\n eventFrameId: string,\n navigationsByFrameId: Map<string, Types.Events.NavigationStart[]>,\n ): Types.Events.NavigationStart|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.Events.PairableAsync|\n Types.Events.SyntheticEventPair<Types.Events.PairableAsync>): string|undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.Micro,\n rendererProcessesByFrame: Map<\n string,\n Map<Types.Events.ProcessID, Array<{frame: Types.Events.TraceFrame, window: Types.Timing.TraceWindowMicro}>>>):\n 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\n/**\n * @param node the node attached to the profile call. Here a node represents a function in the call tree.\n * @param profileId the profile ID that the sample came from that backs this call.\n * @param sampleIndex the index of the sample in the given profile that this call was created from\n * @param ts the timestamp of the profile call\n * @param pid the process ID of the profile call\n * @param tid the thread ID of the profile call\n *\n * See `panels/timeline/docs/profile_calls.md` for more context on how these events are created.\n */\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.Events.ProfileID, sampleIndex: number,\n ts: Types.Timing.Micro, pid: Types.Events.ProcessID,\n tid: Types.Events.ThreadID): Types.Events.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.Events.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.Micro(0),\n callFrame: node.callFrame,\n sampleIndex,\n profileId,\n };\n}\n\n/**\n * Matches beginning events with PairableAsyncEnd and PairableAsyncInstant (ASYNC_NESTABLE_INSTANT)\n * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to\n * account for that.\n *\n * @returns {Map<string, MatchingPairableAsyncEvents>} Map of the animation's ID to it's matching events.\n */\nexport function matchEvents(unpairedEvents: Types.Events.PairableAsync[]): Map<string, MatchingPairableAsyncEvents> {\n // map to store begin and end of the event\n const matchedPairs = new Map<string, MatchingPairableAsyncEvents>();\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, instant: []};\n });\n\n const isStartEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_END;\n const isInstantEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_INSTANT;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.Events.PairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.Events.PairableAsyncEnd;\n } else if (isInstantEvent) {\n if (!otherEventsWithID.instant) {\n otherEventsWithID.instant = [];\n }\n otherEventsWithID.instant.push(event as Types.Events.PairableAsyncInstant);\n }\n }\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.Events.PairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents<T extends Types.Events.PairableAsync>(\n matchedPairs: Map<string, {\n begin: Types.Events.PairableAsyncBegin | null,\n end: Types.Events.PairableAsyncEnd | null,\n instant?: Types.Events.PairableAsyncInstant[],\n }>,\n syntheticEventCallback?: (syntheticEvent: Types.Events.SyntheticEventPair<T>) => void,\n ): Array<Types.Events.SyntheticEventPair<T>> {\n const syntheticEvents: Array<Types.Events.SyntheticEventPair<T>> = [];\n for (const [id, eventsTriplet] of matchedPairs.entries()) {\n const beginEvent = eventsTriplet.begin;\n const endEvent = eventsTriplet.end;\n const instantEvents = eventsTriplet.instant;\n if (!beginEvent || !(endEvent || instantEvents)) {\n // This should never happen, the backend only creates the events once it\n // has them both (beginEvent & endEvent/instantEvents), 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 triplet = {beginEvent, endEvent, instantEvents};\n /**\n * When trying to pair events with instant events present, there are times when these\n * ASYNC_NESTABLE_INSTANT ('n') don't have a corresponding ASYNC_NESTABLE_END ('e') event.\n * In these cases, pair without needing the endEvent.\n */\n function eventsArePairable(data: {\n beginEvent: Types.Events.PairableAsyncBegin,\n endEvent: Types.Events.PairableAsyncEnd|null,\n instantEvents?: Types.Events.PairableAsyncInstant[],\n }): data is Types.Events.SyntheticEventPair<T>['args']['data'] {\n const instantEventsMatch = data.instantEvents ? data.instantEvents.some(e => id === getSyntheticId(e)) : false;\n const endEventMatch = data.endEvent ? id === getSyntheticId(data.endEvent) : false;\n return Boolean(id) && (instantEventsMatch || endEventMatch);\n }\n if (!eventsArePairable(triplet)) {\n continue;\n }\n const targetEvent = endEvent || beginEvent;\n\n const event = SyntheticEventsManager.registerSyntheticEvent<Types.Events.SyntheticEventPair<T>>({\n rawSourceEvent: triplet.beginEvent,\n cat: targetEvent.cat,\n ph: targetEvent.ph,\n pid: targetEvent.pid,\n tid: targetEvent.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.Micro(targetEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: triplet,\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.Events.PairableAsync>(\n unpairedAsyncEvents: T[], syntheticEventCallback?: (syntheticEvent: Types.Events.SyntheticEventPair<T>) => void):\n Array<Types.Events.SyntheticEventPair<T>> {\n const matchedPairs = matchEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents<T>(matchedPairs, syntheticEventCallback);\n return syntheticEvents;\n}\n\n/**\n * Different trace events return line/column numbers that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedLineAndColumnForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n // Some events emit line numbers that are 1 indexed, but the UI layer expects\n // numbers to be 0 indexed. So here, if the event matches a known 1-indexed\n // number event, we subtract one from the line and column numbers.\n // Otherwise, if the event has args.data.lineNumber/colNumber, we return it\n // as is.\n const numbers = getRawLineAndColumnNumbersForEvent(event);\n const {lineNumber, columnNumber} = numbers;\n\n switch (event.name) {\n // All these events have line/column numbers which are 1 indexed; so we\n // subtract to make them 0 indexed.\n case Types.Events.Name.FUNCTION_CALL:\n case Types.Events.Name.EVALUATE_SCRIPT:\n case Types.Events.Name.COMPILE:\n case Types.Events.Name.CACHE_SCRIPT: {\n return {\n lineNumber: typeof lineNumber === 'number' ? lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? columnNumber - 1 : undefined,\n };\n }\n case Types.Events.Name.PROFILE_CALL: {\n const callFrame = (event as Types.Events.SyntheticProfileCall).callFrame;\n return {\n lineNumber: typeof lineNumber === 'number' ? callFrame.lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? callFrame.columnNumber - 1 : undefined,\n };\n }\n default: {\n return numbers;\n }\n }\n}\n\n/**\n * Different trace events contain stack traces with line/column numbers\n * that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n *\n * Note: this only returns the stack trace contained in the payload of\n * an event, which only contains the synchronous portion of the call\n * stack. If you want to obtain the whole stack trace you might need to\n * use the @see Trace.Extras.StackTraceForEvent util.\n */\nexport function getZeroIndexedStackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n const stack = stackTraceInEvent(event);\n if (!stack) {\n return null;\n }\n return stack.map(callFrame => {\n switch (event.name) {\n case Types.Events.Name.SCHEDULE_STYLE_RECALCULATION:\n case Types.Events.Name.INVALIDATE_LAYOUT:\n case Types.Events.Name.FUNCTION_CALL:\n case Types.Events.Name.UPDATE_LAYOUT_TREE: {\n return makeZeroBasedCallFrame(callFrame);\n }\n default: {\n if (Types.Events.isUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) {\n return makeZeroBasedCallFrame(callFrame);\n }\n }\n }\n return callFrame;\n });\n}\n\n/**\n * Given a 1-based call frame creates a 0-based one.\n */\nexport function makeZeroBasedCallFrame(callFrame: Types.Events.CallFrame): Types.Events.CallFrame {\n const normalizedCallFrame = {...callFrame};\n\n normalizedCallFrame.lineNumber = callFrame.lineNumber && callFrame.lineNumber - 1;\n normalizedCallFrame.columnNumber = callFrame.columnNumber && callFrame.columnNumber - 1;\n return normalizedCallFrame;\n}\n\n/**\n * NOTE: you probably do not want this function! (Which is why it is not exported).\n *\n * Some trace events have 0 indexed line/column numbers, and others have 1\n * indexed. This function does NOT normalize them, but\n * `getZeroIndexedLineAndColumnNumbersForEvent` does. It is best to use that!\n *\n * @see {@link getZeroIndexedLineAndColumnForEvent}\n **/\nfunction getRawLineAndColumnNumbersForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n if (!event.args?.data) {\n return {\n lineNumber: undefined,\n columnNumber: undefined,\n };\n }\n let lineNumber: number|undefined = undefined;\n let columnNumber: number|undefined = undefined;\n if ('lineNumber' in event.args.data && typeof event.args.data.lineNumber === 'number') {\n lineNumber = event.args.data.lineNumber;\n }\n if ('columnNumber' in event.args.data && typeof event.args.data.columnNumber === 'number') {\n columnNumber = event.args.data.columnNumber;\n }\n\n return {lineNumber, columnNumber};\n}\n\nexport function frameIDForEvent(event: Types.Events.Event): string|null {\n // There are a few events (for example UpdateLayoutTree, ParseHTML) that have\n // the frame stored in args.beginData\n // Rather than list them all we just check for the presence of the field, so\n // we are robust against future trace events also doing this.\n // This check seems very robust, but it also helps satisfy TypeScript and\n // prevents us against unexpected data.\n if (event.args && 'beginData' in event.args && typeof event.args.beginData === 'object' &&\n event.args.beginData !== null && 'frame' in event.args.beginData &&\n typeof event.args.beginData.frame === 'string') {\n return event.args.beginData.frame;\n }\n // Otherwise, we expect frame to be in args.data\n if (event.args?.data?.frame) {\n return event.args.data.frame;\n }\n\n // No known frame for this event.\n return null;\n}\n\nconst DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';\nexport function isTopLevelEvent(event: Types.Events.Event): boolean {\n if (event.name === 'JSRoot' && event.cat === 'toplevel') {\n // This is used in createFakeTraceFromCpuProfile to insert a fake event prior to the\n // CPU Profile in order to ensure the trace isn't truncated. So if we see\n // this, we want to treat it as a top level event.\n // TODO(crbug.com/341234884): do we need this?\n return true;\n }\n return event.cat.includes(DevToolsTimelineEventCategory) && event.name === Types.Events.Name.RUN_TASK;\n}\n\nfunction topLevelEventIndexEndingAfter(events: Types.Events.Event[], time: Types.Timing.Micro): number {\n let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1;\n while (index > 0 && !isTopLevelEvent(events[index])) {\n index--;\n }\n return Math.max(index, 0);\n}\nexport function findUpdateLayoutTreeEvents(\n events: Types.Events.Event[], startTime: Types.Timing.Micro,\n endTime?: Types.Timing.Micro): Types.Events.UpdateLayoutTree[] {\n const foundEvents: Types.Events.UpdateLayoutTree[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, startTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const event = events[i];\n if (!Types.Events.isUpdateLayoutTree(event)) {\n continue;\n }\n if (event.ts >= (endTime || Infinity)) {\n continue;\n }\n foundEvents.push(event);\n }\n return foundEvents;\n}\n\nexport function findNextEventAfterTimestamp<T extends Types.Events.Event>(candidates: T[], ts: Types.Timing.Micro): T|\n null {\n const index = Platform.ArrayUtilities.nearestIndexFromBeginning(candidates, candidate => ts < candidate.ts);\n return index === null ? null : candidates[index];\n}\n\nexport function findPreviousEventBeforeTimestamp<T extends Types.Events.Event>(\n candidates: T[], ts: Types.Timing.Micro): T|null {\n const index = Platform.ArrayUtilities.nearestIndexFromEnd(candidates, candidate => candidate.ts < ts);\n return index === null ? null : candidates[index];\n}\n\nexport interface ForEachEventConfig {\n onStartEvent: (event: Types.Events.Event) => void;\n onEndEvent: (event: Types.Events.Event) => void;\n onInstantEvent?: (event: Types.Events.Event) => void;\n eventFilter?: (event: Types.Events.Event) => boolean;\n startTime?: Types.Timing.Micro;\n endTime?: Types.Timing.Micro;\n /* If async events should be skipped. Defaults to true */\n ignoreAsyncEvents?: boolean;\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * dictated by the corresponding timestamp.\n *\n * Events are assumed to be in ascendent order by timestamp.\n *\n * Events with 0 duration are treated as instant events. These do not have a\n * begin and end, but will be passed to the config.onInstantEvent callback as\n * they are discovered. Do not provide this callback if you are not interested\n * in them.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n * By default, async events are skipped. This behaviour can be\n * overridden making use of the config.ignoreAsyncEvents parameter.\n */\nexport function forEachEvent(\n events: Types.Events.Event[],\n config: ForEachEventConfig,\n ): void {\n const globalStartTime = config.startTime ?? Types.Timing.Micro(0);\n const globalEndTime = config.endTime || Types.Timing.Micro(Infinity);\n const ignoreAsyncEvents = config.ignoreAsyncEvents === false ? false : true;\n\n const stack: Types.Events.Event[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, globalStartTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const currentEvent = events[i];\n const currentEventTimings = eventTimingsMicroSeconds(currentEvent);\n if (currentEventTimings.endTime < globalStartTime) {\n continue;\n }\n if (currentEventTimings.startTime > globalEndTime) {\n break;\n }\n\n const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.Events.isPhaseAsync(currentEvent.ph);\n if (isIgnoredAsyncEvent || Types.Events.isFlowPhase(currentEvent.ph)) {\n continue;\n }\n\n // If we have now reached an event that is after a bunch of events, we need\n // to call the onEndEvent callback for those events before moving on.\n let lastEventOnStack = stack.at(-1);\n let lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n while (lastEventOnStack && lastEventEndTime && lastEventEndTime <= currentEventTimings.startTime) {\n stack.pop();\n config.onEndEvent(lastEventOnStack);\n lastEventOnStack = stack.at(-1);\n lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n }\n\n // Now we have dealt with all events prior to this one, see if we need to care about this one.\n if (config.eventFilter && !config.eventFilter(currentEvent)) {\n // The user has chosen to filter this event out, so continue on and do nothing\n continue;\n }\n\n if (currentEventTimings.duration) {\n config.onStartEvent(currentEvent);\n stack.push(currentEvent);\n } else if (config.onInstantEvent) {\n // An event with 0 duration is an instant event.\n config.onInstantEvent(currentEvent);\n }\n }\n\n // Now we have finished looping over all events; any events remaining on the\n // stack need to have their onEndEvent called.\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n config.onEndEvent(last);\n }\n }\n}\n\n// Parsed categories are cached to prevent calling cat.split()\n// multiple times on the same categories string.\nconst parsedCategories = new Map<string, Set<string>>();\nexport function eventHasCategory(event: Types.Events.Event, category: string): boolean {\n let parsedCategoriesForEvent = parsedCategories.get(event.cat);\n if (!parsedCategoriesForEvent) {\n parsedCategoriesForEvent = new Set(event.cat.split(',') || []);\n }\n return parsedCategoriesForEvent.has(category);\n}\n\n/**\n * This compares Types.Events.CallFrame with Protocol.Runtime.CallFrame and checks for equality.\n */\nexport function isMatchingCallFrame(\n eventFrame: Types.Events.CallFrame, nodeFrame: Protocol.Runtime.CallFrame): boolean {\n return eventFrame.columnNumber === nodeFrame.columnNumber && eventFrame.lineNumber === nodeFrame.lineNumber &&\n String(eventFrame.scriptId) === nodeFrame.scriptId && eventFrame.url === nodeFrame.url &&\n eventFrame.functionName === nodeFrame.functionName;\n}\n\nexport function eventContainsTimestamp(event: Types.Events.Event, ts: Types.Timing.Micro): boolean {\n return event.ts <= ts && event.ts + (event.dur || 0) >= ts;\n}\n\nexport function extractSampleTraceId(event: Types.Events.Event): number|null {\n if (!event.args) {\n return null;\n }\n if ('beginData' in event.args) {\n const beginData = event.args['beginData'] as {sampleTraceId?: number};\n return beginData.sampleTraceId ?? null;\n }\n return event.args?.sampleTraceId ?? event.args?.data?.sampleTraceId ?? null;\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 Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {SyntheticEventsManager} from './SyntheticEvents.js';\nimport {eventTimingsMicroSeconds} from './Timing.js';\n\ninterface MatchingPairableAsyncEvents {\n begin: Types.Events.PairableAsyncBegin|null;\n end: Types.Events.PairableAsyncEnd|null;\n instant?: Types.Events.PairableAsyncInstant[];\n}\n\n/**\n * Extracts the raw stack trace in known trace events. Most likely than\n * not you want to use `getZeroIndexedStackTraceForEvent`, which returns\n * the stack with zero based numbering. Since some trace events are\n * one based this function can yield unexpected results when used\n * indiscriminately.\n *\n * Note: this only returns the stack trace contained in the payload of\n * an event, which only contains the synchronous portion of the call\n * stack. If you want to obtain the whole stack trace you might need to\n * use the @see Trace.Extras.StackTraceForEvent util.\n */\nexport function stackTraceInEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (event.args?.stackTrace) {\n return event.args.stackTrace;\n }\n if (Types.Events.isUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n if (Types.Events.isLayout(event)) {\n return event.args.beginData.stackTrace ?? null;\n }\n if (Types.Events.isFunctionCall(event)) {\n const data = event.args.data;\n if (!data) {\n return null;\n }\n const {columnNumber, lineNumber, url, scriptId, functionName} = data;\n if (lineNumber === undefined || functionName === undefined || columnNumber === undefined ||\n scriptId === undefined || url === undefined) {\n return null;\n }\n return [{columnNumber, lineNumber, url, scriptId, functionName}];\n }\n if (Types.Events.isProfileCall(event)) {\n // Of type Protocol.Runtime.CallFrame, handle accordingly.\n const callFrame = event.callFrame;\n if (!callFrame) {\n return null;\n }\n const {columnNumber, lineNumber, url, scriptId, functionName} = callFrame;\n if (lineNumber === undefined || functionName === undefined || columnNumber === undefined ||\n scriptId === undefined || url === undefined) {\n return null;\n }\n return [{columnNumber, lineNumber, url, scriptId, functionName}];\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.Events.Event> = Map<Types.Events.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.Events.Event>(\n event: T,\n eventsInProcessThread: Map<Types.Events.ProcessID, EventsInThread<T>>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map<Types.Events.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\nexport interface TimeSpan {\n ts: Types.Timing.Micro;\n dur?: Types.Timing.Micro;\n}\nexport function eventTimeComparator(a: Types.Events.Event, b: Types.Events.Event): -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 // If times are equal, prioritize profile calls over trace events,\n // since an exactly equal timestamp with a trace event is likely\n // indicates that the SamplesIntegrator meant to parent the trace\n // event with the profile call.\n if (Types.Events.isProfileCall(a) && !Types.Events.isProfileCall(b)) {\n return -1;\n }\n if (Types.Events.isProfileCall(b) && !Types.Events.isProfileCall(a)) {\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: Types.Events.Event[]): 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 mergeEventsInOrder<T1 extends Types.Events.Event, T2 extends Types.Events.Event>(\n eventsArray1: readonly T1[], eventsArray2: readonly T2[]): Array<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.Events.Event,\n eventFrameId: string,\n navigationsByFrameId: Map<string, Types.Events.NavigationStart[]>,\n ): Types.Events.NavigationStart|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.Events.PairableAsync|\n Types.Events.SyntheticEventPair<Types.Events.PairableAsync>): string|undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.Micro,\n rendererProcessesByFrame: Map<\n string,\n Map<Types.Events.ProcessID, Array<{frame: Types.Events.TraceFrame, window: Types.Timing.TraceWindowMicro}>>>):\n 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\n/**\n * @param node the node attached to the profile call. Here a node represents a function in the call tree.\n * @param profileId the profile ID that the sample came from that backs this call.\n * @param sampleIndex the index of the sample in the given profile that this call was created from\n * @param ts the timestamp of the profile call\n * @param pid the process ID of the profile call\n * @param tid the thread ID of the profile call\n *\n * See `panels/timeline/docs/profile_calls.md` for more context on how these events are created.\n */\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.Events.ProfileID, sampleIndex: number,\n ts: Types.Timing.Micro, pid: Types.Events.ProcessID,\n tid: Types.Events.ThreadID): Types.Events.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.Events.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.Micro(0),\n callFrame: node.callFrame,\n sampleIndex,\n profileId,\n };\n}\n\n/**\n * Matches beginning events with PairableAsyncEnd and PairableAsyncInstant (ASYNC_NESTABLE_INSTANT)\n * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to\n * account for that.\n *\n * @returns {Map<string, MatchingPairableAsyncEvents>} Map of the animation's ID to it's matching events.\n */\nexport function matchEvents(unpairedEvents: Types.Events.PairableAsync[]): Map<string, MatchingPairableAsyncEvents> {\n // map to store begin and end of the event\n const matchedPairs = new Map<string, MatchingPairableAsyncEvents>();\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, instant: []};\n });\n\n const isStartEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_END;\n const isInstantEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_INSTANT;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.Events.PairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.Events.PairableAsyncEnd;\n } else if (isInstantEvent) {\n if (!otherEventsWithID.instant) {\n otherEventsWithID.instant = [];\n }\n otherEventsWithID.instant.push(event as Types.Events.PairableAsyncInstant);\n }\n }\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.Events.PairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents<T extends Types.Events.PairableAsync>(\n matchedPairs: Map<string, {\n begin: Types.Events.PairableAsyncBegin | null,\n end: Types.Events.PairableAsyncEnd | null,\n instant?: Types.Events.PairableAsyncInstant[],\n }>,\n syntheticEventCallback?: (syntheticEvent: Types.Events.SyntheticEventPair<T>) => void,\n ): Array<Types.Events.SyntheticEventPair<T>> {\n const syntheticEvents: Array<Types.Events.SyntheticEventPair<T>> = [];\n for (const [id, eventsTriplet] of matchedPairs.entries()) {\n const beginEvent = eventsTriplet.begin;\n const endEvent = eventsTriplet.end;\n const instantEvents = eventsTriplet.instant;\n if (!beginEvent || !(endEvent || instantEvents)) {\n // This should never happen, the backend only creates the events once it\n // has them both (beginEvent & endEvent/instantEvents), 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 triplet = {beginEvent, endEvent, instantEvents};\n /**\n * When trying to pair events with instant events present, there are times when these\n * ASYNC_NESTABLE_INSTANT ('n') don't have a corresponding ASYNC_NESTABLE_END ('e') event.\n * In these cases, pair without needing the endEvent.\n */\n function eventsArePairable(data: {\n beginEvent: Types.Events.PairableAsyncBegin,\n endEvent: Types.Events.PairableAsyncEnd|null,\n instantEvents?: Types.Events.PairableAsyncInstant[],\n }): data is Types.Events.SyntheticEventPair<T>['args']['data'] {\n const instantEventsMatch = data.instantEvents ? data.instantEvents.some(e => id === getSyntheticId(e)) : false;\n const endEventMatch = data.endEvent ? id === getSyntheticId(data.endEvent) : false;\n return Boolean(id) && (instantEventsMatch || endEventMatch);\n }\n if (!eventsArePairable(triplet)) {\n continue;\n }\n const targetEvent = endEvent || beginEvent;\n\n const event = SyntheticEventsManager.registerSyntheticEvent<Types.Events.SyntheticEventPair<T>>({\n rawSourceEvent: triplet.beginEvent,\n cat: targetEvent.cat,\n ph: targetEvent.ph,\n pid: targetEvent.pid,\n tid: targetEvent.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.Micro(targetEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: triplet,\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.Events.PairableAsync>(\n unpairedAsyncEvents: T[], syntheticEventCallback?: (syntheticEvent: Types.Events.SyntheticEventPair<T>) => void):\n Array<Types.Events.SyntheticEventPair<T>> {\n const matchedPairs = matchEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents<T>(matchedPairs, syntheticEventCallback);\n return syntheticEvents;\n}\n\n/**\n * Different trace events return line/column numbers that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedLineAndColumnForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n // Some events emit line numbers that are 1 indexed, but the UI layer expects\n // numbers to be 0 indexed. So here, if the event matches a known 1-indexed\n // number event, we subtract one from the line and column numbers.\n // Otherwise, if the event has args.data.lineNumber/colNumber, we return it\n // as is.\n const numbers = getRawLineAndColumnNumbersForEvent(event);\n const {lineNumber, columnNumber} = numbers;\n\n switch (event.name) {\n // All these events have line/column numbers which are 1 indexed; so we\n // subtract to make them 0 indexed.\n case Types.Events.Name.FUNCTION_CALL:\n case Types.Events.Name.EVALUATE_SCRIPT:\n case Types.Events.Name.COMPILE:\n case Types.Events.Name.CACHE_SCRIPT: {\n return {\n lineNumber: typeof lineNumber === 'number' ? lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? columnNumber - 1 : undefined,\n };\n }\n case Types.Events.Name.PROFILE_CALL: {\n const callFrame = (event as Types.Events.SyntheticProfileCall).callFrame;\n return {\n lineNumber: typeof lineNumber === 'number' ? callFrame.lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? callFrame.columnNumber - 1 : undefined,\n };\n }\n default: {\n return numbers;\n }\n }\n}\n\n/**\n * Different trace events contain stack traces with line/column numbers\n * that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n *\n * Note: this only returns the stack trace contained in the payload of\n * an event, which only contains the synchronous portion of the call\n * stack. If you want to obtain the whole stack trace you might need to\n * use the @see Trace.Extras.StackTraceForEvent util.\n */\nexport function getZeroIndexedStackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n const stack = stackTraceInEvent(event);\n if (!stack) {\n return null;\n }\n return stack.map(callFrame => {\n switch (event.name) {\n case Types.Events.Name.SCHEDULE_STYLE_RECALCULATION:\n case Types.Events.Name.INVALIDATE_LAYOUT:\n case Types.Events.Name.FUNCTION_CALL:\n case Types.Events.Name.LAYOUT:\n case Types.Events.Name.UPDATE_LAYOUT_TREE: {\n return makeZeroBasedCallFrame(callFrame);\n }\n default: {\n if (Types.Events.isUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) {\n return makeZeroBasedCallFrame(callFrame);\n }\n }\n }\n return callFrame;\n });\n}\n\n/**\n * Given a 1-based call frame creates a 0-based one.\n */\nexport function makeZeroBasedCallFrame(callFrame: Types.Events.CallFrame): Types.Events.CallFrame {\n const normalizedCallFrame = {...callFrame};\n\n normalizedCallFrame.lineNumber = callFrame.lineNumber && callFrame.lineNumber - 1;\n normalizedCallFrame.columnNumber = callFrame.columnNumber && callFrame.columnNumber - 1;\n return normalizedCallFrame;\n}\n\n/**\n * NOTE: you probably do not want this function! (Which is why it is not exported).\n *\n * Some trace events have 0 indexed line/column numbers, and others have 1\n * indexed. This function does NOT normalize them, but\n * `getZeroIndexedLineAndColumnNumbersForEvent` does. It is best to use that!\n *\n * @see {@link getZeroIndexedLineAndColumnForEvent}\n **/\nfunction getRawLineAndColumnNumbersForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n if (!event.args?.data) {\n return {\n lineNumber: undefined,\n columnNumber: undefined,\n };\n }\n let lineNumber: number|undefined = undefined;\n let columnNumber: number|undefined = undefined;\n if ('lineNumber' in event.args.data && typeof event.args.data.lineNumber === 'number') {\n lineNumber = event.args.data.lineNumber;\n }\n if ('columnNumber' in event.args.data && typeof event.args.data.columnNumber === 'number') {\n columnNumber = event.args.data.columnNumber;\n }\n\n return {lineNumber, columnNumber};\n}\n\nexport function frameIDForEvent(event: Types.Events.Event): string|null {\n // There are a few events (for example UpdateLayoutTree, ParseHTML) that have\n // the frame stored in args.beginData\n // Rather than list them all we just check for the presence of the field, so\n // we are robust against future trace events also doing this.\n // This check seems very robust, but it also helps satisfy TypeScript and\n // prevents us against unexpected data.\n if (event.args && 'beginData' in event.args && typeof event.args.beginData === 'object' &&\n event.args.beginData !== null && 'frame' in event.args.beginData &&\n typeof event.args.beginData.frame === 'string') {\n return event.args.beginData.frame;\n }\n // Otherwise, we expect frame to be in args.data\n if (event.args?.data?.frame) {\n return event.args.data.frame;\n }\n\n // No known frame for this event.\n return null;\n}\n\nconst DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';\nexport function isTopLevelEvent(event: Types.Events.Event): boolean {\n if (event.name === 'JSRoot' && event.cat === 'toplevel') {\n // This is used in createFakeTraceFromCpuProfile to insert a fake event prior to the\n // CPU Profile in order to ensure the trace isn't truncated. So if we see\n // this, we want to treat it as a top level event.\n // TODO(crbug.com/341234884): do we need this?\n return true;\n }\n return event.cat.includes(DevToolsTimelineEventCategory) && event.name === Types.Events.Name.RUN_TASK;\n}\n\nfunction topLevelEventIndexEndingAfter(events: Types.Events.Event[], time: Types.Timing.Micro): number {\n let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1;\n while (index > 0 && !isTopLevelEvent(events[index])) {\n index--;\n }\n return Math.max(index, 0);\n}\nexport function findUpdateLayoutTreeEvents(\n events: Types.Events.Event[], startTime: Types.Timing.Micro,\n endTime?: Types.Timing.Micro): Types.Events.UpdateLayoutTree[] {\n const foundEvents: Types.Events.UpdateLayoutTree[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, startTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const event = events[i];\n if (!Types.Events.isUpdateLayoutTree(event)) {\n continue;\n }\n if (event.ts >= (endTime || Infinity)) {\n continue;\n }\n foundEvents.push(event);\n }\n return foundEvents;\n}\n\nexport function findNextEventAfterTimestamp<T extends Types.Events.Event>(candidates: T[], ts: Types.Timing.Micro): T|\n null {\n const index = Platform.ArrayUtilities.nearestIndexFromBeginning(candidates, candidate => ts < candidate.ts);\n return index === null ? null : candidates[index];\n}\n\nexport function findPreviousEventBeforeTimestamp<T extends Types.Events.Event>(\n candidates: T[], ts: Types.Timing.Micro): T|null {\n const index = Platform.ArrayUtilities.nearestIndexFromEnd(candidates, candidate => candidate.ts < ts);\n return index === null ? null : candidates[index];\n}\n\nexport interface ForEachEventConfig {\n onStartEvent: (event: Types.Events.Event) => void;\n onEndEvent: (event: Types.Events.Event) => void;\n onInstantEvent?: (event: Types.Events.Event) => void;\n eventFilter?: (event: Types.Events.Event) => boolean;\n startTime?: Types.Timing.Micro;\n endTime?: Types.Timing.Micro;\n /* If async events should be skipped. Defaults to true */\n ignoreAsyncEvents?: boolean;\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * dictated by the corresponding timestamp.\n *\n * Events are assumed to be in ascendent order by timestamp.\n *\n * Events with 0 duration are treated as instant events. These do not have a\n * begin and end, but will be passed to the config.onInstantEvent callback as\n * they are discovered. Do not provide this callback if you are not interested\n * in them.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n * By default, async events are skipped. This behaviour can be\n * overridden making use of the config.ignoreAsyncEvents parameter.\n */\nexport function forEachEvent(\n events: Types.Events.Event[],\n config: ForEachEventConfig,\n ): void {\n const globalStartTime = config.startTime ?? Types.Timing.Micro(0);\n const globalEndTime = config.endTime || Types.Timing.Micro(Infinity);\n const ignoreAsyncEvents = config.ignoreAsyncEvents === false ? false : true;\n\n const stack: Types.Events.Event[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, globalStartTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const currentEvent = events[i];\n const currentEventTimings = eventTimingsMicroSeconds(currentEvent);\n if (currentEventTimings.endTime < globalStartTime) {\n continue;\n }\n if (currentEventTimings.startTime > globalEndTime) {\n break;\n }\n\n const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.Events.isPhaseAsync(currentEvent.ph);\n if (isIgnoredAsyncEvent || Types.Events.isFlowPhase(currentEvent.ph)) {\n continue;\n }\n\n // If we have now reached an event that is after a bunch of events, we need\n // to call the onEndEvent callback for those events before moving on.\n let lastEventOnStack = stack.at(-1);\n let lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n while (lastEventOnStack && lastEventEndTime && lastEventEndTime <= currentEventTimings.startTime) {\n stack.pop();\n config.onEndEvent(lastEventOnStack);\n lastEventOnStack = stack.at(-1);\n lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n }\n\n // Now we have dealt with all events prior to this one, see if we need to care about this one.\n if (config.eventFilter && !config.eventFilter(currentEvent)) {\n // The user has chosen to filter this event out, so continue on and do nothing\n continue;\n }\n\n if (currentEventTimings.duration) {\n config.onStartEvent(currentEvent);\n stack.push(currentEvent);\n } else if (config.onInstantEvent) {\n // An event with 0 duration is an instant event.\n config.onInstantEvent(currentEvent);\n }\n }\n\n // Now we have finished looping over all events; any events remaining on the\n // stack need to have their onEndEvent called.\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n config.onEndEvent(last);\n }\n }\n}\n\n// Parsed categories are cached to prevent calling cat.split()\n// multiple times on the same categories string.\nconst parsedCategories = new Map<string, Set<string>>();\nexport function eventHasCategory(event: Types.Events.Event, category: string): boolean {\n let parsedCategoriesForEvent = parsedCategories.get(event.cat);\n if (!parsedCategoriesForEvent) {\n parsedCategoriesForEvent = new Set(event.cat.split(',') || []);\n }\n return parsedCategoriesForEvent.has(category);\n}\n\n/**\n * This compares Types.Events.CallFrame with Protocol.Runtime.CallFrame and checks for equality.\n */\nexport function isMatchingCallFrame(\n eventFrame: Types.Events.CallFrame, nodeFrame: Protocol.Runtime.CallFrame): boolean {\n return eventFrame.columnNumber === nodeFrame.columnNumber && eventFrame.lineNumber === nodeFrame.lineNumber &&\n String(eventFrame.scriptId) === nodeFrame.scriptId && eventFrame.url === nodeFrame.url &&\n eventFrame.functionName === nodeFrame.functionName;\n}\n\nexport function eventContainsTimestamp(event: Types.Events.Event, ts: Types.Timing.Micro): boolean {\n return event.ts <= ts && event.ts + (event.dur || 0) >= ts;\n}\n\nexport function extractSampleTraceId(event: Types.Events.Event): number|null {\n if (!event.args) {\n return null;\n }\n if ('beginData' in event.args) {\n const beginData = event.args['beginData'] as {sampleTraceId?: number};\n return beginData.sampleTraceId ?? null;\n }\n return event.args?.sampleTraceId ?? event.args?.data?.sampleTraceId ?? null;\n}\n"]}
@@ -48,13 +48,14 @@ export declare const UIStrings: {
48
48
  readonly uncompressedDownload: "Uncompressed download";
49
49
  };
50
50
  export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => Record<string, string>;
51
+ export declare function isDocumentLatency(x: InsightModel): x is DocumentLatencyInsightModel;
51
52
  export type DocumentLatencyInsightModel = InsightModel<typeof UIStrings, {
52
53
  data?: {
53
54
  serverResponseTime: Types.Timing.Milli;
54
55
  redirectDuration: Types.Timing.Milli;
55
56
  uncompressedResponseBytes: number;
56
- documentRequest?: Types.Events.SyntheticNetworkRequest;
57
57
  checklist: Checklist<'noRedirects' | 'serverResponseIsFast' | 'usesCompression'>;
58
+ documentRequest?: Types.Events.SyntheticNetworkRequest;
58
59
  };
59
60
  }>;
60
61
  export declare function generateInsight(parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DocumentLatencyInsightModel;
@@ -59,6 +59,9 @@ const TOO_SLOW_THRESHOLD_MS = 600;
59
59
  const TARGET_MS = 100;
60
60
  // Threshold for compression savings.
61
61
  const IGNORE_THRESHOLD_IN_BYTES = 1400;
62
+ export function isDocumentLatency(x) {
63
+ return x.insightKey === 'DocumentLatency';
64
+ }
62
65
  function getServerResponseTime(request) {
63
66
  const timing = request.args.data.timing;
64
67
  if (!timing) {
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type Checklist,\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /**\n *@description Title of an insight that provides a breakdown for how long it took to download the main document.\n */\n title: 'Document request latency',\n /**\n *@description Description of an insight that provides a breakdown for how long it took to download the main document.\n */\n description:\n 'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.',\n /**\n * @description Text to tell the user that the document request does not have redirects.\n */\n passingRedirects: 'Avoids redirects',\n /**\n * @description Text to tell the user that the document request had redirects.\n */\n failedRedirects: 'Had redirects',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.\n */\n passingServerResponseTime: 'Server responds quickly',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.\n */\n failedServerResponseTime: 'Server responded slowly',\n /**\n * @description Text to tell the user that text compression (like gzip) was applied.\n */\n passingTextCompression: 'Applies text compression',\n /**\n * @description Text to tell the user that text compression (like gzip) was not applied.\n */\n failedTextCompression: 'No compression applied',\n /**\n * @description Text for a label describing a network request event as having redirects.\n */\n redirectsLabel: 'Redirects',\n /**\n * @description Text for a label describing a network request event as taking too long to start delivery by the server.\n */\n serverResponseTimeLabel: 'Server response time',\n /**\n * @description Text for a label describing a network request event as taking longer to download because it wasn't compressed.\n */\n uncompressedDownload: 'Uncompressed download',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.\n// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.\nconst TOO_SLOW_THRESHOLD_MS = 600;\nconst TARGET_MS = 100;\n\n// Threshold for compression savings.\nconst IGNORE_THRESHOLD_IN_BYTES = 1400;\n\nexport type DocumentLatencyInsightModel = InsightModel<typeof UIStrings, {\n data?: {\n serverResponseTime: Types.Timing.Milli,\n redirectDuration: Types.Timing.Milli,\n uncompressedResponseBytes: number,\n documentRequest?: Types.Events.SyntheticNetworkRequest,\n checklist: Checklist<'noRedirects'|'serverResponseIsFast'|'usesCompression'>,\n },\n}>;\n\nfunction getServerResponseTime(request: Types.Events.SyntheticNetworkRequest): Types.Timing.Milli|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n const ms = Helpers.Timing.microToMilli(request.args.data.syntheticData.waiting);\n return Math.round(ms) as Types.Timing.Milli;\n}\n\nfunction getCompressionSavings(request: Types.Events.SyntheticNetworkRequest): number {\n // Check from headers if compression was already applied.\n // Older devtools logs are lower case, while modern logs are Cased-Like-This.\n const patterns = [\n /^content-encoding$/i,\n /^x-content-encoding-over-network$/i,\n ];\n const compressionTypes = ['gzip', 'br', 'deflate', 'zstd'];\n const isCompressed = request.args.data.responseHeaders.some(\n header => patterns.some(p => header.name.match(p)) && compressionTypes.includes(header.value));\n if (isCompressed) {\n return 0;\n }\n\n // We don't know how many bytes this asset used on the network, but we can guess it was\n // roughly the size of the content gzipped.\n // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples\n // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers\n // See https://letstalkaboutwebperf.com/en/gzip-brotli-server-config/ for MIME types to compress\n const originalSize = request.args.data.decodedBodyLength;\n let estimatedSavings = 0;\n switch (request.args.data.mimeType) {\n case 'text/css':\n // Stylesheets tend to compress extremely well.\n estimatedSavings = Math.round(originalSize * 0.8);\n break;\n case 'text/html':\n case 'text/javascript':\n // Scripts and HTML compress fairly well too.\n estimatedSavings = Math.round(originalSize * 0.67);\n break;\n case 'text/plain':\n case 'text/xml':\n case 'text/x-component':\n case 'application/javascript':\n case 'application/json':\n case 'application/manifest+json':\n case 'application/vnd.api+json':\n case 'application/xml':\n case 'application/xhtml+xml':\n case 'application/rss+xml':\n case 'application/atom+xml':\n case 'application/vnd.ms-fontobject':\n case 'application/x-font-ttf':\n case 'application/x-font-opentype':\n case 'application/x-font-truetype':\n case 'image/svg+xml':\n case 'image/x-icon':\n case 'image/vnd.microsoft.icon':\n case 'font/ttf':\n case 'font/eot':\n case 'font/otf':\n case 'font/opentype':\n // Use the average savings in HTTPArchive.\n estimatedSavings = Math.round(originalSize * 0.5);\n break;\n default: // Any other MIME types are likely already compressed.\n }\n // Check if the estimated savings are greater than the byte ignore threshold.\n // Note that the estimated gzip savings are always more than 10%, so there is\n // no percent threshold.\n return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;\n}\n\nfunction finalize(partialModel: PartialInsightModel<DocumentLatencyInsightModel>): DocumentLatencyInsightModel {\n let hasFailure = false;\n if (partialModel.data) {\n hasFailure = !partialModel.data.checklist.usesCompression.value ||\n !partialModel.data.checklist.serverResponseIsFast.value || !partialModel.data.checklist.noRedirects.value;\n }\n\n return {\n insightKey: InsightKeys.DOCUMENT_LATENCY,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: hasFailure ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DocumentLatencyInsightModel {\n if (!context.navigation) {\n return finalize({});\n }\n\n const documentRequest =\n parsedTrace.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!documentRequest) {\n return finalize({warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});\n }\n\n const serverResponseTime = getServerResponseTime(documentRequest);\n if (serverResponseTime === null) {\n throw new Error('missing document request timing');\n }\n\n const serverResponseTooSlow = serverResponseTime > TOO_SLOW_THRESHOLD_MS;\n\n let overallSavingsMs = 0;\n if (serverResponseTime > TOO_SLOW_THRESHOLD_MS) {\n overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);\n }\n\n const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);\n overallSavingsMs += redirectDuration;\n\n const metricSavings = {\n FCP: overallSavingsMs as Types.Timing.Milli,\n LCP: overallSavingsMs as Types.Timing.Milli,\n };\n\n const uncompressedResponseBytes = getCompressionSavings(documentRequest);\n\n const noRedirects = redirectDuration === 0;\n const serverResponseIsFast = !serverResponseTooSlow;\n const usesCompression = uncompressedResponseBytes === 0;\n\n return finalize({\n relatedEvents: [documentRequest],\n data: {\n serverResponseTime,\n redirectDuration: Types.Timing.Milli(redirectDuration),\n uncompressedResponseBytes,\n documentRequest,\n checklist: {\n noRedirects: {\n label: noRedirects ? i18nString(UIStrings.passingRedirects) : i18nString(UIStrings.failedRedirects),\n value: noRedirects\n },\n serverResponseIsFast: {\n label: serverResponseIsFast ? i18nString(UIStrings.passingServerResponseTime) :\n i18nString(UIStrings.failedServerResponseTime),\n value: serverResponseIsFast\n },\n usesCompression: {\n label: usesCompression ? i18nString(UIStrings.passingTextCompression) :\n i18nString(UIStrings.failedTextCompression),\n value: usesCompression\n },\n },\n },\n metricSavings,\n });\n}\n"]}
1
+ {"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type Checklist,\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /**\n *@description Title of an insight that provides a breakdown for how long it took to download the main document.\n */\n title: 'Document request latency',\n /**\n *@description Description of an insight that provides a breakdown for how long it took to download the main document.\n */\n description:\n 'Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression.',\n /**\n * @description Text to tell the user that the document request does not have redirects.\n */\n passingRedirects: 'Avoids redirects',\n /**\n * @description Text to tell the user that the document request had redirects.\n */\n failedRedirects: 'Had redirects',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.\n */\n passingServerResponseTime: 'Server responds quickly',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.\n */\n failedServerResponseTime: 'Server responded slowly',\n /**\n * @description Text to tell the user that text compression (like gzip) was applied.\n */\n passingTextCompression: 'Applies text compression',\n /**\n * @description Text to tell the user that text compression (like gzip) was not applied.\n */\n failedTextCompression: 'No compression applied',\n /**\n * @description Text for a label describing a network request event as having redirects.\n */\n redirectsLabel: 'Redirects',\n /**\n * @description Text for a label describing a network request event as taking too long to start delivery by the server.\n */\n serverResponseTimeLabel: 'Server response time',\n /**\n * @description Text for a label describing a network request event as taking longer to download because it wasn't compressed.\n */\n uncompressedDownload: 'Uncompressed download',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/DocumentLatency.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.\n// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.\nconst TOO_SLOW_THRESHOLD_MS = 600;\nconst TARGET_MS = 100;\n\n// Threshold for compression savings.\nconst IGNORE_THRESHOLD_IN_BYTES = 1400;\n\nexport function isDocumentLatency(x: InsightModel): x is DocumentLatencyInsightModel {\n return x.insightKey === 'DocumentLatency';\n}\n\nexport type DocumentLatencyInsightModel = InsightModel<typeof UIStrings, {\n data?: {\n serverResponseTime: Types.Timing.Milli,\n redirectDuration: Types.Timing.Milli,\n uncompressedResponseBytes: number,\n checklist: Checklist<'noRedirects'|'serverResponseIsFast'|'usesCompression'>,\n documentRequest?: Types.Events.SyntheticNetworkRequest,\n },\n}>;\n\nfunction getServerResponseTime(request: Types.Events.SyntheticNetworkRequest): Types.Timing.Milli|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n const ms = Helpers.Timing.microToMilli(request.args.data.syntheticData.waiting);\n return Math.round(ms) as Types.Timing.Milli;\n}\n\nfunction getCompressionSavings(request: Types.Events.SyntheticNetworkRequest): number {\n // Check from headers if compression was already applied.\n // Older devtools logs are lower case, while modern logs are Cased-Like-This.\n const patterns = [\n /^content-encoding$/i,\n /^x-content-encoding-over-network$/i,\n ];\n const compressionTypes = ['gzip', 'br', 'deflate', 'zstd'];\n const isCompressed = request.args.data.responseHeaders.some(\n header => patterns.some(p => header.name.match(p)) && compressionTypes.includes(header.value));\n if (isCompressed) {\n return 0;\n }\n\n // We don't know how many bytes this asset used on the network, but we can guess it was\n // roughly the size of the content gzipped.\n // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples\n // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers\n // See https://letstalkaboutwebperf.com/en/gzip-brotli-server-config/ for MIME types to compress\n const originalSize = request.args.data.decodedBodyLength;\n let estimatedSavings = 0;\n switch (request.args.data.mimeType) {\n case 'text/css':\n // Stylesheets tend to compress extremely well.\n estimatedSavings = Math.round(originalSize * 0.8);\n break;\n case 'text/html':\n case 'text/javascript':\n // Scripts and HTML compress fairly well too.\n estimatedSavings = Math.round(originalSize * 0.67);\n break;\n case 'text/plain':\n case 'text/xml':\n case 'text/x-component':\n case 'application/javascript':\n case 'application/json':\n case 'application/manifest+json':\n case 'application/vnd.api+json':\n case 'application/xml':\n case 'application/xhtml+xml':\n case 'application/rss+xml':\n case 'application/atom+xml':\n case 'application/vnd.ms-fontobject':\n case 'application/x-font-ttf':\n case 'application/x-font-opentype':\n case 'application/x-font-truetype':\n case 'image/svg+xml':\n case 'image/x-icon':\n case 'image/vnd.microsoft.icon':\n case 'font/ttf':\n case 'font/eot':\n case 'font/otf':\n case 'font/opentype':\n // Use the average savings in HTTPArchive.\n estimatedSavings = Math.round(originalSize * 0.5);\n break;\n default: // Any other MIME types are likely already compressed.\n }\n // Check if the estimated savings are greater than the byte ignore threshold.\n // Note that the estimated gzip savings are always more than 10%, so there is\n // no percent threshold.\n return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;\n}\n\nfunction finalize(partialModel: PartialInsightModel<DocumentLatencyInsightModel>): DocumentLatencyInsightModel {\n let hasFailure = false;\n if (partialModel.data) {\n hasFailure = !partialModel.data.checklist.usesCompression.value ||\n !partialModel.data.checklist.serverResponseIsFast.value || !partialModel.data.checklist.noRedirects.value;\n }\n\n return {\n insightKey: InsightKeys.DOCUMENT_LATENCY,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: hasFailure ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DocumentLatencyInsightModel {\n if (!context.navigation) {\n return finalize({});\n }\n\n const documentRequest =\n parsedTrace.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!documentRequest) {\n return finalize({warnings: [InsightWarning.NO_DOCUMENT_REQUEST]});\n }\n\n const serverResponseTime = getServerResponseTime(documentRequest);\n if (serverResponseTime === null) {\n throw new Error('missing document request timing');\n }\n\n const serverResponseTooSlow = serverResponseTime > TOO_SLOW_THRESHOLD_MS;\n\n let overallSavingsMs = 0;\n if (serverResponseTime > TOO_SLOW_THRESHOLD_MS) {\n overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);\n }\n\n const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);\n overallSavingsMs += redirectDuration;\n\n const metricSavings = {\n FCP: overallSavingsMs as Types.Timing.Milli,\n LCP: overallSavingsMs as Types.Timing.Milli,\n };\n\n const uncompressedResponseBytes = getCompressionSavings(documentRequest);\n\n const noRedirects = redirectDuration === 0;\n const serverResponseIsFast = !serverResponseTooSlow;\n const usesCompression = uncompressedResponseBytes === 0;\n\n return finalize({\n relatedEvents: [documentRequest],\n data: {\n serverResponseTime,\n redirectDuration: Types.Timing.Milli(redirectDuration),\n uncompressedResponseBytes,\n documentRequest,\n checklist: {\n noRedirects: {\n label: noRedirects ? i18nString(UIStrings.passingRedirects) : i18nString(UIStrings.failedRedirects),\n value: noRedirects\n },\n serverResponseIsFast: {\n label: serverResponseIsFast ? i18nString(UIStrings.passingServerResponseTime) :\n i18nString(UIStrings.failedServerResponseTime),\n value: serverResponseIsFast\n },\n usesCompression: {\n label: usesCompression ? i18nString(UIStrings.passingTextCompression) :\n i18nString(UIStrings.failedTextCompression),\n value: usesCompression\n },\n },\n },\n metricSavings,\n });\n}\n"]}
@@ -5,14 +5,19 @@ export declare const UIStrings: {
5
5
  /**
6
6
  * @description Title of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.
7
7
  */
8
- readonly title: "Duplicate JavaScript";
8
+ readonly title: "Duplicated JavaScript";
9
9
  /**
10
10
  * @description Description of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.
11
11
  */
12
12
  readonly description: "Remove large, duplicate JavaScript modules from bundles to reduce unnecessary bytes consumed by network activity.";
13
+ /** Label for a column in a data table; entries will be the locations of JavaScript or CSS code, e.g. the name of a Javascript package or module. */
14
+ readonly columnSource: "Source";
15
+ /** Label for a column in a data table; entries will be the file size of a web resource in kilobytes. */
16
+ readonly columnResourceSize: "Resource size";
13
17
  };
14
18
  export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => Record<string, string>;
15
19
  export type DuplicateJavaScriptInsightModel = InsightModel<typeof UIStrings, {
16
20
  duplication: Extras.ScriptDuplication.ScriptDuplication;
21
+ scriptsWithDuplication: Handlers.ModelHandlers.Scripts.Script[];
17
22
  }>;
18
23
  export declare function generateInsight(parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DuplicateJavaScriptInsightModel;
@@ -9,18 +9,23 @@ export const UIStrings = {
9
9
  /**
10
10
  * @description Title of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.
11
11
  */
12
- title: 'Duplicate JavaScript',
12
+ title: 'Duplicated JavaScript',
13
13
  /**
14
14
  * @description Description of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.
15
15
  */
16
16
  description: 'Remove large, duplicate JavaScript modules from bundles to reduce unnecessary bytes consumed by network activity.',
17
+ /** Label for a column in a data table; entries will be the locations of JavaScript or CSS code, e.g. the name of a Javascript package or module. */
18
+ columnSource: 'Source',
19
+ /** Label for a column in a data table; entries will be the file size of a web resource in kilobytes. */
20
+ columnResourceSize: 'Resource size',
17
21
  };
18
- // const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DuplicateJavaScript.ts', UIStrings);
22
+ // const str_ = i18n.i18n.registerUIStrings('models/trace/insights/DuplicatedJavaScript.ts', UIStrings);
19
23
  export const i18nString = (i18nId, values) => ({i18nId, values}); // i18n.i18n.getLocalizedString.bind(undefined, str_);
20
24
  function finalize(partialModel) {
21
- const requests = [...partialModel.duplication.values().flatMap(array => array.map(v => v.script.request))].filter(e => !!e); // eslint-disable-line no-implicit-coercion
25
+ const requests = partialModel.scriptsWithDuplication.map(script => script.request)
26
+ .filter(e => !!e); // eslint-disable-line no-implicit-coercion
22
27
  return {
23
- insightKey: "DuplicateJavaScript" /* InsightKeys.DUPLICATE_JAVASCRIPT */,
28
+ insightKey: "DuplicatedJavaScript" /* InsightKeys.DUPLICATE_JAVASCRIPT */,
24
29
  strings: UIStrings,
25
30
  title: i18nString(UIStrings.title),
26
31
  description: i18nString(UIStrings.description),
@@ -41,6 +46,10 @@ export function generateInsight(parsedTrace, context) {
41
46
  return Helpers.Timing.timestampIsInBounds(context.bounds, script.ts);
42
47
  });
43
48
  const duplication = Extras.ScriptDuplication.computeScriptDuplication({ scripts });
44
- return finalize({ duplication });
49
+ const scriptsWithDuplication = [...duplication.values().flatMap(data => data.duplicates.map(d => d.script))];
50
+ return finalize({
51
+ duplication,
52
+ scriptsWithDuplication: [...new Set(scriptsWithDuplication)],
53
+ });
45
54
  }
46
- //# sourceMappingURL=DuplicateJavaScript.js.map
55
+ //# sourceMappingURL=DuplicatedJavaScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuplicatedJavaScript.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DuplicatedJavaScript.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EACL,eAAe,GAKhB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB;;OAEG;IACH,KAAK,EAAE,uBAAuB;IAC9B;;OAEG;IACH,WAAW,EACP,mHAAmH;IACvH,oJAAoJ;IACpJ,YAAY,EAAE,QAAQ;IACtB,wGAAwG;IACxG,kBAAkB,EAAE,eAAe;CAC3B,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,+CAA+C,EAAE,SAAS,CAAC,CAAC;AACrG,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAO7E,SAAS,QAAQ,CAAC,YAAkE;IAClF,MAAM,QAAQ,GAAG,YAAY,CAAC,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;SAC5D,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,2CAA2C;IAEpF,OAAO;QACL,UAAU,+DAAkC;QAC5C,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;QAClC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QAC9C,QAAQ,EAAE,eAAe,CAAC,GAAG;QAC7B,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAChF,aAAa,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAuC,EAAE,OAA0B;IACrE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;QAC1D,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,CAAC,EAAC,OAAO,EAAC,CAAC,CAAC;IACjF,MAAM,sBAAsB,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7G,OAAO,QAAQ,CAAC;QACd,WAAW;QACX,sBAAsB,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,CAAC;KAC7D,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright 2025 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 i18n from '../../../core/i18n/i18n.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\n\nimport {\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /**\n * @description Title of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.\n */\n title: 'Duplicated JavaScript',\n /**\n * @description Description of an insight that identifies multiple copies of the same JavaScript sources, and recommends removing the duplication.\n */\n description:\n 'Remove large, duplicate JavaScript modules from bundles to reduce unnecessary bytes consumed by network activity.',\n /** Label for a column in a data table; entries will be the locations of JavaScript or CSS code, e.g. the name of a Javascript package or module. */\n columnSource: 'Source',\n /** Label for a column in a data table; entries will be the file size of a web resource in kilobytes. */\n columnResourceSize: 'Resource size',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/DuplicatedJavaScript.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type DuplicateJavaScriptInsightModel = InsightModel<typeof UIStrings, {\n duplication: Extras.ScriptDuplication.ScriptDuplication,\n scriptsWithDuplication: Handlers.ModelHandlers.Scripts.Script[],\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<DuplicateJavaScriptInsightModel>): DuplicateJavaScriptInsightModel {\n const requests = partialModel.scriptsWithDuplication.map(script => script.request)\n .filter(e => !!e); // eslint-disable-line no-implicit-coercion\n\n return {\n insightKey: InsightKeys.DUPLICATE_JAVASCRIPT,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.LCP,\n state: Boolean(partialModel.duplication.values().next().value) ? 'fail' : 'pass',\n relatedEvents: [...new Set(requests)],\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DuplicateJavaScriptInsightModel {\n const scripts = parsedTrace.Scripts.scripts.filter(script => {\n if (!context.navigation) {\n return false;\n }\n\n if (script.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.timestampIsInBounds(context.bounds, script.ts);\n });\n\n const duplication = Extras.ScriptDuplication.computeScriptDuplication({scripts});\n const scriptsWithDuplication = [...duplication.values().flatMap(data => data.duplicates.map(d => d.script))];\n return finalize({\n duplication,\n scriptsWithDuplication: [...new Set(scriptsWithDuplication)],\n });\n}\n"]}
@@ -15,7 +15,7 @@ export declare const UIStrings: {
15
15
  readonly wastedTimeColumn: "Wasted time";
16
16
  };
17
17
  export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => {i18nId: string, values: Record<string, string|number>, formattedDefault: string};
18
- interface RemoteFont {
18
+ export interface RemoteFont {
19
19
  name?: string;
20
20
  request: Types.Events.SyntheticNetworkRequest;
21
21
  display: string;
@@ -25,4 +25,3 @@ export type FontDisplayInsightModel = InsightModel<typeof UIStrings, {
25
25
  fonts: RemoteFont[];
26
26
  }>;
27
27
  export declare function generateInsight(parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): FontDisplayInsightModel;
28
- export {};
@@ -1 +1 @@
1
- {"version":3,"file":"FontDisplay.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */\n title: 'Font display',\n /**\n * @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page.\n */\n description:\n 'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).',\n /** Column for a font loaded by the page to render text. */\n fontColumn: 'Font',\n /** Column for the amount of time wasted. */\n wastedTimeColumn: 'Wasted time',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface RemoteFont {\n name?: string;\n request: Types.Events.SyntheticNetworkRequest;\n display: string;\n wastedTime: Types.Timing.Milli;\n}\n\nexport type FontDisplayInsightModel = InsightModel<typeof UIStrings, {\n fonts: RemoteFont[],\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<FontDisplayInsightModel>): FontDisplayInsightModel {\n return {\n insightKey: InsightKeys.FONT_DISPLAY,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n state: partialModel.fonts.find(font => font.wastedTime > 0) ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): FontDisplayInsightModel {\n const fonts: RemoteFont[] = [];\n for (const remoteFont of parsedTrace.LayoutShifts.remoteFonts) {\n const event = remoteFont.beginRemoteFontLoadEvent;\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\n const requestId = `${event.pid}.${event.args.id}`;\n const request = parsedTrace.NetworkRequests.byId.get(requestId);\n if (!request) {\n continue;\n }\n\n if (!/^(block|fallback|auto)$/.test(remoteFont.display)) {\n continue;\n }\n\n const wastedTimeMicro =\n Types.Timing.Micro(request.args.data.syntheticData.finishTime - request.args.data.syntheticData.sendStartTime);\n // TODO(crbug.com/352244504): should really end at the time of the next Commit trace event.\n let wastedTime =\n Platform.NumberUtilities.floor(Helpers.Timing.microToMilli(wastedTimeMicro), 1 / 5) as Types.Timing.Milli;\n if (wastedTime === 0) {\n continue;\n }\n\n // All browsers wait for no more than 3s.\n wastedTime = Math.min(wastedTime, 3000) as Types.Timing.Milli;\n\n fonts.push({\n name: remoteFont.name,\n request,\n display: remoteFont.display,\n wastedTime,\n });\n }\n\n fonts.sort((a, b) => b.wastedTime - a.wastedTime);\n\n const savings = Math.max(...fonts.map(f => f.wastedTime)) as Types.Timing.Milli;\n\n return finalize({\n relatedEvents: fonts.map(f => f.request),\n fonts,\n metricSavings: {FCP: savings},\n });\n}\n"]}
1
+ {"version":3,"file":"FontDisplay.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */\n title: 'Font display',\n /**\n * @description Text to tell the user about the font-display CSS feature to help improve a the UX of a page.\n */\n description:\n 'Consider setting [`font-display`](https://developer.chrome.com/blog/font-display) to `swap` or `optional` to ensure text is consistently visible. `swap` can be further optimized to mitigate layout shifts with [font metric overrides](https://developer.chrome.com/blog/font-fallbacks).',\n /** Column for a font loaded by the page to render text. */\n fontColumn: 'Font',\n /** Column for the amount of time wasted. */\n wastedTimeColumn: 'Wasted time',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/FontDisplay.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport interface RemoteFont {\n name?: string;\n request: Types.Events.SyntheticNetworkRequest;\n display: string;\n wastedTime: Types.Timing.Milli;\n}\n\nexport type FontDisplayInsightModel = InsightModel<typeof UIStrings, {\n fonts: RemoteFont[],\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<FontDisplayInsightModel>): FontDisplayInsightModel {\n return {\n insightKey: InsightKeys.FONT_DISPLAY,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n state: partialModel.fonts.find(font => font.wastedTime > 0) ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): FontDisplayInsightModel {\n const fonts: RemoteFont[] = [];\n for (const remoteFont of parsedTrace.LayoutShifts.remoteFonts) {\n const event = remoteFont.beginRemoteFontLoadEvent;\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\n const requestId = `${event.pid}.${event.args.id}`;\n const request = parsedTrace.NetworkRequests.byId.get(requestId);\n if (!request) {\n continue;\n }\n\n if (!/^(block|fallback|auto)$/.test(remoteFont.display)) {\n continue;\n }\n\n const wastedTimeMicro =\n Types.Timing.Micro(request.args.data.syntheticData.finishTime - request.args.data.syntheticData.sendStartTime);\n // TODO(crbug.com/352244504): should really end at the time of the next Commit trace event.\n let wastedTime =\n Platform.NumberUtilities.floor(Helpers.Timing.microToMilli(wastedTimeMicro), 1 / 5) as Types.Timing.Milli;\n if (wastedTime === 0) {\n continue;\n }\n\n // All browsers wait for no more than 3s.\n wastedTime = Math.min(wastedTime, 3000) as Types.Timing.Milli;\n\n fonts.push({\n name: remoteFont.name,\n request,\n display: remoteFont.display,\n wastedTime,\n });\n }\n\n fonts.sort((a, b) => b.wastedTime - a.wastedTime);\n\n const savings = Math.max(...fonts.map(f => f.wastedTime)) as Types.Timing.Milli;\n\n return finalize({\n relatedEvents: fonts.map(f => f.request),\n fonts,\n metricSavings: {FCP: savings},\n });\n}\n"]}
@@ -1,5 +1,8 @@
1
+ import * as Platform from '../../../core/platform/platform.js';
2
+ import type * as Protocol from '../../../generated/protocol.js';
1
3
  import type * as Handlers from '../handlers/handlers.js';
2
- import { type BottomUpCallStack, type ForcedReflowAggregatedData, type InsightModel, type InsightSetContext } from './types.js';
4
+ import * as Types from '../types/types.js';
5
+ import { type InsightModel, type InsightSetContext } from './types.js';
3
6
  export declare const UIStrings: {
4
7
  /**
5
8
  *@description Title of an insight that provides details about Forced reflow.
@@ -21,10 +24,27 @@ export declare const UIStrings: {
21
24
  * @description Text to describe the total reflow time
22
25
  */
23
26
  readonly totalReflowTime: "Total reflow time";
27
+ /**
28
+ * @description Text to describe CPU processor tasks that could not be attributed to any specific source code.
29
+ */
30
+ readonly unattributed: "Unattributed";
24
31
  };
25
- export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => Record<string, string>;
32
+ export declare const i18nString: (id: string, values?: Record<string, string> | undefined) => {i18nId: string, values: Record<string, string|number>, formattedDefault: string};
26
33
  export type ForcedReflowInsightModel = InsightModel<typeof UIStrings, {
27
34
  topLevelFunctionCallData: ForcedReflowAggregatedData | undefined;
28
35
  aggregatedBottomUpData: BottomUpCallStack[];
29
36
  }>;
30
- export declare function generateInsight(traceParsedData: Handlers.Types.ParsedTrace, _context: InsightSetContext): ForcedReflowInsightModel;
37
+ export interface BottomUpCallStack {
38
+ /**
39
+ * `null` indicates that this data is for unattributed force reflows.
40
+ */
41
+ bottomUpData: Types.Events.CallFrame | Protocol.Runtime.CallFrame | null;
42
+ totalTime: number;
43
+ relatedEvents: Types.Events.Event[];
44
+ }
45
+ export interface ForcedReflowAggregatedData {
46
+ topLevelFunctionCall: Types.Events.CallFrame | Protocol.Runtime.CallFrame;
47
+ totalReflowTime: number;
48
+ topLevelFunctionCallEvents: Types.Events.Event[];
49
+ }
50
+ export declare function generateInsight(traceParsedData: Handlers.Types.ParsedTrace, context: InsightSetContext): ForcedReflowInsightModel;