@paulirish/trace_engine 0.0.56 → 0.0.57

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 (183) hide show
  1. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  2. package/README.md +2 -2
  3. package/generated/protocol.d.ts +51 -23
  4. package/locales/af.json +8 -8
  5. package/locales/am.json +8 -8
  6. package/locales/ar.json +8 -8
  7. package/locales/as.json +8 -8
  8. package/locales/az.json +8 -8
  9. package/locales/be.json +7 -7
  10. package/locales/bg.json +8 -8
  11. package/locales/bn.json +8 -8
  12. package/locales/bs.json +8 -8
  13. package/locales/ca.json +8 -8
  14. package/locales/cs.json +8 -8
  15. package/locales/cy.json +8 -8
  16. package/locales/da.json +8 -8
  17. package/locales/de.json +8 -8
  18. package/locales/el.json +8 -8
  19. package/locales/en-GB.json +8 -8
  20. package/locales/en-US.json +14 -5
  21. package/locales/en-XL.json +14 -5
  22. package/locales/es-419.json +8 -8
  23. package/locales/es.json +8 -8
  24. package/locales/et.json +8 -8
  25. package/locales/eu.json +8 -8
  26. package/locales/fa.json +11 -11
  27. package/locales/fi.json +8 -8
  28. package/locales/fil.json +8 -8
  29. package/locales/fr-CA.json +8 -8
  30. package/locales/fr.json +8 -8
  31. package/locales/gl.json +8 -8
  32. package/locales/gu.json +8 -8
  33. package/locales/he.json +8 -8
  34. package/locales/hi.json +8 -8
  35. package/locales/hr.json +8 -8
  36. package/locales/hu.json +8 -8
  37. package/locales/hy.json +8 -8
  38. package/locales/id.json +8 -8
  39. package/locales/is.json +8 -8
  40. package/locales/it.json +8 -8
  41. package/locales/ja.json +8 -8
  42. package/locales/ka.json +8 -8
  43. package/locales/kk.json +8 -8
  44. package/locales/km.json +8 -8
  45. package/locales/kn.json +7 -7
  46. package/locales/ko.json +8 -8
  47. package/locales/ky.json +7 -7
  48. package/locales/lo.json +8 -8
  49. package/locales/lt.json +8 -8
  50. package/locales/lv.json +8 -8
  51. package/locales/mk.json +8 -8
  52. package/locales/ml.json +8 -8
  53. package/locales/mn.json +8 -8
  54. package/locales/mr.json +7 -7
  55. package/locales/ms.json +7 -7
  56. package/locales/my.json +8 -8
  57. package/locales/ne.json +8 -8
  58. package/locales/nl.json +8 -8
  59. package/locales/no.json +8 -8
  60. package/locales/or.json +8 -8
  61. package/locales/pa.json +7 -7
  62. package/locales/pl.json +8 -8
  63. package/locales/pt-PT.json +8 -8
  64. package/locales/pt.json +8 -8
  65. package/locales/ro.json +8 -8
  66. package/locales/ru.json +8 -8
  67. package/locales/si.json +8 -8
  68. package/locales/sk.json +8 -8
  69. package/locales/sl.json +8 -8
  70. package/locales/sq.json +8 -8
  71. package/locales/sr-Latn.json +8 -8
  72. package/locales/sr.json +8 -8
  73. package/locales/sv.json +8 -8
  74. package/locales/sw.json +7 -7
  75. package/locales/ta.json +8 -8
  76. package/locales/te.json +8 -8
  77. package/locales/th.json +8 -8
  78. package/locales/tr.json +7 -7
  79. package/locales/uk.json +7 -7
  80. package/locales/ur.json +8 -8
  81. package/locales/uz.json +7 -7
  82. package/locales/vi.json +8 -8
  83. package/locales/zh-HK.json +8 -8
  84. package/locales/zh-TW.json +8 -8
  85. package/locales/zh.json +8 -8
  86. package/locales/zu.json +8 -8
  87. package/models/trace/ModelImpl.d.ts +1 -0
  88. package/models/trace/ModelImpl.js +2 -4
  89. package/models/trace/ModelImpl.js.map +1 -1
  90. package/models/trace/Processor.js +18 -12
  91. package/models/trace/Processor.js.map +1 -1
  92. package/models/trace/extras/TraceTree.d.ts +0 -1
  93. package/models/trace/extras/TraceTree.js +0 -3
  94. package/models/trace/extras/TraceTree.js.map +1 -1
  95. package/models/trace/handlers/ExtensionTraceDataHandler.js +28 -14
  96. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  97. package/models/trace/handlers/NetworkRequestsHandler.js +9 -2
  98. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  99. package/models/trace/handlers/SamplesHandler.js +2 -6
  100. package/models/trace/handlers/SamplesHandler.js.map +1 -1
  101. package/models/trace/handlers/SelectorStatsHandler.d.ts +17 -0
  102. package/models/trace/handlers/SelectorStatsHandler.js +42 -0
  103. package/models/trace/handlers/SelectorStatsHandler.js.map +1 -1
  104. package/models/trace/helpers/SamplesIntegrator.js +14 -22
  105. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  106. package/models/trace/helpers/SyntheticEvents.d.ts +0 -6
  107. package/models/trace/helpers/SyntheticEvents.js +2 -2
  108. package/models/trace/helpers/SyntheticEvents.js.map +1 -1
  109. package/models/trace/helpers/Timing.d.ts +5 -0
  110. package/models/trace/helpers/Timing.js +53 -3
  111. package/models/trace/helpers/Timing.js.map +1 -1
  112. package/models/trace/insights/CLSCulprits.d.ts +1 -0
  113. package/models/trace/insights/CLSCulprits.js +22 -0
  114. package/models/trace/insights/CLSCulprits.js.map +1 -1
  115. package/models/trace/insights/Cache.d.ts +2 -0
  116. package/models/trace/insights/Cache.js +10 -0
  117. package/models/trace/insights/Cache.js.map +1 -1
  118. package/models/trace/insights/DOMSize.d.ts +1 -0
  119. package/models/trace/insights/DOMSize.js +8 -0
  120. package/models/trace/insights/DOMSize.js.map +1 -1
  121. package/models/trace/insights/DocumentLatency.d.ts +1 -0
  122. package/models/trace/insights/DocumentLatency.js +42 -0
  123. package/models/trace/insights/DocumentLatency.js.map +1 -1
  124. package/models/trace/insights/DuplicatedJavaScript.d.ts +2 -0
  125. package/models/trace/insights/DuplicatedJavaScript.js +9 -0
  126. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
  127. package/models/trace/insights/FontDisplay.d.ts +1 -0
  128. package/models/trace/insights/FontDisplay.js +7 -0
  129. package/models/trace/insights/FontDisplay.js.map +1 -1
  130. package/models/trace/insights/ForcedReflow.d.ts +2 -0
  131. package/models/trace/insights/ForcedReflow.js +17 -0
  132. package/models/trace/insights/ForcedReflow.js.map +1 -1
  133. package/models/trace/insights/INPBreakdown.d.ts +6 -0
  134. package/models/trace/insights/INPBreakdown.js +31 -0
  135. package/models/trace/insights/INPBreakdown.js.map +1 -1
  136. package/models/trace/insights/ImageDelivery.d.ts +2 -0
  137. package/models/trace/insights/ImageDelivery.js +10 -0
  138. package/models/trace/insights/ImageDelivery.js.map +1 -1
  139. package/models/trace/insights/LCPBreakdown.d.ts +1 -0
  140. package/models/trace/insights/LCPBreakdown.js +23 -4
  141. package/models/trace/insights/LCPBreakdown.js.map +1 -1
  142. package/models/trace/insights/LCPDiscovery.d.ts +12 -0
  143. package/models/trace/insights/LCPDiscovery.js +58 -0
  144. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  145. package/models/trace/insights/LegacyJavaScript.d.ts +2 -0
  146. package/models/trace/insights/LegacyJavaScript.js +9 -0
  147. package/models/trace/insights/LegacyJavaScript.js.map +1 -1
  148. package/models/trace/insights/ModernHTTP.d.ts +8 -5
  149. package/models/trace/insights/ModernHTTP.js +26 -13
  150. package/models/trace/insights/ModernHTTP.js.map +1 -1
  151. package/models/trace/insights/NetworkDependencyTree.d.ts +1 -0
  152. package/models/trace/insights/NetworkDependencyTree.js +25 -1
  153. package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
  154. package/models/trace/insights/RenderBlocking.d.ts +2 -0
  155. package/models/trace/insights/RenderBlocking.js +10 -0
  156. package/models/trace/insights/RenderBlocking.js.map +1 -1
  157. package/models/trace/insights/SlowCSSSelector.d.ts +11 -2
  158. package/models/trace/insights/SlowCSSSelector.js +33 -14
  159. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  160. package/models/trace/insights/ThirdParties.d.ts +3 -0
  161. package/models/trace/insights/ThirdParties.js +31 -0
  162. package/models/trace/insights/ThirdParties.js.map +1 -1
  163. package/models/trace/insights/Viewport.d.ts +2 -1
  164. package/models/trace/insights/Viewport.js +16 -0
  165. package/models/trace/insights/Viewport.js.map +1 -1
  166. package/models/trace/insights/types.d.ts +4 -1
  167. package/models/trace/insights/types.js +1 -0
  168. package/models/trace/insights/types.js.map +1 -1
  169. package/models/trace/types/Extensions.d.ts +13 -1
  170. package/models/trace/types/Extensions.js +5 -1
  171. package/models/trace/types/Extensions.js.map +1 -1
  172. package/models/trace/types/Overlays.d.ts +110 -0
  173. package/models/trace/types/Overlays.js +5 -0
  174. package/models/trace/types/Overlays.js.map +1 -0
  175. package/models/trace/types/TraceEvents.d.ts +27 -9
  176. package/models/trace/types/TraceEvents.js +7 -18
  177. package/models/trace/types/TraceEvents.js.map +1 -1
  178. package/models/trace/types/types-tsconfig.json +1 -0
  179. package/models/trace/types/types.d.ts +1 -0
  180. package/models/trace/types/types.js +1 -0
  181. package/models/trace/types/types.js.map +1 -1
  182. package/package.json +1 -1
  183. package/test/test-trace-engine.mjs +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.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 {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.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 /**\n *@description Title of an insight that provides details about slow CSS selectors.\n */\n title: 'CSS Selector costs',\n\n /**\n * @description Text to describe how to improve the performance of CSS selectors.\n */\n description:\n 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',\n /**\n *@description Column name for count of elements that the engine attempted to match against a style rule\n */\n matchAttempts: 'Match attempts',\n /**\n *@description Column name for count of elements that matched a style rule\n */\n matchCount: 'Match count',\n /**\n *@description Column name for elapsed time spent computing a style rule\n */\n elapsed: 'Elapsed time',\n /**\n *@description Column name for the selectors that took the longest amount of time/effort.\n */\n topSelectors: 'Top selectors',\n /**\n *@description Column name for a total sum.\n */\n total: 'Total',\n /**\n * @description Text status indicating that no CSS selector data was found.\n */\n enableSelectorData:\n 'No CSS selector data was found. CSS selector stats need to be enabled in the performance panel settings.',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type SlowCSSSelectorInsightModel = InsightModel<typeof UIStrings, {\n totalElapsedMs: Types.Timing.Milli,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topElapsedMs: Types.Events.SelectorTiming[],\n topMatchAttempts: Types.Events.SelectorTiming[],\n}>;\n\nfunction aggregateSelectorStats(\n data: Map<Types.Events.UpdateLayoutTree, {\n timings: Types.Events.SelectorTiming[],\n }>,\n context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map<String, SelectorTiming>();\n\n for (const [event, value] of data) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nfunction finalize(partialModel: PartialInsightModel<SlowCSSSelectorInsightModel>): SlowCSSSelectorInsightModel {\n return {\n insightKey: InsightKeys.SLOW_CSS_SELECTOR,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: partialModel.topElapsedMs.length !== 0 && partialModel.topMatchAttempts.length !== 0 ? 'informative' :\n 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): SlowCSSSelectorInsightModel {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent, context);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n // sort by elapsed time\n const sortByElapsedMs = [...selectorTimings].sort((a, b) => {\n return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];\n });\n\n // sort by match attempts\n const sortByMatchAttempts = [...selectorTimings].sort((a, b) => {\n return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];\n });\n\n return finalize({\n // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\n totalElapsedMs: Types.Timing.Milli(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topElapsedMs: sortByElapsedMs.slice(0, 3),\n topMatchAttempts: sortByMatchAttempts.slice(0, 3),\n });\n}\n"]}
1
+ {"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AAGnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAsB,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EACL,eAAe,EACf,WAAW,GAIZ,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB;;OAEG;IACH,KAAK,EAAE,oBAAoB;IAE3B;;OAEG;IACH,WAAW,EACP,yUAAyU;IAC7U;;OAEG;IACH,aAAa,EAAE,gBAAgB;IAC/B;;OAEG;IACH,UAAU,EAAE,aAAa;IACzB;;OAEG;IACH,OAAO,EAAE,cAAc;IACvB;;OAEG;IACH,YAAY,EAAE,eAAe;IAC7B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,kBAAkB,EACd,0GAA0G;IAC9G;;OAEG;IACH,sBAAsB,EAAE,4BAA4B;IACpD;;OAEG;IACH,uBAAuB,EAAE,4BAA4B;CAC7C,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,0CAA0C,EAAE,SAAS,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC7E,MAAM,wBAAwB,GAAG,GAAG,CAAC,CAAE,qCAAqC;AAU5E,SAAS,sBAAsB,CAAC,IAAuB,EAAE,OAA0B;IACjF,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEtD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC3D,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,SAAS;QACX,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;YAChG,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC7B,UAAU,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBAC7E,UAAU,CAAC,kBAAkB,CAAC,eAAe,CAAC,IAAI,MAAM,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;gBAC7F,UAAU,CAAC,kBAAkB,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;gBACzF,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;YACrF,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAC,GAAG,MAAM,EAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,QAAQ,CAAC,YAA8D;IAC9E,OAAO;QACL,UAAU,EAAE,WAAW,CAAC,iBAAiB;QACzC,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,YAAY,CAAC,oBAAoB,IAAI,YAAY,CAAC,wBAAwB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM;QAC1G,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAuC,EAAE,OAA0B;IACrE,MAAM,iBAAiB,GAAG,WAAW,CAAC,aAAa,CAAC;IAEpD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,eAAe,GAAG,sBAAsB,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAE3E,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,IAAI,eAAe,GAAG,CAAC,CAAC;IAExB,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;QAC3B,cAAc,IAAI,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACrD,kBAAkB,IAAI,MAAM,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAC/D,eAAe,IAAI,MAAM,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,IAAI,oBAAoB,GAAwB,IAAI,CAAC;IACrD,IAAI,wBAAwB,GAAwB,IAAI,CAAC;IAEzD,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,2CAA2C;QAC3C,oBAAoB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACrD,OAAO,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;QAEH,wEAAwE;QACxE,IAAI,oBAAoB,IAAI,oBAAoB,CAAC,kBAAkB,CAAC,OAAO,CAAC,GAAG,wBAAwB,EAAE,CAAC;YACxG,oBAAoB,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED,6CAA6C;QAC7C,wBAAwB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzD,OAAO,CAAC,CAAC,kBAAkB,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,0EAA0E;QAC1E,aAAa,EAAE,EAAE;QACjB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC;QAC3D,kBAAkB;QAClB,eAAe;QACf,oBAAoB;QACpB,wBAAwB;KACzB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAA8B;IAC3D,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type {SelectorStatsData} from '../handlers/SelectorStatsHandler.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.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 /**\n *@description Title of an insight that provides details about slow CSS selectors.\n */\n title: 'CSS Selector costs',\n\n /**\n * @description Text to describe how to improve the performance of CSS selectors.\n */\n description:\n 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',\n /**\n *@description Column name for count of elements that the engine attempted to match against a style rule\n */\n matchAttempts: 'Match attempts',\n /**\n *@description Column name for count of elements that matched a style rule\n */\n matchCount: 'Match count',\n /**\n *@description Column name for elapsed time spent computing a style rule\n */\n elapsed: 'Elapsed time',\n /**\n *@description Column name for the selectors that took the longest amount of time/effort.\n */\n topSelectors: 'Top selectors',\n /**\n *@description Column name for a total sum.\n */\n total: 'Total',\n /**\n * @description Text status indicating that no CSS selector data was found.\n */\n enableSelectorData:\n 'No CSS selector data was found. CSS selector stats need to be enabled in the performance panel settings.',\n /**\n *@description top CSS selector when ranked by elapsed time in ms\n */\n topSelectorElapsedTime: 'Top selector elaspsed time',\n /**\n *@description top CSS selector when ranked by match attempt\n */\n topSelectorMatchAttempt: 'Top selector match attempt',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst slowCSSSelectorThreshold = 500; // 500us threshold for slow selectors\n\nexport type SlowCSSSelectorInsightModel = InsightModel<typeof UIStrings, {\n totalElapsedMs: Types.Timing.Milli,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topSelectorElapsedMs: Types.Events.SelectorTiming | null,\n topSelectorMatchAttempts: Types.Events.SelectorTiming | null,\n}>;\n\nfunction aggregateSelectorStats(data: SelectorStatsData, context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map<String, SelectorTiming>();\n\n for (const [event, value] of data.dataForUpdateLayoutEvent) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nfunction finalize(partialModel: PartialInsightModel<SlowCSSSelectorInsightModel>): SlowCSSSelectorInsightModel {\n return {\n insightKey: InsightKeys.SLOW_CSS_SELECTOR,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: partialModel.topSelectorElapsedMs && partialModel.topSelectorMatchAttempts ? 'informative' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): SlowCSSSelectorInsightModel {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData, context);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n let topSelectorElapsedMs: SelectorTiming|null = null;\n let topSelectorMatchAttempts: SelectorTiming|null = null;\n\n if (selectorTimings.length > 0) {\n // find the selector with most elapsed time\n topSelectorElapsedMs = selectorTimings.reduce((a, b) => {\n return a[SelectorTimingsKey.Elapsed] > b[SelectorTimingsKey.Elapsed] ? a : b;\n });\n\n // check if the slowest selector is slow enough to trigger insights info\n if (topSelectorElapsedMs && topSelectorElapsedMs[SelectorTimingsKey.Elapsed] < slowCSSSelectorThreshold) {\n topSelectorElapsedMs = null;\n }\n\n // find the selector with most match attempts\n topSelectorMatchAttempts = selectorTimings.reduce((a, b) => {\n return a[SelectorTimingsKey.MatchAttempts] > b[SelectorTimingsKey.MatchAttempts] ? a : b;\n });\n }\n\n return finalize({\n // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\n totalElapsedMs: Types.Timing.Milli(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topSelectorElapsedMs,\n topSelectorMatchAttempts,\n });\n}\n\nexport function createOverlays(_: SlowCSSSelectorInsightModel): Types.Overlays.Overlay[] {\n return [];\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import * as Extras from '../extras/extras.js';
2
2
  import * as Handlers from '../handlers/handlers.js';
3
+ import type * as Types from '../types/types.js';
3
4
  import { type InsightModel, type InsightSetContext } from './types.js';
4
5
  export declare const UIStrings: {
5
6
  /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as "third-party code"). */
@@ -27,3 +28,5 @@ export type ThirdPartiesInsightModel = InsightModel<typeof UIStrings, {
27
28
  firstPartyEntity?: Extras.ThirdParties.Entity;
28
29
  }>;
29
30
  export declare function generateInsight(parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ThirdPartiesInsightModel;
31
+ export declare function createOverlaysForSummary(summary: Extras.ThirdParties.EntitySummary): Types.Overlays.Overlay[];
32
+ export declare function createOverlays(model: ThirdPartiesInsightModel): Types.Overlays.Overlay[];
@@ -61,4 +61,35 @@ export function generateInsight(parsedTrace, context) {
61
61
  entitySummaries,
62
62
  });
63
63
  }
64
+ export function createOverlaysForSummary(summary) {
65
+ const overlays = [];
66
+ for (const event of summary.relatedEvents) {
67
+ // The events found for a third party can be vast, as they gather every
68
+ // single main thread task along with everything else on the page. If the
69
+ // main thread is busy with large icicles, we can easily create tens of
70
+ // thousands of overlays. Therefore, only create overlays for events of at least 1ms.
71
+ if (event.dur === undefined || event.dur < 1_000) {
72
+ continue;
73
+ }
74
+ const overlay = {
75
+ type: 'ENTRY_OUTLINE',
76
+ entry: event,
77
+ outlineReason: 'INFO',
78
+ };
79
+ overlays.push(overlay);
80
+ }
81
+ return overlays;
82
+ }
83
+ export function createOverlays(model) {
84
+ const overlays = [];
85
+ const summaries = model.entitySummaries ?? [];
86
+ for (const summary of summaries) {
87
+ if (summary.entity === model.firstPartyEntity) {
88
+ continue;
89
+ }
90
+ const summaryOverlays = createOverlaysForSummary(summary);
91
+ overlays.push(...summaryOverlays);
92
+ }
93
+ return overlays;
94
+ }
64
95
  //# sourceMappingURL=ThirdParties.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,aAAa,MAAM,yDAAyD,CAAC;AACzF,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAC9C,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,WAAW,GAIZ,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,gJAAgJ;IAChJ,KAAK,EAAE,aAAa;IACpB;;;OAGG;IACH,WAAW,EAAE,4DAA4D;QACrE,0KAA0K;IAC9K,iFAAiF;IACjF,gBAAgB,EAAE,WAAW;IAC7B,4GAA4G;IAC5G,kBAAkB,EAAE,eAAe;IACnC,wJAAwJ;IACxJ,oBAAoB,EAAE,kBAAkB;IACxC;;OAEG;IACH,cAAc,EAAE,wBAAwB;CAChC,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,uCAAuC,EAAE,SAAS,CAAC,CAAC;AAC7F,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAQ7E,SAAS,gBAAgB,CACrB,SAA8C,EAC9C,gBAAsD;IACxD,MAAM,aAAa,GAAG,EAAE,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;YACxC,aAAa,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,QAAQ,CAAC,YAA2D;IAC3E,OAAO;QACL,UAAU,EAAE,WAAW,CAAC,aAAa;QACrC,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,YAAY,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;YACnG,aAAa,CAAC,CAAC;YACf,MAAM;QACV,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAuC,EAAE,OAA0B;IACrE,MAAM,eAAe,GACjB,MAAM,CAAC,YAAY,CAAC,qBAAqB,CAAC,WAAyC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzG,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,iBAAiB,IAAI,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC;IACxG,MAAM,gBAAgB,GAAG,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC;QACzE,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IAEzG,OAAO,QAAQ,CAAC;QACd,aAAa,EAAE,gBAAgB,CAAC,eAAe,EAAE,gBAAgB,CAAC;QAClE,gBAAgB;QAChB,eAAe;KAChB,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport type * 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 code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: '3rd parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description: '3rd party code can significantly impact load performance. ' +\n '[Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page\\'s content.',\n /** Label for a table column that displays the name of a third-party provider. */\n columnThirdParty: '3rd party',\n /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */\n columnTransferSize: 'Transfer size',\n /** Label for a table column that displays how much time each row spent running on the main thread, entries will be the number of milliseconds spent. */\n columnMainThreadTime: 'Main thread time',\n /**\n * @description Text block indicating that no third party content was detected on the page\n */\n noThirdParties: 'No third parties found',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type ThirdPartiesInsightModel = InsightModel<typeof UIStrings, {\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n entitySummaries: Extras.ThirdParties.EntitySummary[],\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.EntitySummary[],\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const relatedEvents = [];\n for (const summary of summaries) {\n if (summary.entity !== firstPartyEntity) {\n relatedEvents.push(...summary.relatedEvents);\n }\n }\n\n return relatedEvents;\n}\n\nfunction finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>): ThirdPartiesInsightModel {\n return {\n insightKey: InsightKeys.THIRD_PARTIES,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: partialModel.entitySummaries.find(summary => summary.entity !== partialModel.firstPartyEntity) ?\n 'informative' :\n 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ThirdPartiesInsightModel {\n const entitySummaries =\n Extras.ThirdParties.summarizeByThirdParty(parsedTrace as Handlers.Types.ParsedTrace, context.bounds);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Handlers.Helpers.makeUpEntity(parsedTrace.Renderer.entityMappings.createdEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(entitySummaries, firstPartyEntity),\n firstPartyEntity,\n entitySummaries,\n });\n}\n"]}
1
+ {"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.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 ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport type * 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 code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: '3rd parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description: '3rd party code can significantly impact load performance. ' +\n '[Reduce and defer loading of 3rd party code](https://web.dev/articles/optimizing-content-efficiency-loading-third-party-javascript/) to prioritize your page\\'s content.',\n /** Label for a table column that displays the name of a third-party provider. */\n columnThirdParty: '3rd party',\n /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */\n columnTransferSize: 'Transfer size',\n /** Label for a table column that displays how much time each row spent running on the main thread, entries will be the number of milliseconds spent. */\n columnMainThreadTime: 'Main thread time',\n /**\n * @description Text block indicating that no third party content was detected on the page\n */\n noThirdParties: 'No third parties found',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type ThirdPartiesInsightModel = InsightModel<typeof UIStrings, {\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n entitySummaries: Extras.ThirdParties.EntitySummary[],\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.EntitySummary[],\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const relatedEvents = [];\n for (const summary of summaries) {\n if (summary.entity !== firstPartyEntity) {\n relatedEvents.push(...summary.relatedEvents);\n }\n }\n\n return relatedEvents;\n}\n\nfunction finalize(partialModel: PartialInsightModel<ThirdPartiesInsightModel>): ThirdPartiesInsightModel {\n return {\n insightKey: InsightKeys.THIRD_PARTIES,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n state: partialModel.entitySummaries.find(summary => summary.entity !== partialModel.firstPartyEntity) ?\n 'informative' :\n 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ThirdPartiesInsightModel {\n const entitySummaries =\n Extras.ThirdParties.summarizeByThirdParty(parsedTrace as Handlers.Types.ParsedTrace, context.bounds);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Handlers.Helpers.makeUpEntity(parsedTrace.Renderer.entityMappings.createdEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(entitySummaries, firstPartyEntity),\n firstPartyEntity,\n entitySummaries,\n });\n}\n\nexport function createOverlaysForSummary(summary: Extras.ThirdParties.EntitySummary): Types.Overlays.Overlay[] {\n const overlays = [];\n for (const event of summary.relatedEvents) {\n // The events found for a third party can be vast, as they gather every\n // single main thread task along with everything else on the page. If the\n // main thread is busy with large icicles, we can easily create tens of\n // thousands of overlays. Therefore, only create overlays for events of at least 1ms.\n if (event.dur === undefined || event.dur < 1_000) {\n continue;\n }\n\n const overlay: Types.Overlays.Overlay = {\n type: 'ENTRY_OUTLINE',\n entry: event,\n outlineReason: 'INFO',\n };\n overlays.push(overlay);\n }\n return overlays;\n}\n\nexport function createOverlays(model: ThirdPartiesInsightModel): Types.Overlays.Overlay[] {\n const overlays: Types.Overlays.Overlay[] = [];\n const summaries = model.entitySummaries ?? [];\n for (const summary of summaries) {\n if (summary.entity === model.firstPartyEntity) {\n continue;\n }\n\n const summaryOverlays = createOverlaysForSummary(summary);\n overlays.push(...summaryOverlays);\n }\n\n return overlays;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as Platform from '../../../core/platform/platform.js';
2
2
  import * as Handlers from '../handlers/handlers.js';
3
- import type * as Types from '../types/types.js';
3
+ import * as Types from '../types/types.js';
4
4
  import { type InsightModel, type InsightSetContext } from './types.js';
5
5
  export declare const UIStrings: {
6
6
  /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */
@@ -21,3 +21,4 @@ export type ViewportInsightModel = InsightModel<typeof UIStrings, {
21
21
  longPointerInteractions?: Types.Events.SyntheticInteractionPair[];
22
22
  }>;
23
23
  export declare function generateInsight(parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ViewportInsightModel;
24
+ export declare function createOverlays(model: ViewportInsightModel): Types.Overlays.Overlay[];
@@ -5,6 +5,7 @@
5
5
  import * as Platform from '../../../core/platform/platform.js';
6
6
  import * as Handlers from '../handlers/handlers.js';
7
7
  import * as Helpers from '../helpers/helpers.js';
8
+ import * as Types from '../types/types.js';
8
9
  import { InsightCategory, InsightKeys, InsightWarning, } from './types.js';
9
10
  export const UIStrings = {
10
11
  /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */
@@ -80,4 +81,19 @@ export function generateInsight(parsedTrace, context) {
80
81
  viewportEvent,
81
82
  });
82
83
  }
84
+ export function createOverlays(model) {
85
+ if (!model.longPointerInteractions) {
86
+ return [];
87
+ }
88
+ return model.longPointerInteractions.map(interaction => {
89
+ const delay = Math.min(interaction.inputDelay, 300 * 1000);
90
+ const bounds = Helpers.Timing.traceWindowFromMicroSeconds(Types.Timing.Micro(interaction.ts), Types.Timing.Micro(interaction.ts + delay));
91
+ return {
92
+ type: 'TIMESPAN_BREAKDOWN',
93
+ entry: interaction,
94
+ sections: [{ bounds, label: i18nString(UIStrings.mobileTapDelayLabel), showDuration: true }],
95
+ renderLocation: 'ABOVE_EVENT',
96
+ };
97
+ });
98
+ }
83
99
  //# sourceMappingURL=Viewport.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.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 * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n InsightKeys,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Optimize viewport for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'Tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',\n /**\n * @description Text for a label describing the portion of an interaction event that was delayed due to a bad mobile viewport.\n */\n mobileTapDelayLabel: 'Mobile tap delay',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type ViewportInsightModel = InsightModel<typeof UIStrings, {\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n longPointerInteractions?: Types.Events.SyntheticInteractionPair[],\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<ViewportInsightModel>): ViewportInsightModel {\n return {\n insightKey: InsightKeys.VIEWPORT,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n state: partialModel.mobileOptimized === false ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ViewportInsightModel {\n const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n // Commit compositor frame events can be emitted before the viewport tag is parsed.\n // We shouldn't count these since the browser hasn't had time to make the viewport mobile optimized.\n if (viewportEvent && event.ts < viewportEvent.ts) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return finalize({\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n });\n }\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n // Grab all the pointer events with at least 50ms of input delay.\n const longPointerInteractions = [...parsedTrace.UserInteractions.interactionsOverThreshold.values()].filter(\n interaction => Handlers.ModelHandlers.UserInteractions.categoryOfInteraction(interaction) === 'POINTER' &&\n interaction.inputDelay >= 50_000);\n\n // The actual impact varies between 0 and 300.\n // Using inputDelay as the closest thing we have for measuring this, though inputDelay may be high for other reasons.\n // b/371566378#comment8\n const inputDelay = Math.max(0, ...longPointerInteractions.map(interaction => interaction.inputDelay)) / 1000;\n const inpMetricSavings = Platform.NumberUtilities.clamp(inputDelay, 0, 300);\n\n return finalize({\n mobileOptimized: false,\n viewportEvent,\n longPointerInteractions,\n metricSavings: {INP: inpMetricSavings as Types.Timing.Milli},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n"]}
1
+ {"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.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 * 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 InsightWarning,\n type PartialInsightModel,\n} from './types.js';\n\nexport const UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Optimize viewport for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'Tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/) if the viewport is not optimized for mobile.',\n /**\n * @description Text for a label describing the portion of an interaction event that was delayed due to a bad mobile viewport.\n */\n mobileTapDelayLabel: 'Mobile tap delay',\n} as const;\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nexport const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type ViewportInsightModel = InsightModel<typeof UIStrings, {\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n longPointerInteractions?: Types.Events.SyntheticInteractionPair[],\n}>;\n\nfunction finalize(partialModel: PartialInsightModel<ViewportInsightModel>): ViewportInsightModel {\n return {\n insightKey: InsightKeys.VIEWPORT,\n strings: UIStrings,\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n state: partialModel.mobileOptimized === false ? 'fail' : 'pass',\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): ViewportInsightModel {\n const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n // Commit compositor frame events can be emitted before the viewport tag is parsed.\n // We shouldn't count these since the browser hasn't had time to make the viewport mobile optimized.\n if (viewportEvent && event.ts < viewportEvent.ts) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return finalize({\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n });\n }\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n // Grab all the pointer events with at least 50ms of input delay.\n const longPointerInteractions = [...parsedTrace.UserInteractions.interactionsOverThreshold.values()].filter(\n interaction => Handlers.ModelHandlers.UserInteractions.categoryOfInteraction(interaction) === 'POINTER' &&\n interaction.inputDelay >= 50_000);\n\n // The actual impact varies between 0 and 300.\n // Using inputDelay as the closest thing we have for measuring this, though inputDelay may be high for other reasons.\n // b/371566378#comment8\n const inputDelay = Math.max(0, ...longPointerInteractions.map(interaction => interaction.inputDelay)) / 1000;\n const inpMetricSavings = Platform.NumberUtilities.clamp(inputDelay, 0, 300);\n\n return finalize({\n mobileOptimized: false,\n viewportEvent,\n longPointerInteractions,\n metricSavings: {INP: inpMetricSavings as Types.Timing.Milli},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n\nexport function createOverlays(model: ViewportInsightModel): Types.Overlays.Overlay[] {\n if (!model.longPointerInteractions) {\n return [];\n }\n\n return model.longPointerInteractions.map(interaction => {\n const delay = Math.min(interaction.inputDelay, 300 * 1000);\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(\n Types.Timing.Micro(interaction.ts),\n Types.Timing.Micro(interaction.ts + delay),\n );\n return {\n type: 'TIMESPAN_BREAKDOWN',\n entry: interaction,\n sections: [{bounds, label: i18nString(UIStrings.mobileTapDelayLabel), showDuration: true}],\n renderLocation: 'ABOVE_EVENT',\n };\n });\n}\n"]}
@@ -76,6 +76,8 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
76
76
  * If this insight is attached to a navigation, this stores its ID.
77
77
  */
78
78
  navigationId?: string;
79
+ /** This is lazily-generated because some insights may create many overlays. */
80
+ createOverlays?: () => Types.Overlays.Overlay[];
79
81
  };
80
82
  export type PartialInsightModel<T> = Omit<T, 'strings' | 'title' | 'description' | 'category' | 'state' | 'insightKey' | 'navigationId' | 'frameId'>;
81
83
  /**
@@ -122,5 +124,6 @@ export declare enum InsightKeys {
122
124
  NETWORK_DEPENDENCY_TREE = "NetworkDependencyTree",
123
125
  RENDER_BLOCKING = "RenderBlocking",
124
126
  SLOW_CSS_SELECTOR = "SlowCSSSelector",
125
- VIEWPORT = "Viewport"
127
+ VIEWPORT = "Viewport",
128
+ MODERN_HTTP = "ModernHTTP"
126
129
  }
@@ -34,5 +34,6 @@ export var InsightKeys;
34
34
  InsightKeys["RENDER_BLOCKING"] = "RenderBlocking";
35
35
  InsightKeys["SLOW_CSS_SELECTOR"] = "SlowCSSSelector";
36
36
  InsightKeys["VIEWPORT"] = "Viewport";
37
+ InsightKeys["MODERN_HTTP"] = "ModernHTTP";
37
38
  })(InsightKeys || (InsightKeys = {}));
38
39
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAoC7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB;AAYD,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B;AAuED,MAAM,CAAN,IAAY,WAiBX;AAjBD,WAAY,WAAW;IACrB,6CAA8B,CAAA;IAC9B,6CAA8B,CAAA;IAC9B,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,mDAAoC,CAAA;IACpC,mCAAoB,CAAA;IACpB,4DAA6C,CAAA;IAC7C,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,+CAAgC,CAAA;IAChC,6CAA8B,CAAA;IAC9B,qDAAsC,CAAA;IACtC,gEAAiD,CAAA;IACjD,iDAAkC,CAAA;IAClC,oDAAqC,CAAA;IACrC,oCAAqB,CAAA;AACvB,CAAC,EAjBW,WAAW,KAAX,WAAW,QAiBtB","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../../core/common/common.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as Models from './Models.js';\n\n/**\n * Context for the portion of the trace an insight should look at.\n */\nexport type InsightSetContext = InsightSetContextWithoutNavigation|InsightSetContextWithNavigation;\n\nexport interface InsightSetContextWithoutNavigation {\n bounds: Types.Timing.TraceWindowMicro;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicro;\n frameId: string;\n navigation: Types.Events.NavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n requests: Array<Lantern.Types.NetworkRequest<Types.Events.SyntheticNetworkRequest>>;\n graph: Lantern.Graph.Node<Types.Events.SyntheticNetworkRequest>;\n simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;\n metrics: Record<string, Lantern.Metrics.MetricResult>;\n}\n\nexport type InsightModelsType = typeof Models;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.Milli;\n LCP?: Types.Timing.Milli;\n TBT?: Types.Timing.Milli;\n CLS?: number;\n INP?: Types.Timing.Milli;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum InsightCategory {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n}\n\nexport type RelatedEventsMap = Map<Types.Events.Event, string[]>;\n\nexport type Checklist<Keys extends string> = Record<Keys, {label: Common.UIString.LocalizedString, value: boolean}>;\n\nexport type InsightModel<UIStrings extends Record<string, string> = Record<string, string>,\n ExtraDetail extends Record<string, unknown> = Record<string, unknown>> =\n ExtraDetail&{\n /** Used internally to identify the type of a model, not shown visibly to users **/\n insightKey: keyof InsightModelsType,\n /** Not used within DevTools - this is for external consumers (like Lighthouse). */\n strings: UIStrings,\n title: Common.UIString.LocalizedString,\n description: Common.UIString.LocalizedString,\n category: InsightCategory,\n state: 'pass' | 'fail' | 'informative',\n /** Used by RelatedInsightChips.ts */\n relatedEvents?: RelatedEventsMap | Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\n /**\n * An estimate for the number of bytes that this insight deems to have been wasted.\n * Bytes are in terms of transfer size: for each component of savings related to an\n * individual request, the insight will estimate its impact on transfer size by using\n * the compression ratio of the resource.\n *\n * This field is only displayed for informational purposes.\n */\n wastedBytes?: number,\n frameId?: string,\n /**\n * If this insight is attached to a navigation, this stores its ID.\n */\n navigationId?: string,\n };\n\nexport type PartialInsightModel<T> =\n Omit<T, 'strings'|'title'|'description'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;\n\n/**\n * Contains insights for a specific navigation. If a trace began after a navigation already started,\n * this could instead represent the duration from the beginning of the trace up to the first recorded\n * navigation (or the end of the trace).\n */\nexport interface InsightSet {\n /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId;\n /** The URL to show in the accordion list. */\n url: URL;\n frameId: string;\n bounds: Types.Timing.TraceWindowMicro;\n model: InsightModels;\n navigation?: Types.Events.NavigationStart;\n}\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: ReturnType<InsightModelsType[I]['generateInsight']>;\n};\n\n/**\n * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:\n *\n * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no\n * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;\n\nexport enum InsightKeys {\n LCP_BREAKDOWN = 'LCPBreakdown',\n INP_BREAKDOWN = 'INPBreakdown',\n CLS_CULPRITS = 'CLSCulprits',\n THIRD_PARTIES = 'ThirdParties',\n DOCUMENT_LATENCY = 'DocumentLatency',\n DOM_SIZE = 'DOMSize',\n DUPLICATE_JAVASCRIPT = 'DuplicatedJavaScript',\n FONT_DISPLAY = 'FontDisplay',\n FORCED_REFLOW = 'ForcedReflow',\n IMAGE_DELIVERY = 'ImageDelivery',\n LCP_DISCOVERY = 'LCPDiscovery',\n LEGACY_JAVASCRIPT = 'LegacyJavaScript',\n NETWORK_DEPENDENCY_TREE = 'NetworkDependencyTree',\n RENDER_BLOCKING = 'RenderBlocking',\n SLOW_CSS_SELECTOR = 'SlowCSSSelector',\n VIEWPORT = 'Viewport',\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAoC7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB;AAYD,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B;AAyED,MAAM,CAAN,IAAY,WAkBX;AAlBD,WAAY,WAAW;IACrB,6CAA8B,CAAA;IAC9B,6CAA8B,CAAA;IAC9B,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,mDAAoC,CAAA;IACpC,mCAAoB,CAAA;IACpB,4DAA6C,CAAA;IAC7C,2CAA4B,CAAA;IAC5B,6CAA8B,CAAA;IAC9B,+CAAgC,CAAA;IAChC,6CAA8B,CAAA;IAC9B,qDAAsC,CAAA;IACtC,gEAAiD,CAAA;IACjD,iDAAkC,CAAA;IAClC,oDAAqC,CAAA;IACrC,oCAAqB,CAAA;IACrB,yCAA0B,CAAA;AAC5B,CAAC,EAlBW,WAAW,KAAX,WAAW,QAkBtB","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../../core/common/common.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as Models from './Models.js';\n\n/**\n * Context for the portion of the trace an insight should look at.\n */\nexport type InsightSetContext = InsightSetContextWithoutNavigation|InsightSetContextWithNavigation;\n\nexport interface InsightSetContextWithoutNavigation {\n bounds: Types.Timing.TraceWindowMicro;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicro;\n frameId: string;\n navigation: Types.Events.NavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n requests: Array<Lantern.Types.NetworkRequest<Types.Events.SyntheticNetworkRequest>>;\n graph: Lantern.Graph.Node<Types.Events.SyntheticNetworkRequest>;\n simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;\n metrics: Record<string, Lantern.Metrics.MetricResult>;\n}\n\nexport type InsightModelsType = typeof Models;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.Milli;\n LCP?: Types.Timing.Milli;\n TBT?: Types.Timing.Milli;\n CLS?: number;\n INP?: Types.Timing.Milli;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum InsightCategory {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n}\n\nexport type RelatedEventsMap = Map<Types.Events.Event, string[]>;\n\nexport type Checklist<Keys extends string> = Record<Keys, {label: Common.UIString.LocalizedString, value: boolean}>;\n\nexport type InsightModel<UIStrings extends Record<string, string> = Record<string, string>,\n ExtraDetail extends Record<string, unknown> = Record<string, unknown>> =\n ExtraDetail&{\n /** Used internally to identify the type of a model, not shown visibly to users **/\n insightKey: keyof InsightModelsType,\n /** Not used within DevTools - this is for external consumers (like Lighthouse). */\n strings: UIStrings,\n title: Common.UIString.LocalizedString,\n description: Common.UIString.LocalizedString,\n category: InsightCategory,\n state: 'pass' | 'fail' | 'informative',\n /** Used by RelatedInsightChips.ts */\n relatedEvents?: RelatedEventsMap | Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\n /**\n * An estimate for the number of bytes that this insight deems to have been wasted.\n * Bytes are in terms of transfer size: for each component of savings related to an\n * individual request, the insight will estimate its impact on transfer size by using\n * the compression ratio of the resource.\n *\n * This field is only displayed for informational purposes.\n */\n wastedBytes?: number,\n frameId?: string,\n /**\n * If this insight is attached to a navigation, this stores its ID.\n */\n navigationId?: string,\n /** This is lazily-generated because some insights may create many overlays. */\n createOverlays?: () => Types.Overlays.Overlay[],\n };\n\nexport type PartialInsightModel<T> =\n Omit<T, 'strings'|'title'|'description'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;\n\n/**\n * Contains insights for a specific navigation. If a trace began after a navigation already started,\n * this could instead represent the duration from the beginning of the trace up to the first recorded\n * navigation (or the end of the trace).\n */\nexport interface InsightSet {\n /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId;\n /** The URL to show in the accordion list. */\n url: URL;\n frameId: string;\n bounds: Types.Timing.TraceWindowMicro;\n model: InsightModels;\n navigation?: Types.Events.NavigationStart;\n}\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: ReturnType<InsightModelsType[I]['generateInsight']>;\n};\n\n/**\n * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:\n *\n * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no\n * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;\n\nexport enum InsightKeys {\n LCP_BREAKDOWN = 'LCPBreakdown',\n INP_BREAKDOWN = 'INPBreakdown',\n CLS_CULPRITS = 'CLSCulprits',\n THIRD_PARTIES = 'ThirdParties',\n DOCUMENT_LATENCY = 'DocumentLatency',\n DOM_SIZE = 'DOMSize',\n DUPLICATE_JAVASCRIPT = 'DuplicatedJavaScript',\n FONT_DISPLAY = 'FontDisplay',\n FORCED_REFLOW = 'ForcedReflow',\n IMAGE_DELIVERY = 'ImageDelivery',\n LCP_DISCOVERY = 'LCPDiscovery',\n LEGACY_JAVASCRIPT = 'LegacyJavaScript',\n NETWORK_DEPENDENCY_TREE = 'NetworkDependencyTree',\n RENDER_BLOCKING = 'RenderBlocking',\n SLOW_CSS_SELECTOR = 'SlowCSSSelector',\n VIEWPORT = 'Viewport',\n MODERN_HTTP = 'ModernHTTP',\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type * as Platform from '../../../core/platform/platform.js';
1
2
  import type { Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased } from './TraceEvents.js';
2
3
  export type ExtensionEntryType = 'track-entry' | 'marker';
3
4
  export declare const extensionPalette: readonly ["primary", "primary-light", "primary-dark", "secondary", "secondary-light", "secondary-dark", "tertiary", "tertiary-light", "tertiary-dark", "error", "warning"];
@@ -13,10 +14,15 @@ export interface ExtensionDataPayloadBase {
13
14
  tooltipText?: string;
14
15
  }
15
16
  export type ExtensionDataPayload = ExtensionTrackEntryPayload | ExtensionMarkerPayload;
17
+ export interface ExtensionTrackEntryPayloadDeeplink {
18
+ url: Platform.DevToolsPath.UrlString;
19
+ description: string;
20
+ }
16
21
  export interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {
17
22
  dataType?: 'track-entry';
18
23
  track: string;
19
24
  trackGroup?: string;
25
+ additionalContext?: ExtensionTrackEntryPayloadDeeplink;
20
26
  }
21
27
  export interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {
22
28
  dataType: 'marker';
@@ -41,10 +47,16 @@ export declare function isExtensionPayloadTrackEntry(payload: {
41
47
  track?: string;
42
48
  dataType?: string;
43
49
  }): payload is ExtensionTrackEntryPayload;
50
+ export declare function isConsoleTimestampPayloadTrackEntry(payload: {
51
+ description?: string;
52
+ url?: string;
53
+ }): payload is ExtensionTrackEntryPayloadDeeplink;
44
54
  export declare function isValidExtensionPayload(payload: {
45
55
  track?: string;
46
56
  dataType?: string;
47
- }): payload is ExtensionDataPayload;
57
+ description?: string;
58
+ url?: string;
59
+ }): payload is ExtensionDataPayload | ExtensionTrackEntryPayloadDeeplink;
48
60
  export declare function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry;
49
61
  export interface ExtensionTrackData {
50
62
  name: string;
@@ -22,8 +22,12 @@ export function isExtensionPayloadTrackEntry(payload) {
22
22
  const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;
23
23
  return validEntryType && hasTrack;
24
24
  }
25
+ export function isConsoleTimestampPayloadTrackEntry(payload) {
26
+ return payload.url !== undefined && payload.description !== undefined;
27
+ }
25
28
  export function isValidExtensionPayload(payload) {
26
- return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);
29
+ return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload) ||
30
+ isConsoleTimestampPayloadTrackEntry(payload);
27
31
  }
28
32
  export function isSyntheticExtensionEntry(entry) {
29
33
  return entry.cat === 'devtools.extension';
@@ -1 +1 @@
1
- {"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAQ7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;AAsDX,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type {\n Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased} from\n './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nexport const extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n 'warning',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n /**\n * We document to users that we support only string values here, but because\n * this is coming from user code the values could be anything, so we ensure we\n * deal with bad data by typing this as unknown.\n */\n properties?: Array<[string, unknown]>;\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends\n SyntheticBased<Phase.COMPLETE, PerformanceMeasureBegin|PerformanceMark|ConsoleTimeStamp> {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased<Phase.COMPLETE, PerformanceMark> {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: Record<string, SyntheticExtensionTrackEntry[]>;\n}\n"]}
1
+ {"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAU7B,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;IACP,SAAS;CACD,CAAC;AAiEX,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,OAA6C;IAE/F,OAAO,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,uBAAuB,CACnC,OAAgF;IAElF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC;QAC7E,mCAAmC,CAAC,OAAO,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../core/platform/platform.js';\n\nimport type {\n Args, ConsoleTimeStamp, Event, PerformanceMark, PerformanceMeasureBegin, Phase, SyntheticBased} from\n './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nexport const extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n 'warning',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n /**\n * We document to users that we support only string values here, but because\n * this is coming from user code the values could be anything, so we ensure we\n * deal with bad data by typing this as unknown.\n */\n properties?: Array<[string, unknown]>;\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayloadDeeplink {\n // The URL (deep-link) to show in the summary for the track.\n url: Platform.DevToolsPath.UrlString;\n // The label to show in front of the URL when the deep-link is shown in the\n // graph.\n description: string;\n}\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n // Additional context (deep-link URL) that can be shown in the summary for the\n // track.\n additionalContext?: ExtensionTrackEntryPayloadDeeplink;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends\n SyntheticBased<Phase.COMPLETE, PerformanceMeasureBegin|PerformanceMark|ConsoleTimeStamp> {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased<Phase.COMPLETE, PerformanceMark> {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isConsoleTimestampPayloadTrackEntry(payload: {description?: string, url?: string}):\n payload is ExtensionTrackEntryPayloadDeeplink {\n return payload.url !== undefined && payload.description !== undefined;\n}\n\nexport function isValidExtensionPayload(\n payload: {track?: string, dataType?: string, description?: string, url?: string}): payload is ExtensionDataPayload|\n ExtensionTrackEntryPayloadDeeplink {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload) ||\n isConsoleTimestampPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: Record<string, SyntheticExtensionTrackEntry[]>;\n}\n"]}
@@ -0,0 +1,110 @@
1
+ // import type * as Lit from '../../../ui/lit/lit.js';
2
+ import type { EntriesLinkState } from './File.js';
3
+ import type { Micro, TraceWindowMicro } from './Timing.js';
4
+ import type { Event, LegacyTimelineFrame, PageLoadEvent } from './TraceEvents.js';
5
+ /**
6
+ * Represents which flamechart an entry is rendered in.
7
+ * We need to know this because when we place an overlay for an entry we need
8
+ * to adjust its Y value if it's in the main chart which is drawn below the
9
+ * network chart
10
+ */
11
+ export type EntryChartLocation = 'main' | 'network';
12
+ /**
13
+ * You can add overlays to trace events, but also right now frames are drawn on
14
+ * the timeline but they are not trace events, so we need to allow for that.
15
+ * In the future when the frames track has been migrated to be powered by
16
+ * animation frames (crbug.com/345144583), we can remove the requirement to
17
+ * support TimelineFrame instances (which themselves will be removed from the
18
+ * codebase.)
19
+ */
20
+ export type OverlayEntry = Event | LegacyTimelineFrame;
21
+ /**
22
+ * Represents when a user has selected an entry in the timeline
23
+ */
24
+ export interface EntrySelected {
25
+ type: 'ENTRY_SELECTED';
26
+ entry: OverlayEntry;
27
+ }
28
+ /**
29
+ * Drawn around an entry when we want to highlight it to the user.
30
+ */
31
+ export interface EntryOutline {
32
+ type: 'ENTRY_OUTLINE';
33
+ entry: OverlayEntry;
34
+ outlineReason: 'ERROR' | 'INFO';
35
+ }
36
+ /**
37
+ * Represents an object created when a user creates a label for an entry in the timeline.
38
+ */
39
+ export interface EntryLabel {
40
+ type: 'ENTRY_LABEL';
41
+ entry: OverlayEntry;
42
+ label: string;
43
+ }
44
+ export interface EntriesLink {
45
+ type: 'ENTRIES_LINK';
46
+ state: EntriesLinkState;
47
+ entryFrom: OverlayEntry;
48
+ entryTo?: OverlayEntry;
49
+ }
50
+ /**
51
+ * Represents a time range on the trace. Also used when the user shift+clicks
52
+ * and drags to create a time range.
53
+ */
54
+ export interface TimeRangeLabel {
55
+ type: 'TIME_RANGE';
56
+ bounds: TraceWindowMicro;
57
+ label: string;
58
+ showDuration: boolean;
59
+ }
60
+ /**
61
+ * Used to highlight with a red-candy stripe a time range. It takes an entry
62
+ * because this entry is the row that will be used to place the candy stripe,
63
+ * and its height will be set to the height of that row.
64
+ */
65
+ export interface CandyStripedTimeRange {
66
+ type: 'CANDY_STRIPED_TIME_RANGE';
67
+ bounds: TraceWindowMicro;
68
+ entry: Event;
69
+ }
70
+ /**
71
+ * An EntryBreakdown, or section, that makes up a TimespanBreakdown.
72
+ */
73
+ export interface TimespanBreakdownEntryBreakdown {
74
+ bounds: TraceWindowMicro;
75
+ label: string | any;
76
+ showDuration: boolean;
77
+ }
78
+ /**
79
+ * Represents a timespan on a trace broken down into parts. Each part has a label to it.
80
+ * If an entry is defined, the breakdown will be vertically positioned based on it.
81
+ */
82
+ export interface TimespanBreakdown {
83
+ type: 'TIMESPAN_BREAKDOWN';
84
+ sections: TimespanBreakdownEntryBreakdown[];
85
+ entry?: Event;
86
+ renderLocation?: 'BOTTOM_OF_TIMELINE' | 'BELOW_EVENT' | 'ABOVE_EVENT';
87
+ }
88
+ export interface TimestampMarker {
89
+ type: 'TIMESTAMP_MARKER';
90
+ timestamp: Micro;
91
+ }
92
+ /**
93
+ * Represents a timings marker. This has a line that runs up the whole canvas.
94
+ * We can hold an array of entries, in the case we want to hold more than one with the same timestamp.
95
+ * The adjusted timestamp being the timestamp for the event adjusted by closest navigation.
96
+ */
97
+ export interface TimingsMarker {
98
+ type: 'TIMINGS_MARKER';
99
+ entries: PageLoadEvent[];
100
+ entryToFieldResult: Map<PageLoadEvent, TimingsMarkerFieldResult>;
101
+ adjustedTimestamp: Micro;
102
+ }
103
+ export interface TimingsMarkerFieldResult {
104
+ value: Micro;
105
+ pageScope: 'url' | 'origin';
106
+ }
107
+ /**
108
+ * All supported overlay types.
109
+ */
110
+ export type Overlay = EntrySelected | EntryOutline | TimeRangeLabel | EntryLabel | EntriesLink | TimespanBreakdown | TimestampMarker | CandyStripedTimeRange | TimingsMarker;
@@ -0,0 +1,5 @@
1
+ // Copyright 2025 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+ export {};
5
+ //# sourceMappingURL=Overlays.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Overlays.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Overlays.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B","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 type * as Lit from '../../../ui/lit/lit.js';\n\nimport type {EntriesLinkState} from './File.js';\nimport type {Micro, TraceWindowMicro} from './Timing.js';\nimport type {Event, LegacyTimelineFrame, PageLoadEvent} from './TraceEvents.js';\n\n/**\n * Represents which flamechart an entry is rendered in.\n * We need to know this because when we place an overlay for an entry we need\n * to adjust its Y value if it's in the main chart which is drawn below the\n * network chart\n */\nexport type EntryChartLocation = 'main'|'network';\n\n/**\n * You can add overlays to trace events, but also right now frames are drawn on\n * the timeline but they are not trace events, so we need to allow for that.\n * In the future when the frames track has been migrated to be powered by\n * animation frames (crbug.com/345144583), we can remove the requirement to\n * support TimelineFrame instances (which themselves will be removed from the\n * codebase.)\n */\nexport type OverlayEntry = Event|LegacyTimelineFrame;\n\n/**\n * Represents when a user has selected an entry in the timeline\n */\nexport interface EntrySelected {\n type: 'ENTRY_SELECTED';\n entry: OverlayEntry;\n}\n\n/**\n * Drawn around an entry when we want to highlight it to the user.\n */\nexport interface EntryOutline {\n type: 'ENTRY_OUTLINE';\n entry: OverlayEntry;\n outlineReason: 'ERROR'|'INFO';\n}\n\n/**\n * Represents an object created when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabel {\n type: 'ENTRY_LABEL';\n entry: OverlayEntry;\n label: string;\n}\n\nexport interface EntriesLink {\n type: 'ENTRIES_LINK';\n state: EntriesLinkState;\n entryFrom: OverlayEntry;\n entryTo?: OverlayEntry;\n}\n\n/**\n * Represents a time range on the trace. Also used when the user shift+clicks\n * and drags to create a time range.\n */\nexport interface TimeRangeLabel {\n type: 'TIME_RANGE';\n bounds: TraceWindowMicro;\n label: string;\n showDuration: boolean;\n}\n\n/**\n * Used to highlight with a red-candy stripe a time range. It takes an entry\n * because this entry is the row that will be used to place the candy stripe,\n * and its height will be set to the height of that row.\n */\nexport interface CandyStripedTimeRange {\n type: 'CANDY_STRIPED_TIME_RANGE';\n bounds: TraceWindowMicro;\n entry: Event;\n}\n\n/**\n * An EntryBreakdown, or section, that makes up a TimespanBreakdown.\n */\nexport interface TimespanBreakdownEntryBreakdown {\n bounds: TraceWindowMicro;\n label: string|Lit.LitTemplate;\n showDuration: boolean;\n}\n\n/**\n * Represents a timespan on a trace broken down into parts. Each part has a label to it.\n * If an entry is defined, the breakdown will be vertically positioned based on it.\n */\nexport interface TimespanBreakdown {\n type: 'TIMESPAN_BREAKDOWN';\n sections: TimespanBreakdownEntryBreakdown[];\n entry?: Event;\n renderLocation?: 'BOTTOM_OF_TIMELINE'|'BELOW_EVENT'|'ABOVE_EVENT';\n}\n\nexport interface TimestampMarker {\n type: 'TIMESTAMP_MARKER';\n timestamp: Micro;\n}\n\n/**\n * Represents a timings marker. This has a line that runs up the whole canvas.\n * We can hold an array of entries, in the case we want to hold more than one with the same timestamp.\n * The adjusted timestamp being the timestamp for the event adjusted by closest navigation.\n */\nexport interface TimingsMarker {\n type: 'TIMINGS_MARKER';\n entries: PageLoadEvent[];\n entryToFieldResult: Map<PageLoadEvent, TimingsMarkerFieldResult>;\n adjustedTimestamp: Micro;\n}\n\nexport interface TimingsMarkerFieldResult {\n value: Micro;\n pageScope: 'url'|'origin';\n}\n\n/**\n * All supported overlay types.\n */\nexport type Overlay = EntrySelected|EntryOutline|TimeRangeLabel|EntryLabel|EntriesLink|TimespanBreakdown|\n TimestampMarker|CandyStripedTimeRange|TimingsMarker;\n"]}