@paulirish/trace_engine 0.0.53 → 0.0.54

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 (158) hide show
  1. package/.tmp/tsbuildinfo/analyze-inspector-issues.d.mts +13 -0
  2. package/.tmp/tsbuildinfo/analyze-inspector-issues.d.mts.map +1 -0
  3. package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
  4. package/analyze-inspector-issues.mjs +60 -0
  5. package/core/common/common.d.ts +1 -0
  6. package/core/common/common.js +1 -0
  7. package/core/host/host.d.ts +1 -0
  8. package/core/host/host.js +1 -0
  9. package/core/platform/ServerTiming.d.ts +31 -0
  10. package/core/platform/ServerTiming.js +212 -0
  11. package/core/platform/ServerTiming.js.map +1 -0
  12. package/core/root/root.d.ts +1 -0
  13. package/core/root/root.js +1 -0
  14. package/core/sdk/sdk.d.ts +1 -0
  15. package/core/sdk/sdk.js +1 -0
  16. package/models/issues_manager/CheckFormsIssuesTrigger.d.ts +1 -0
  17. package/models/issues_manager/CheckFormsIssuesTrigger.js +1 -0
  18. package/models/issues_manager/ContrastCheckTrigger.d.ts +1 -0
  19. package/models/issues_manager/ContrastCheckTrigger.js +1 -0
  20. package/models/issues_manager/DeprecationIssue.d.ts +1 -0
  21. package/models/issues_manager/DeprecationIssue.js +1 -0
  22. package/models/issues_manager/IssueResolver.d.ts +1 -0
  23. package/models/issues_manager/IssueResolver.js +1 -0
  24. package/models/issues_manager/RelatedIssue.d.ts +1 -0
  25. package/models/issues_manager/RelatedIssue.js +1 -0
  26. package/models/issues_manager/SourceFrameIssuesManager.d.ts +1 -0
  27. package/models/issues_manager/SourceFrameIssuesManager.js +1 -0
  28. package/models/trace/LanternComputationData.js +2 -2
  29. package/models/trace/LanternComputationData.js.map +1 -1
  30. package/models/trace/ModelImpl.js +1 -1
  31. package/models/trace/ModelImpl.js.map +1 -1
  32. package/models/trace/extras/Metadata.js +2 -2
  33. package/models/trace/extras/Metadata.js.map +1 -1
  34. package/models/trace/extras/ThirdParties.js +1 -1
  35. package/models/trace/extras/ThirdParties.js.map +1 -1
  36. package/models/trace/extras/TimelineJSProfile.d.ts +13 -0
  37. package/models/trace/extras/TimelineJSProfile.js +55 -0
  38. package/models/trace/extras/TimelineJSProfile.js.map +1 -0
  39. package/models/trace/extras/TraceFilter.js +2 -2
  40. package/models/trace/extras/TraceFilter.js.map +1 -1
  41. package/models/trace/extras/URLForEntry.d.ts +12 -0
  42. package/models/trace/extras/URLForEntry.js +43 -0
  43. package/models/trace/extras/URLForEntry.js.map +1 -0
  44. package/models/trace/extras/extras.d.ts +4 -1
  45. package/models/trace/extras/extras.js +4 -1
  46. package/models/trace/handlers/AuctionWorkletsHandler.js +5 -5
  47. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
  48. package/models/trace/handlers/ExtensionTraceDataHandler.js +4 -4
  49. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  50. package/models/trace/handlers/FlowsHandler.js +3 -3
  51. package/models/trace/handlers/FlowsHandler.js.map +1 -1
  52. package/models/trace/handlers/FramesHandler.js +7 -7
  53. package/models/trace/handlers/FramesHandler.js.map +1 -1
  54. package/models/trace/handlers/LargestImagePaintHandler.js +2 -2
  55. package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
  56. package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -1
  57. package/models/trace/handlers/LayoutShiftsHandler.js +18 -10
  58. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  59. package/models/trace/handlers/MetaHandler.js +7 -7
  60. package/models/trace/handlers/MetaHandler.js.map +1 -1
  61. package/models/trace/handlers/NetworkRequestsHandler.js +3 -3
  62. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  63. package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -2
  64. package/models/trace/handlers/PageLoadMetricsHandler.js +54 -25
  65. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  66. package/models/trace/handlers/RendererHandler.js +1 -1
  67. package/models/trace/handlers/RendererHandler.js.map +1 -1
  68. package/models/trace/handlers/ServerTimingsHandler.d.ts +9 -0
  69. package/models/trace/handlers/ServerTimingsHandler.js +106 -0
  70. package/models/trace/handlers/ServerTimingsHandler.js.map +1 -0
  71. package/models/trace/handlers/Threads.d.ts +1 -1
  72. package/models/trace/handlers/Threads.js +17 -7
  73. package/models/trace/handlers/Threads.js.map +1 -1
  74. package/models/trace/handlers/UserInteractionsHandler.js +4 -3
  75. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  76. package/models/trace/handlers/WarningsHandler.js +2 -2
  77. package/models/trace/handlers/WarningsHandler.js.map +1 -1
  78. package/models/trace/helpers/SamplesIntegrator.d.ts +1 -1
  79. package/models/trace/helpers/SamplesIntegrator.js +19 -12
  80. package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
  81. package/models/trace/helpers/Trace.js +111 -111
  82. package/models/trace/helpers/Trace.js.map +1 -1
  83. package/models/trace/insights/CLSCulprits.d.ts +1 -1
  84. package/models/trace/insights/CLSCulprits.js +43 -22
  85. package/models/trace/insights/CLSCulprits.js.map +1 -1
  86. package/models/trace/insights/Common.js +4 -3
  87. package/models/trace/insights/Common.js.map +1 -1
  88. package/models/trace/insights/CumulativeLayoutShift.d.ts +57 -0
  89. package/models/trace/insights/CumulativeLayoutShift.js +335 -0
  90. package/models/trace/insights/CumulativeLayoutShift.js.map +1 -0
  91. package/models/trace/insights/DOMSize.js +3 -3
  92. package/models/trace/insights/DOMSize.js.map +1 -1
  93. package/models/trace/insights/DocumentLatency.js +2 -2
  94. package/models/trace/insights/DocumentLatency.js.map +1 -1
  95. package/models/trace/insights/DuplicatedJavaScript.js +2 -2
  96. package/models/trace/insights/DuplicatedJavaScript.js.map +1 -1
  97. package/models/trace/insights/FontDisplay.js +2 -2
  98. package/models/trace/insights/FontDisplay.js.map +1 -1
  99. package/models/trace/insights/ForcedReflow.js +2 -2
  100. package/models/trace/insights/ForcedReflow.js.map +1 -1
  101. package/models/trace/insights/ImageDelivery.js +2 -2
  102. package/models/trace/insights/ImageDelivery.js.map +1 -1
  103. package/models/trace/insights/InsightRunners.d.ts +9 -0
  104. package/models/trace/insights/InsightRunners.js +13 -0
  105. package/models/trace/insights/InsightRunners.js.map +1 -0
  106. package/models/trace/insights/InteractionToNextPaint.js +3 -3
  107. package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
  108. package/models/trace/insights/LCPDiscovery.js +3 -3
  109. package/models/trace/insights/LCPDiscovery.js.map +1 -1
  110. package/models/trace/insights/LCPPhases.js +3 -3
  111. package/models/trace/insights/LCPPhases.js.map +1 -1
  112. package/models/trace/insights/LargestContentfulPaint.d.ts +38 -0
  113. package/models/trace/insights/LargestContentfulPaint.js +113 -0
  114. package/models/trace/insights/LargestContentfulPaint.js.map +1 -0
  115. package/models/trace/insights/LegacyJavaScript.js +2 -2
  116. package/models/trace/insights/LegacyJavaScript.js.map +1 -1
  117. package/models/trace/insights/ModernHTTP.js +2 -2
  118. package/models/trace/insights/ModernHTTP.js.map +1 -1
  119. package/models/trace/insights/NetworkDependencyTree.js +2 -2
  120. package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
  121. package/models/trace/insights/RenderBlocking.js +3 -3
  122. package/models/trace/insights/RenderBlocking.js.map +1 -1
  123. package/models/trace/insights/SlowCSSSelector.js +2 -2
  124. package/models/trace/insights/SlowCSSSelector.js.map +1 -1
  125. package/models/trace/insights/ThirdParties.js +2 -2
  126. package/models/trace/insights/ThirdParties.js.map +1 -1
  127. package/models/trace/insights/ThirdPartyWeb.d.ts +13 -0
  128. package/models/trace/insights/ThirdPartyWeb.js +42 -0
  129. package/models/trace/insights/ThirdPartyWeb.js.map +1 -0
  130. package/models/trace/insights/Viewport.js +2 -2
  131. package/models/trace/insights/Viewport.js.map +1 -1
  132. package/models/trace/insights/types.d.ts +1 -1
  133. package/models/trace/insights/types.js +19 -0
  134. package/models/trace/insights/types.js.map +1 -1
  135. package/models/trace/root-causes/LayoutShift.d.ts +125 -0
  136. package/models/trace/root-causes/LayoutShift.js +519 -0
  137. package/models/trace/root-causes/LayoutShift.js.map +1 -0
  138. package/models/trace/root-causes/RootCauses.d.ts +15 -0
  139. package/models/trace/root-causes/RootCauses.js +12 -0
  140. package/models/trace/root-causes/RootCauses.js.map +1 -0
  141. package/models/trace/root-causes/bundle-tsconfig.json +1 -0
  142. package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
  143. package/models/trace/root-causes/root-causes-tsconfig.json +55 -0
  144. package/models/trace/root-causes/root-causes.d.ts +1 -0
  145. package/models/trace/root-causes/root-causes.js +5 -0
  146. package/models/trace/root-causes/root-causes.js.map +1 -0
  147. package/models/trace/types/File.d.ts +3 -3
  148. package/models/trace/types/File.js +28 -4
  149. package/models/trace/types/File.js.map +1 -1
  150. package/models/trace/types/TraceEvents.d.ts +6 -6
  151. package/models/trace/types/TraceEvents.js +373 -105
  152. package/models/trace/types/TraceEvents.js.map +1 -1
  153. package/package.json +1 -1
  154. package/test/test-trace-engine.mjs +77 -0
  155. package/third_party/marked/marked.d.ts +1 -0
  156. package/third_party/marked/marked.js +1 -0
  157. package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts +0 -4
  158. package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts.map +0 -1
@@ -0,0 +1,42 @@
1
+ // Copyright 2024 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+ import * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';
5
+ import * as Extras from '../extras/extras.js';
6
+ import * as Helpers from '../helpers/helpers.js';
7
+ export function deps() {
8
+ return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];
9
+ }
10
+ function getRelatedEvents(summaries, firstPartyEntity) {
11
+ const events = [];
12
+ for (const [entity, requests] of summaries.requestsByEntity.entries()) {
13
+ if (entity !== firstPartyEntity) {
14
+ events.push(...requests);
15
+ }
16
+ }
17
+ return events;
18
+ }
19
+ export function generateInsight(parsedTrace, context) {
20
+ const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {
21
+ if (!context.navigation) {
22
+ return false;
23
+ }
24
+ if (event.args.data.frame !== context.frameId) {
25
+ return false;
26
+ }
27
+ return Helpers.Timing.eventIsInBounds(event, context.bounds);
28
+ });
29
+ const { entityByRequest, madeUpEntityCache, summaries } = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(parsedTrace, context.bounds, networkRequests);
30
+ const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;
31
+ const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||
32
+ Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl);
33
+ return {
34
+ relatedEvents: getRelatedEvents(summaries, firstPartyEntity),
35
+ entityByRequest,
36
+ requestsByEntity: summaries.requestsByEntity,
37
+ summaryByRequest: summaries.byRequest,
38
+ summaryByEntity: summaries.byEntity,
39
+ firstPartyEntity,
40
+ };
41
+ }
42
+ //# sourceMappingURL=ThirdPartyWeb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThirdPartyWeb.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,yDAAyD,CAAC;AACzF,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAClE,CAAC;AAWD,SAAS,gBAAgB,CACrB,SAA0C,EAC1C,gBAAsD;IACxD,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QACtE,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,MAAM,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACxE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,EAAC,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAC,GAAG,MAAM,CAAC,YAAY,CAAC,qCAAqC,CAC7G,WAAyC,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAEhF,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,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAEvE,OAAO;QACL,aAAa,EAAE,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,CAAC;QAC5D,eAAe;QACf,gBAAgB,EAAE,SAAS,CAAC,gBAAgB;QAC5C,gBAAgB,EAAE,SAAS,CAAC,SAAS;QACrC,eAAe,EAAE,SAAS,CAAC,QAAQ;QACnC,gBAAgB;KACjB,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport type {InsightResult, InsightSetContext, RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type ThirdPartyWebInsightResult = InsightResult<{\n entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Entity>,\n requestsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.SyntheticNetworkRequest[]>,\n summaryByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Summary>,\n summaryByEntity: Map<Extras.ThirdParties.Entity, Extras.ThirdParties.Summary>,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.SummaryMaps,\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const events = [];\n\n for (const [entity, requests] of summaries.requestsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n events.push(...requests);\n }\n }\n\n return events;\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartyWebInsightResult {\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {\n if (!context.navigation) {\n return false;\n }\n\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 {entityByRequest, madeUpEntityCache, summaries} = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(\n parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return {\n relatedEvents: getRelatedEvents(summaries, firstPartyEntity),\n entityByRequest,\n requestsByEntity: summaries.requestsByEntity,\n summaryByRequest: summaries.byRequest,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n };\n}\n"]}
@@ -3,7 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  // import * as i18n from '../../../core/i18n/i18n.js';
5
5
  import * as Helpers from '../helpers/helpers.js';
6
- import { InsightCategory, InsightWarning, } from './types.js';
6
+ import { InsightCategory, InsightKeys, InsightWarning, } from './types.js';
7
7
  export const UIStrings = {
8
8
  /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */
9
9
  title: 'Optimize viewport for mobile',
@@ -16,7 +16,7 @@ export const UIStrings = {
16
16
  export const i18nString = (i18nId, values) => ({i18nId, values}); // i18n.i18n.getLocalizedString.bind(undefined, str_);
17
17
  function finalize(partialModel) {
18
18
  return {
19
- insightKey: "Viewport" /* InsightKeys.VIEWPORT */,
19
+ insightKey: InsightKeys.VIEWPORT,
20
20
  strings: UIStrings,
21
21
  title: i18nString(UIStrings.title),
22
22
  description: i18nString(UIStrings.description),
@@ -1 +1 @@
1
- {"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AAEnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EACL,eAAe,EAIf,cAAc,GAEf,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,8GAA8G;IAC9G,KAAK,EAAE,8BAA8B;IACrC;;OAEG;IACH,WAAW,EACP,iKAAiK;CAC7J,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAO7E,SAAS,QAAQ,CAAC,YAAuD;IACvE,OAAO;QACL,UAAU,uCAAsB;QAChC,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,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAC/D,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAuC,EAAE,OAA0B;IACrE,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mFAAmF;QACnF,oGAAoG;QACpG,IAAI,aAAa,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,CAAC;IAED,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAyB,EAAC;aAChD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,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 type * 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} 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}>;\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 return finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 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":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AAEnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EACL,eAAe,EACf,WAAW,EAGX,cAAc,GAEf,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,8GAA8G;IAC9G,KAAK,EAAE,8BAA8B;IACrC;;OAEG;IACH,WAAW,EACP,iKAAiK;CAC7J,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAO7E,SAAS,QAAQ,CAAC,YAAuD;IACvE,OAAO;QACL,UAAU,EAAE,WAAW,CAAC,QAAQ;QAChC,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,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAC/D,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAuC,EAAE,OAA0B;IACrE,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mFAAmF;QACnF,oGAAoG;QACpG,IAAI,aAAa,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,CAAC;IAED,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAyB,EAAC;aAChD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,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 type * 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} 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}>;\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 return finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.Milli},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n"]}
@@ -106,7 +106,7 @@ export type InsightModels = {
106
106
  * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.
107
107
  */
108
108
  export type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;
109
- export declare const enum InsightKeys {
109
+ export declare enum InsightKeys {
110
110
  LCP_PHASES = "LCPPhases",
111
111
  INTERACTION_TO_NEXT_PAINT = "InteractionToNextPaint",
112
112
  CLS_CULPRITS = "CLSCulprits",
@@ -16,4 +16,23 @@ export var InsightCategory;
16
16
  InsightCategory["LCP"] = "LCP";
17
17
  InsightCategory["CLS"] = "CLS";
18
18
  })(InsightCategory || (InsightCategory = {}));
19
+ export var InsightKeys;
20
+ (function (InsightKeys) {
21
+ InsightKeys["LCP_PHASES"] = "LCPPhases";
22
+ InsightKeys["INTERACTION_TO_NEXT_PAINT"] = "InteractionToNextPaint";
23
+ InsightKeys["CLS_CULPRITS"] = "CLSCulprits";
24
+ InsightKeys["THIRD_PARTIES"] = "ThirdParties";
25
+ InsightKeys["DOCUMENT_LATENCY"] = "DocumentLatency";
26
+ InsightKeys["DOM_SIZE"] = "DOMSize";
27
+ InsightKeys["DUPLICATE_JAVASCRIPT"] = "DuplicatedJavaScript";
28
+ InsightKeys["FONT_DISPLAY"] = "FontDisplay";
29
+ InsightKeys["FORCED_REFLOW"] = "ForcedReflow";
30
+ InsightKeys["IMAGE_DELIVERY"] = "ImageDelivery";
31
+ InsightKeys["LCP_DISCOVERY"] = "LCPDiscovery";
32
+ InsightKeys["LEGACY_JAVASCRIPT"] = "LegacyJavaScript";
33
+ InsightKeys["NETWORK_DEPENDENCY_TREE"] = "NetworkDependencyTree";
34
+ InsightKeys["RENDER_BLOCKING"] = "RenderBlocking";
35
+ InsightKeys["SLOW_CSS_SELECTOR"] = "SlowCSSSelector";
36
+ InsightKeys["VIEWPORT"] = "Viewport";
37
+ })(InsightKeys || (InsightKeys = {}));
19
38
  //# 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","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 const enum InsightKeys {\n LCP_PHASES = 'LCPPhases',\n INTERACTION_TO_NEXT_PAINT = 'InteractionToNextPaint',\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;AAuED,MAAM,CAAN,IAAY,WAiBX;AAjBD,WAAY,WAAW;IACrB,uCAAwB,CAAA;IACxB,mEAAoD,CAAA;IACpD,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_PHASES = 'LCPPhases',\n INTERACTION_TO_NEXT_PAINT = 'InteractionToNextPaint',\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"]}
@@ -0,0 +1,125 @@
1
+ import type * as Protocol from '../../../generated/protocol.js';
2
+ import type { ParsedTrace } from '../handlers/types.js';
3
+ import * as Types from '../types/types.js';
4
+ import type { RootCauseProtocolInterface } from './RootCauses.js';
5
+ export type CSSDimensions = {
6
+ width?: string;
7
+ height?: string;
8
+ aspectRatio?: string;
9
+ };
10
+ export interface UnsizedMedia {
11
+ node: Protocol.DOM.Node;
12
+ authoredDimensions?: CSSDimensions;
13
+ computedDimensions: CSSDimensions;
14
+ }
15
+ export interface InjectedIframe {
16
+ iframe: Protocol.DOM.Node;
17
+ }
18
+ export interface RootCauseRequest {
19
+ request: Types.Events.SyntheticNetworkRequest;
20
+ initiator?: Protocol.Network.Initiator;
21
+ }
22
+ export interface FontChange extends RootCauseRequest {
23
+ fontFace: Protocol.CSS.FontFace;
24
+ }
25
+ export interface RenderBlockingRequest extends RootCauseRequest {
26
+ }
27
+ export interface LayoutShiftRootCausesData {
28
+ unsizedMedia: UnsizedMedia[];
29
+ iframes: InjectedIframe[];
30
+ fontChanges: FontChange[];
31
+ renderBlockingRequests: RenderBlockingRequest[];
32
+ scriptStackTrace: Types.Events.CallFrame[];
33
+ }
34
+ interface Options {
35
+ /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */
36
+ enableIframeRootCauses?: boolean;
37
+ }
38
+ export declare class LayoutShiftRootCauses {
39
+ #private;
40
+ constructor(protocolInterface: RootCauseProtocolInterface, options?: Options);
41
+ /**
42
+ * Calculates the potential root causes for a given layout shift event. Once
43
+ * calculated, this data is cached.
44
+ * Note: because you need all layout shift data at once to calculate these
45
+ * correctly, this function will parse the root causes for _all_ layout shift
46
+ * events the first time that it's called. That then populates the cache for
47
+ * each shift, so any subsequent calls are just a constant lookup.
48
+ */
49
+ rootCausesForEvent(modelData: ParsedTrace, event: Types.Events.LayoutShift): Promise<Readonly<LayoutShiftRootCausesData> | null>;
50
+ /**
51
+ * Determines potential root causes for shifts
52
+ */
53
+ blameShifts(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): Promise<void>;
54
+ /**
55
+ * "LayoutInvalidations" are a set of trace events dispatched in Blink under the name
56
+ * "layoutInvalidationTracking", which track invalidations on the "Layout"stage of the
57
+ * rendering pipeline. This function utilizes this event to flag potential root causes
58
+ * to layout shifts.
59
+ */
60
+ linkShiftsToLayoutInvalidations(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): Promise<void>;
61
+ /**
62
+ * For every shift looks up the initiator of its corresponding Layout event. This initiator
63
+ * is assigned by the RendererHandler and contains the stack trace of the point in a script
64
+ * that caused a style recalculation or a relayout. This stack trace is added to the shift's
65
+ * potential root causes.
66
+ * Note that a Layout cannot always be linked to a script, in that case, we cannot add a
67
+ * "script causing reflow" as a potential root cause to the corresponding shift.
68
+ */
69
+ linkShiftsToLayoutEvents(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): void;
70
+ /**
71
+ * Given a LayoutInvalidation trace event, determines if it was dispatched
72
+ * because a media element without dimensions was resized.
73
+ */
74
+ getUnsizedMediaRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<UnsizedMedia | null>;
75
+ /**
76
+ * Given a LayoutInvalidation trace event, determines if it was dispatched
77
+ * because a node, which is an ancestor to an iframe, was injected.
78
+ */
79
+ getIframeRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise<InjectedIframe | null>;
80
+ getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise<Protocol.DOM.Node | null>;
81
+ /**
82
+ * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a
83
+ * 500ms window before the layout invalidation.
84
+ */
85
+ requestsInInvalidationWindow(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, modelData: ParsedTrace): RootCauseRequest[];
86
+ /**
87
+ * Given a LayoutInvalidation trace event, determines if it was dispatched
88
+ * because fonts were changed and if so returns the information of all network
89
+ * request with which the fonts were possibly fetched, if any. The computed
90
+ * network requests are cached for the corresponding prepaint event, meaning
91
+ * that other LayoutInvalidation events that correspond to the same prepaint
92
+ * are not processed and the cached network requests for the prepaint is
93
+ * returned instead.
94
+ */
95
+ getFontChangeRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): FontChange[] | null;
96
+ /**
97
+ * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font
98
+ * requests of them.
99
+ */
100
+ getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[];
101
+ /**
102
+ * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout
103
+ * invalidation and if so returns the information of all network request, if any. The computed network
104
+ * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events
105
+ * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is
106
+ * returned instead.
107
+ */
108
+ getRenderBlockRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): RenderBlockingRequest[] | null;
109
+ /**
110
+ * Returns a function that retrieves the active value of a given
111
+ * CSS property within the matched styles of the param node.
112
+ * The first occurence within the matched styles is returned and the
113
+ * value is looked up in the following order, which follows CSS
114
+ * specificity:
115
+ * 1. Inline styles.
116
+ * 2. CSS rules matching this node, from all applicable stylesheets.
117
+ * 3. Attribute defined styles.
118
+ */
119
+ nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)>;
120
+ /**
121
+ * Returns the CSS dimensions set to the node from its matched styles.
122
+ */
123
+ getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise<CSSDimensions>;
124
+ }
125
+ export {};