@paulirish/trace_engine 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/generated/protocol.d.ts +60 -4
  2. package/models/trace/EntriesFilter.d.ts +14 -13
  3. package/models/trace/EntriesFilter.js +40 -38
  4. package/models/trace/EntriesFilter.js.map +1 -1
  5. package/models/trace/ModelImpl.d.ts +6 -4
  6. package/models/trace/ModelImpl.js +13 -4
  7. package/models/trace/ModelImpl.js.map +1 -1
  8. package/models/trace/Processor.js +6 -1
  9. package/models/trace/Processor.js.map +1 -1
  10. package/models/trace/TracingManager.js.map +1 -1
  11. package/models/trace/extras/FetchNodes.js +1 -1
  12. package/models/trace/extras/FetchNodes.js.map +1 -1
  13. package/models/trace/extras/URLForEntry.d.ts +4 -0
  14. package/models/trace/extras/URLForEntry.js +35 -0
  15. package/models/trace/extras/URLForEntry.js.map +1 -0
  16. package/models/trace/extras/extras-tsconfig.json +1 -0
  17. package/models/trace/extras/extras.js.map +1 -1
  18. package/models/trace/handlers/AuctionWorkletsHandler.js +5 -2
  19. package/models/trace/handlers/AuctionWorkletsHandler.js.map +1 -1
  20. package/models/trace/handlers/ExtensionTraceDataHandler.js +18 -5
  21. package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
  22. package/models/trace/handlers/InitiatorsHandler.js +1 -12
  23. package/models/trace/handlers/InitiatorsHandler.js.map +1 -1
  24. package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -0
  25. package/models/trace/handlers/LayoutShiftsHandler.js +11 -2
  26. package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
  27. package/models/trace/handlers/NetworkRequestsHandler.d.ts +1 -1
  28. package/models/trace/handlers/NetworkRequestsHandler.js +6 -4
  29. package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
  30. package/models/trace/handlers/PageLoadMetricsHandler.js +1 -1
  31. package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
  32. package/models/trace/handlers/RendererHandler.d.ts +1 -0
  33. package/models/trace/handlers/RendererHandler.js +2 -0
  34. package/models/trace/handlers/RendererHandler.js.map +1 -1
  35. package/models/trace/handlers/ScreenshotsHandler.js +4 -2
  36. package/models/trace/handlers/ScreenshotsHandler.js.map +1 -1
  37. package/models/trace/handlers/UserInteractionsHandler.js +4 -2
  38. package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
  39. package/models/trace/helpers/Extensions.js +4 -0
  40. package/models/trace/helpers/Extensions.js.map +1 -1
  41. package/models/trace/helpers/SyntheticEvents.d.ts +30 -0
  42. package/models/trace/helpers/SyntheticEvents.js +87 -0
  43. package/models/trace/helpers/SyntheticEvents.js.map +1 -0
  44. package/models/trace/helpers/Trace.d.ts +2 -0
  45. package/models/trace/helpers/Trace.js +23 -3
  46. package/models/trace/helpers/Trace.js.map +1 -1
  47. package/models/trace/helpers/TreeHelpers.d.ts +20 -0
  48. package/models/trace/helpers/TreeHelpers.js +50 -0
  49. package/models/trace/helpers/TreeHelpers.js.map +1 -1
  50. package/models/trace/helpers/helpers-tsconfig.json +1 -0
  51. package/models/trace/helpers/helpers.d.ts +1 -0
  52. package/models/trace/helpers/helpers.js +1 -0
  53. package/models/trace/helpers/helpers.js.map +1 -1
  54. package/models/trace/insights/CumulativeLayoutShift.d.ts +7 -2
  55. package/models/trace/insights/CumulativeLayoutShift.js +130 -2
  56. package/models/trace/insights/CumulativeLayoutShift.js.map +1 -1
  57. package/models/trace/insights/RenderBlocking.js +14 -0
  58. package/models/trace/insights/RenderBlocking.js.map +1 -1
  59. package/models/trace/trace-tsconfig.json +0 -1
  60. package/models/trace/trace.d.ts +1 -2
  61. package/models/trace/trace.js +1 -4
  62. package/models/trace/trace.js.map +1 -1
  63. package/models/trace/types/File.d.ts +11 -6
  64. package/models/trace/types/File.js +0 -3
  65. package/models/trace/types/File.js.map +1 -1
  66. package/models/trace/types/TraceEvents.d.ts +104 -10
  67. package/models/trace/types/TraceEvents.js +46 -2
  68. package/models/trace/types/TraceEvents.js.map +1 -1
  69. package/package.json +1 -1
@@ -1,9 +1,11 @@
1
1
  // Copyright 2024 The Chromium Authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
+ import * as Platform from '../../../core/platform/platform.js';
4
5
  import * as Helpers from '../helpers/helpers.js';
6
+ import * as Types from '../types/types.js';
5
7
  export function deps() {
6
- return ['Meta', 'Animations'];
8
+ return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];
7
9
  }
8
10
  /**
9
11
  * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define
@@ -37,6 +39,13 @@ const ACTIONABLE_FAILURE_REASONS = [
37
39
  failure: "UNSUPPORTED_TIMING_PARAMS" /* AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS */,
38
40
  },
39
41
  ];
42
+ // 500ms window.
43
+ // Use this window to consider events and requests that may have caused a layout shift.
44
+ const INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));
45
+ function isInInvalidationWindow(event, targetEvent) {
46
+ const eventEnd = event.dur ? event.ts + event.dur : event.ts;
47
+ return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;
48
+ }
40
49
  /**
41
50
  * Returns a list of NoncompositedAnimationFailures.
42
51
  */
@@ -68,14 +77,133 @@ function getNonCompositedAnimations(animations) {
68
77
  }
69
78
  return failures;
70
79
  }
80
+ /**
81
+ * Given an array of layout shift and PrePaint events, returns a mapping from
82
+ * PrePaint events to layout shifts dispatched within it.
83
+ */
84
+ function getShiftsByPrePaintEvents(layoutShifts, prePaintEvents) {
85
+ // Maps from PrePaint events to LayoutShifts that occured in each one.
86
+ const shiftsByPrePaint = new Map();
87
+ // Associate all shifts to their corresponding PrePaint.
88
+ for (const prePaintEvent of prePaintEvents) {
89
+ const firstShiftIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);
90
+ if (firstShiftIndex === null) {
91
+ // No layout shifts registered after this PrePaint start. Continue.
92
+ continue;
93
+ }
94
+ for (let i = firstShiftIndex; i < layoutShifts.length; i++) {
95
+ const shift = layoutShifts[i];
96
+ if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {
97
+ const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);
98
+ shiftsInPrePaint.push(shift);
99
+ }
100
+ if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {
101
+ // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ return shiftsByPrePaint;
107
+ }
108
+ /**
109
+ * This gets the first prePaint event that follows the provided event and returns it.
110
+ */
111
+ function getNextPrePaintEvent(prePaintEvents, targetEvent) {
112
+ // Get the first PrePaint event that happened after the targetEvent.
113
+ const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));
114
+ // No PrePaint event registered after this event
115
+ if (nextPrePaintIndex === null) {
116
+ return undefined;
117
+ }
118
+ return prePaintEvents[nextPrePaintIndex];
119
+ }
120
+ /**
121
+ * An Iframe is considered a root cause if the iframe event occurs before a prePaint event
122
+ * and within this prePaint event a layout shift(s) occurs.
123
+ */
124
+ function getIframeRootCauses(iframeCreatedEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
125
+ for (const iframeEvent of iframeCreatedEvents) {
126
+ const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);
127
+ // If no following prePaint, this is not a root cause.
128
+ if (!nextPrePaint) {
129
+ continue;
130
+ }
131
+ const shifts = shiftsByPrePaint.get(nextPrePaint);
132
+ // if no layout shift(s), this is not a root cause.
133
+ if (!shifts) {
134
+ continue;
135
+ }
136
+ for (const shift of shifts) {
137
+ const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {
138
+ return {
139
+ iframes: [],
140
+ fontRequests: [],
141
+ };
142
+ });
143
+ rootCausesForShift.iframes.push(iframeEvent);
144
+ }
145
+ }
146
+ return rootCausesByShift;
147
+ }
148
+ /**
149
+ * A font request is considered a root cause if the request occurs before a prePaint event
150
+ * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should
151
+ * happen within the INVALIDATION_WINDOW of the prePaint event.
152
+ */
153
+ function getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift) {
154
+ const fontRequests = networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));
155
+ for (const req of fontRequests) {
156
+ const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);
157
+ if (!nextPrePaint) {
158
+ continue;
159
+ }
160
+ // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.
161
+ if (!isInInvalidationWindow(req, nextPrePaint)) {
162
+ continue;
163
+ }
164
+ // Get the shifts that belong to this prepaint
165
+ const shifts = shiftsByPrePaint.get(nextPrePaint);
166
+ // if no layout shift(s) in this prePaint, the request is not a root cause.
167
+ if (!shifts) {
168
+ continue;
169
+ }
170
+ // Include the root cause to the shifts in this prePaint.
171
+ for (const shift of shifts) {
172
+ const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {
173
+ return {
174
+ iframes: [],
175
+ fontRequests: [],
176
+ };
177
+ });
178
+ rootCausesForShift.fontRequests.push(req);
179
+ }
180
+ }
181
+ return rootCausesByShift;
182
+ }
71
183
  export function generateInsight(traceParsedData, context) {
72
- const compositeAnimationEvents = traceParsedData.Animations.animations.filter(event => {
184
+ const isWithinSameNavigation = ((event) => {
73
185
  const nav = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);
74
186
  return nav?.args.data?.navigationId === context.navigationId;
75
187
  });
188
+ const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation);
76
189
  const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);
190
+ const iframeEvents = traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);
191
+ const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation);
192
+ const layoutShifts = traceParsedData.LayoutShifts.clusters.flatMap(cluster =>
193
+ // Use one of the events in the cluster to determine if within the same navigation.
194
+ isWithinSameNavigation(cluster.events[0]) ? cluster.events : []);
195
+ const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);
196
+ // Get root causes.
197
+ const rootCausesByShift = new Map();
198
+ const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);
199
+ for (const shift of layoutShifts) {
200
+ rootCausesByShift.set(shift, { iframes: [], fontRequests: [] });
201
+ }
202
+ getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
203
+ getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);
77
204
  return {
78
205
  animationFailures,
206
+ shifts: rootCausesByShift,
79
207
  };
80
208
  }
81
209
  //# sourceMappingURL=CumulativeLayoutShift.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CumulativeLayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AASjD,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AAChC,CAAC;AA2BD;;;;;GAKG;AACH,MAAM,0BAA0B,GAAG;IACjC;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,mFAAkD;KAC1D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,2FAAsD;KAC9D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,+EAAgD;KACxD;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,uFAAoD;KAC5D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,iFAAiD;KACzD;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,qFAAmD;KAC3D;CACF,CAAC;AAEF;;GAEG;AACH,SAAS,0BAA0B,CAAC,UAA+D;IAEjG,MAAM,QAAQ,GAAoC,EAAE,CAAC;IACrD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QAC9C,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;QAC1D;;;WAGG;QACH,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;YACpD,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC;YACpE,IAAI,CAAC,WAAW,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3C,SAAS;YACX,CAAC;YACD,MAAM,cAAc,GAAG,0BAA0B,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBACzG,OAAO,MAAM,CAAC,OAAO,CAAC;YACxB,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,GAAkC;gBAC7C,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW;gBACtC,cAAc;gBACd,qBAAqB;aACtB,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,eAA0C,EAAE,OAAiC;IAE3G,MAAM,wBAAwB,GAAG,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpF,MAAM,GAAG,GACL,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,OAAO,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,wBAAwB,CAAC,CAAC;IAC/E,OAAO;QACL,iBAAiB;KAClB,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 Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n type InsightResult,\n type NavigationInsightContext,\n type RequiredData,\n} from './types.js';\n\nexport function deps(): ['Meta', 'Animations'] {\n return ['Meta', 'Animations'];\n}\n\nexport const enum AnimationFailureReasons {\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_MAY_MOVE_PIXELS = 'FILTER_MAY_MOVE_PIXELS',\n NON_REPLACE_COMPOSITE_MODE = 'NON_REPLACE_COMPOSITE_MODE',\n INCOMPATIBLE_ANIMATIONS = 'INCOMPATIBLE_ANIMATIONS',\n UNSUPPORTED_TIMING_PARAMS = 'UNSUPPORTED_TIMING_PARAMS',\n}\n\nexport interface NoncompositedAnimationFailure {\n /**\n * Animation name.\n */\n name?: string;\n /**\n * Failure reason based on mask number defined in\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22.\n */\n failureReasons: AnimationFailureReasons[];\n /**\n * Unsupported properties.\n */\n unsupportedProperties?: Types.TraceEvents.TraceEventAnimation['args']['data']['unsupportedProperties'];\n}\n\n/**\n * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define\n * which bit corresponds to each failure reason.\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22\n * @type {{flag: number, failure: AnimationFailureReasons}[]}\n */\nconst ACTIONABLE_FAILURE_REASONS = [\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS,\n },\n];\n\n/**\n * Returns a list of NoncompositedAnimationFailures.\n */\nfunction getNonCompositedAnimations(animations: readonly Types.TraceEvents.SyntheticAnimationPair[]):\n NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n for (const event of animations) {\n const beginEvent = event.args.data.beginEvent;\n const instantEvents = event.args.data.instantEvents || [];\n /**\n * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').\n * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.\n */\n for (const event of instantEvents) {\n const failureMask = event.args.data.compositeFailed;\n const unsupportedProperties = event.args.data.unsupportedProperties;\n if (!failureMask || !unsupportedProperties) {\n continue;\n }\n const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => {\n return reason.failure;\n });\n const failure: NoncompositedAnimationFailure = {\n name: beginEvent.args.data.displayName,\n failureReasons,\n unsupportedProperties,\n };\n failures.push(failure);\n }\n }\n return failures;\n}\n\nexport function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext):\n InsightResult<{animationFailures?: readonly NoncompositedAnimationFailure[]}> {\n const compositeAnimationEvents = traceParsedData.Animations.animations.filter(event => {\n const nav =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return nav?.args.data?.navigationId === context.navigationId;\n });\n const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);\n return {\n animationFailures,\n };\n}\n"]}
1
+ {"version":3,"file":"CumulativeLayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAQ3C,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;AACnE,CAAC;AA2BD;;;;;GAKG;AACH,MAAM,0BAA0B,GAAG;IACjC;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,mFAAkD;KAC1D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,2FAAsD;KAC9D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,EAAE;QACb,OAAO,+EAAgD;KACxD;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,uFAAoD;KAC5D;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,iFAAiD;KACzD;IACD;QACE,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,OAAO,qFAAmD;KAC3D;CACF,CAAC;AAEF,gBAAgB;AAChB,uFAAuF;AACvF,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAO5F,SAAS,sBAAsB,CAC3B,KAAuC,EAAE,WAA6C;IACxF,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7D,OAAO,QAAQ,GAAG,WAAW,CAAC,EAAE,IAAI,QAAQ,IAAI,WAAW,CAAC,EAAE,GAAG,mBAAmB,CAAC;AACvF,CAAC;AAED;;GAEG;AACH,SAAS,0BAA0B,CAAC,UAA+D;IAEjG,MAAM,QAAQ,GAAoC,EAAE,CAAC;IACrD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QAC9C,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;QAC1D;;;WAGG;QACH,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;YACpD,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC;YACpE,IAAI,CAAC,WAAW,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3C,SAAS;YACX,CAAC;YACD,MAAM,cAAc,GAAG,0BAA0B,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBACzG,OAAO,MAAM,CAAC,OAAO,CAAC;YACxB,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,GAAkC;gBAC7C,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW;gBACtC,cAAc;gBACd,qBAAqB;aACtB,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAC9B,YAAuD,EACvD,cAAsD;IAExD,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAmF,CAAC;IAEpH,wDAAwD;IACxD,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;QAC3G,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7B,mEAAmE;YACnE,SAAS;QACX,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACrF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACpD,iGAAiG;gBACjG,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CACzB,cAAsD,EACtD,WAA6C;IAC/C,oEAAoE;IACpE,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,WAAW,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACvF,gDAAgD;IAChD,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,cAAc,CAAC,iBAAiB,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CACxB,mBAA2F,EAC3F,cAAsD,EACtD,gBAAsG,EACtG,iBAA0F;IAE5F,KAAK,MAAM,WAAW,IAAI,mBAAmB,EAAE,CAAC;QAC9C,MAAM,YAAY,GAAG,oBAAoB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QACvE,sDAAsD;QACtD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAClD,mDAAmD;QACnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC7F,OAAO;oBACL,OAAO,EAAE,EAAE;oBACX,YAAY,EAAE,EAAE;iBACjB,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACtB,eAA4D,EAC5D,cAAsD,EACtD,gBAAsG,EACtG,iBAA0F;IAE5F,MAAM,YAAY,GACd,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAEtH,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,oBAAoB,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,SAAS;QACX,CAAC;QAED,+EAA+E;QAC/E,IAAI,CAAC,sBAAsB,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,8CAA8C;QAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAElD,2EAA2E;QAC3E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,yDAAyD;QACzD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE;gBAC7F,OAAO;oBACL,OAAO,EAAE,EAAE;oBACX,YAAY,EAAE,EAAE;iBACjB,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,eAA0C,EAAE,OAAiC;IAI/E,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAuC,EAAW,EAAE;QACnF,MAAM,GAAG,GACL,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,OAAO,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,wBAAwB,GAAG,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACtG,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,wBAAwB,CAAC,CAAC;IAE/E,MAAM,YAAY,GACd,eAAe,CAAC,YAAY,CAAC,qCAAqC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACtG,MAAM,eAAe,GAAG,eAAe,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAE9F,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAC9D,OAAO,CAAC,EAAE;IACN,mFAAmF;IACvF,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAClE,CAAC;IACF,MAAM,cAAc,GAAG,eAAe,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAElG,mBAAmB;IACnB,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAsE,CAAC;IACxG,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAEjF,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,EAAC,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAC,CAAC,CAAC;IAChE,CAAC;IAED,mBAAmB,CAAC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IACvF,iBAAiB,CAAC,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IAExF,OAAO;QACL,iBAAiB;QACjB,MAAM,EAAE,iBAAiB;KAC1B,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 Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type InsightResult,\n type NavigationInsightContext,\n type RequiredData,\n} from './types.js';\n\nexport function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'] {\n return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];\n}\n\nexport const enum AnimationFailureReasons {\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_MAY_MOVE_PIXELS = 'FILTER_MAY_MOVE_PIXELS',\n NON_REPLACE_COMPOSITE_MODE = 'NON_REPLACE_COMPOSITE_MODE',\n INCOMPATIBLE_ANIMATIONS = 'INCOMPATIBLE_ANIMATIONS',\n UNSUPPORTED_TIMING_PARAMS = 'UNSUPPORTED_TIMING_PARAMS',\n}\n\nexport interface NoncompositedAnimationFailure {\n /**\n * Animation name.\n */\n name?: string;\n /**\n * Failure reason based on mask number defined in\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22.\n */\n failureReasons: AnimationFailureReasons[];\n /**\n * Unsupported properties.\n */\n unsupportedProperties?: Types.TraceEvents.TraceEventAnimation['args']['data']['unsupportedProperties'];\n}\n\n/**\n * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define\n * which bit corresponds to each failure reason.\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22\n * @type {{flag: number, failure: AnimationFailureReasons}[]}\n */\nconst ACTIONABLE_FAILURE_REASONS = [\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS,\n },\n];\n\n// 500ms window.\n// Use this window to consider events and requests that may have caused a layout shift.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\nexport interface LayoutShiftRootCausesData {\n iframes: Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[];\n fontRequests: Types.TraceEvents.SyntheticNetworkRequest[];\n}\n\nfunction isInInvalidationWindow(\n event: Types.TraceEvents.TraceEventData, targetEvent: Types.TraceEvents.TraceEventData): boolean {\n const eventEnd = event.dur ? event.ts + event.dur : event.ts;\n return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;\n}\n\n/**\n * Returns a list of NoncompositedAnimationFailures.\n */\nfunction getNonCompositedAnimations(animations: readonly Types.TraceEvents.SyntheticAnimationPair[]):\n NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n for (const event of animations) {\n const beginEvent = event.args.data.beginEvent;\n const instantEvents = event.args.data.instantEvents || [];\n /**\n * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').\n * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.\n */\n for (const event of instantEvents) {\n const failureMask = event.args.data.compositeFailed;\n const unsupportedProperties = event.args.data.unsupportedProperties;\n if (!failureMask || !unsupportedProperties) {\n continue;\n }\n const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => {\n return reason.failure;\n });\n const failure: NoncompositedAnimationFailure = {\n name: beginEvent.args.data.displayName,\n failureReasons,\n unsupportedProperties,\n };\n failures.push(failure);\n }\n }\n return failures;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]> {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n\n/**\n * This gets the first prePaint event that follows the provided event and returns it.\n */\nfunction getNextPrePaintEvent(\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n targetEvent: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventPrePaint|undefined {\n // Get the first PrePaint event that happened after the targetEvent.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));\n // No PrePaint event registered after this event\n if (nextPrePaintIndex === null) {\n return undefined;\n }\n\n return prePaintEvents[nextPrePaintIndex];\n}\n\n/**\n * An Iframe is considered a root cause if the iframe event occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs.\n */\nfunction getIframeRootCauses(\n iframeCreatedEvents: readonly Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>,\n rootCausesByShift: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>):\n Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData> {\n for (const iframeEvent of iframeCreatedEvents) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);\n // If no following prePaint, this is not a root cause.\n if (!nextPrePaint) {\n continue;\n }\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n // if no layout shift(s), this is not a root cause.\n if (!shifts) {\n continue;\n }\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframes: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.iframes.push(iframeEvent);\n }\n }\n return rootCausesByShift;\n}\n\n/**\n * A font request is considered a root cause if the request occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should\n * happen within the INVALIDATION_WINDOW of the prePaint event.\n */\nfunction getFontRootCauses(\n networkRequests: Types.TraceEvents.SyntheticNetworkRequest[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map<Types.TraceEvents.TraceEventPrePaint, Types.TraceEvents.TraceEventLayoutShift[]>,\n rootCausesByShift: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>):\n Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData> {\n const fontRequests =\n networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));\n\n for (const req of fontRequests) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);\n if (!nextPrePaint) {\n continue;\n }\n\n // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.\n if (!isInInvalidationWindow(req, nextPrePaint)) {\n continue;\n }\n\n // Get the shifts that belong to this prepaint\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n\n // if no layout shift(s) in this prePaint, the request is not a root cause.\n if (!shifts) {\n continue;\n }\n // Include the root cause to the shifts in this prePaint.\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframes: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.fontRequests.push(req);\n }\n }\n return rootCausesByShift;\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext): InsightResult<{\n animationFailures?: readonly NoncompositedAnimationFailure[],\n shifts?: Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>,\n}> {\n const isWithinSameNavigation = ((event: Types.TraceEvents.TraceEventData): boolean => {\n const nav =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return nav?.args.data?.navigationId === context.navigationId;\n });\n\n const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation);\n const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);\n\n const iframeEvents =\n traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);\n const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation);\n\n const layoutShifts = traceParsedData.LayoutShifts.clusters.flatMap(\n cluster =>\n // Use one of the events in the cluster to determine if within the same navigation.\n isWithinSameNavigation(cluster.events[0]) ? cluster.events : [],\n );\n const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);\n\n // Get root causes.\n const rootCausesByShift = new Map<Types.TraceEvents.TraceEventLayoutShift, LayoutShiftRootCausesData>();\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n for (const shift of layoutShifts) {\n rootCausesByShift.set(shift, {iframes: [], fontRequests: []});\n }\n\n getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n\n return {\n animationFailures,\n shifts: rootCausesByShift,\n };\n}\n"]}
@@ -29,6 +29,20 @@ export function generateInsight(traceParsedData, context) {
29
29
  if (req.args.data.syntheticData.finishTime > firstPaintTs) {
30
30
  continue;
31
31
  }
32
+ // If a resource is marked `in_body_parser_blocking` it should only be considered render blocking if it is a
33
+ // high enough priority. Some resources (e.g. scripts) are not marked as high priority if they are fetched
34
+ // after a non-preloaded image. (See "early" definition in https://web.dev/articles/fetch-priority)
35
+ //
36
+ // There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation
37
+ // of render blocking resources in the document body.
38
+ if (req.args.data.renderBlocking === 'in_body_parser_blocking') {
39
+ const priority = req.args.data.priority;
40
+ const isScript = req.args.data.resourceType === "Script" /* Protocol.Network.ResourceType.Script */;
41
+ const isBlockingScript = isScript && priority === "High" /* Protocol.Network.ResourcePriority.High */;
42
+ if (priority !== "VeryHigh" /* Protocol.Network.ResourcePriority.VeryHigh */ && !isBlockingScript) {
43
+ continue;
44
+ }
45
+ }
32
46
  const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);
33
47
  if (navigation?.args.data?.navigationId !== context.navigationId) {
34
48
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAqB,cAAc,EAAmD,MAAM,YAAY,CAAC;AAEhH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,eAA0C,EAAE,OAAiC;IAE3G,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QACtE,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;QAC3B,EAAE,GAAG,iEAAsD;QAC3D,EAAE,KAAK,EAAE,EAAE,CAAC;IACrC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL,sBAAsB,EAAE,EAAE;YAC1B,QAAQ,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,sBAAsB,GAAG,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,yBAAyB,EAAE,CAAC;YAC9G,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,GAAG,YAAY,EAAE,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9G,IAAI,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACjE,SAAS;QACX,CAAC;QAED,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACL,sBAAsB;KACvB,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 Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics'] {\n return ['NetworkRequests', 'PageLoadMetrics'];\n}\n\nexport function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext):\n InsightResult<{renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[]}> {\n const firstPaintTs = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)\n ?.get(context.navigationId)\n ?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)\n ?.event?.ts;\n if (!firstPaintTs) {\n return {\n renderBlockingRequests: [],\n warnings: [InsightWarning.NO_FP],\n };\n }\n\n const renderBlockingRequests = [];\n for (const req of traceParsedData.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n if (req.args.data.renderBlocking !== 'blocking' && req.args.data.renderBlocking !== 'in_body_parser_blocking') {\n continue;\n }\n\n if (req.args.data.syntheticData.finishTime > firstPaintTs) {\n continue;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n if (navigation?.args.data?.navigationId !== context.navigationId) {\n continue;\n }\n\n renderBlockingRequests.push(req);\n }\n\n return {\n renderBlockingRequests,\n };\n}\n"]}
1
+ {"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAqB,cAAc,EAAmD,MAAM,YAAY,CAAC;AAEhH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,eAA0C,EAAE,OAAiC;IAE3G,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QACtE,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;QAC3B,EAAE,GAAG,iEAAsD;QAC3D,EAAE,KAAK,EAAE,EAAE,CAAC;IACrC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;YACL,sBAAsB,EAAE,EAAE;YAC1B,QAAQ,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,sBAAsB,GAAG,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,yBAAyB,EAAE,CAAC;YAC9G,SAAS;QACX,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,GAAG,YAAY,EAAE,CAAC;YAC1D,SAAS;QACX,CAAC;QAED,4GAA4G;QAC5G,0GAA0G;QAC1G,mGAAmG;QACnG,EAAE;QACF,qGAAqG;QACrG,qDAAqD;QACrD,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,yBAAyB,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,wDAAyC,CAAC;YACrF,MAAM,gBAAgB,GAAG,QAAQ,IAAI,QAAQ,wDAA2C,CAAC;YACzF,IAAI,QAAQ,gEAA+C,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACjF,SAAS;YACX,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC9G,IAAI,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACjE,SAAS;QACX,CAAC;QAED,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO;QACL,sBAAsB;KACvB,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 Protocol from '../../../generated/protocol.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 {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics'] {\n return ['NetworkRequests', 'PageLoadMetrics'];\n}\n\nexport function generateInsight(traceParsedData: RequiredData<typeof deps>, context: NavigationInsightContext):\n InsightResult<{renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[]}> {\n const firstPaintTs = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)\n ?.get(context.navigationId)\n ?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)\n ?.event?.ts;\n if (!firstPaintTs) {\n return {\n renderBlockingRequests: [],\n warnings: [InsightWarning.NO_FP],\n };\n }\n\n const renderBlockingRequests = [];\n for (const req of traceParsedData.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n if (req.args.data.renderBlocking !== 'blocking' && req.args.data.renderBlocking !== 'in_body_parser_blocking') {\n continue;\n }\n\n if (req.args.data.syntheticData.finishTime > firstPaintTs) {\n continue;\n }\n\n // If a resource is marked `in_body_parser_blocking` it should only be considered render blocking if it is a\n // high enough priority. Some resources (e.g. scripts) are not marked as high priority if they are fetched\n // after a non-preloaded image. (See \"early\" definition in https://web.dev/articles/fetch-priority)\n //\n // There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation\n // of render blocking resources in the document body.\n if (req.args.data.renderBlocking === 'in_body_parser_blocking') {\n const priority = req.args.data.priority;\n const isScript = req.args.data.resourceType === Protocol.Network.ResourceType.Script;\n const isBlockingScript = isScript && priority === Protocol.Network.ResourcePriority.High;\n if (priority !== Protocol.Network.ResourcePriority.VeryHigh && !isBlockingScript) {\n continue;\n }\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n if (navigation?.args.data?.navigationId !== context.navigationId) {\n continue;\n }\n\n renderBlockingRequests.push(req);\n }\n\n return {\n renderBlockingRequests,\n };\n}\n"]}
@@ -30,7 +30,6 @@
30
30
  },
31
31
  "files": [
32
32
  "../../../../../../front_end/models/trace/EntriesFilter.ts",
33
- "../../../../../../front_end/models/trace/LegacyTracingModel.ts",
34
33
  "../../../../../../front_end/models/trace/ModelImpl.ts",
35
34
  "../../../../../../front_end/models/trace/Processor.ts",
36
35
  "../../../../../../front_end/models/trace/TracingManager.ts",
@@ -3,10 +3,9 @@ import * as Extras from './extras/extras.js';
3
3
  import * as Handlers from './handlers/handlers.js';
4
4
  import * as Helpers from './helpers/helpers.js';
5
5
  import * as Insights from './insights/insights.js';
6
- import * as Legacy from './LegacyTracingModel.js';
7
6
  import * as TraceModel from './ModelImpl.js';
8
7
  import * as Processor from './Processor.js';
9
8
  import * as RootCauses from './root-causes/root-causes.js';
10
9
  import * as TracingManager from './TracingManager.js';
11
10
  import * as Types from './types/types.js';
12
- export { EntriesFilter, Extras, Handlers, Helpers, Insights, Legacy, Processor, RootCauses, TraceModel, TracingManager, Types, };
11
+ export { EntriesFilter, Extras, Handlers, Helpers, Insights, Processor, RootCauses, TraceModel, TracingManager, Types, };
@@ -6,13 +6,10 @@ import * as Extras from './extras/extras.js';
6
6
  import * as Handlers from './handlers/handlers.js';
7
7
  import * as Helpers from './helpers/helpers.js';
8
8
  import * as Insights from './insights/insights.js';
9
- // Purposefully use a shorter name here so references to this are
10
- // Legacy.TracingModel.
11
- import * as Legacy from './LegacyTracingModel.js';
12
9
  import * as TraceModel from './ModelImpl.js';
13
10
  import * as Processor from './Processor.js';
14
11
  import * as RootCauses from './root-causes/root-causes.js';
15
12
  import * as TracingManager from './TracingManager.js';
16
13
  import * as Types from './types/types.js';
17
- export { EntriesFilter, Extras, Handlers, Helpers, Insights, Legacy, Processor, RootCauses, TraceModel, TracingManager, Types, };
14
+ export { EntriesFilter, Extras, Handlers, Helpers, Insights, Processor, RootCauses, TraceModel, TracingManager, Types, };
18
15
  //# sourceMappingURL=trace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/trace.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,iEAAiE;AACjE,uBAAuB;AACvB,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,UAAU,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EACL,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,EACd,KAAK,GACN,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as EntriesFilter from './EntriesFilter.js';\nimport * as Extras from './extras/extras.js';\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\n// Purposefully use a shorter name here so references to this are\n// Legacy.TracingModel.\nimport * as Legacy from './LegacyTracingModel.js';\nimport * as TraceModel from './ModelImpl.js';\nimport * as Processor from './Processor.js';\nimport * as RootCauses from './root-causes/root-causes.js';\nimport * as TracingManager from './TracingManager.js';\nimport * as Types from './types/types.js';\n\nexport {\n EntriesFilter,\n Extras,\n Handlers,\n Helpers,\n Insights,\n Legacy,\n Processor,\n RootCauses,\n TraceModel,\n TracingManager,\n Types,\n};\n"]}
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/trace.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,UAAU,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EACL,aAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,UAAU,EACV,UAAU,EACV,cAAc,EACd,KAAK,GACN,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as EntriesFilter from './EntriesFilter.js';\nimport * as Extras from './extras/extras.js';\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as TraceModel from './ModelImpl.js';\nimport * as Processor from './Processor.js';\nimport * as RootCauses from './root-causes/root-causes.js';\nimport * as TracingManager from './TracingManager.js';\nimport * as Types from './types/types.js';\n\nexport {\n EntriesFilter,\n Extras,\n Handlers,\n Helpers,\n Insights,\n Processor,\n RootCauses,\n TraceModel,\n TracingManager,\n Types,\n};\n"]}
@@ -1,5 +1,6 @@
1
+ import type * as Protocol from '../../../generated/protocol.js';
1
2
  import { type TraceWindowMicroSeconds } from './Timing.js';
2
- import { type TraceEventData } from './TraceEvents.js';
3
+ import { type ProcessID, type SampleIndex, type ThreadID, type TraceEventData } from './TraceEvents.js';
3
4
  export type TraceFile = {
4
5
  traceEvents: readonly TraceEventData[];
5
6
  metadata: MetaData;
@@ -12,10 +13,14 @@ export declare const enum DataOrigin {
12
13
  CPUProfile = "CPUProfile",
13
14
  TraceEvents = "TraceEvents"
14
15
  }
15
- export interface Annotations {
16
- entriesFilterAnnotations: {
17
- hiddenEntriesIndexes: number[];
18
- modifiedEntriesIndexes: number[];
16
+ export type RawEventKey = ['r', number];
17
+ export type ProfileCallKey = ['p', ProcessID, ThreadID, SampleIndex, Protocol.integer];
18
+ export type SyntheticEventKey = ['s', number];
19
+ export type TraceEventSerializableKey = RawEventKey | ProfileCallKey | SyntheticEventKey;
20
+ export interface Modifications {
21
+ entriesModifications: {
22
+ hiddenEntries: string[];
23
+ expandableEntries: string[];
19
24
  };
20
25
  initialBreadcrumb: Breadcrumb;
21
26
  }
@@ -31,6 +36,6 @@ export interface MetaData {
31
36
  cpuThrottling?: number;
32
37
  hardwareConcurrency?: number;
33
38
  dataOrigin?: DataOrigin;
34
- annotations?: Annotations;
39
+ modifications?: Modifications;
35
40
  }
36
41
  export type Contents = TraceFile | TraceEventData[];
@@ -1,5 +1,2 @@
1
- // Copyright 2023 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
1
  export {};
5
2
  //# sourceMappingURL=File.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"File.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type TraceWindowMicroSeconds} from './Timing.js';\nimport {type TraceEventData} from './TraceEvents.js';\n\nexport type TraceFile = {\n traceEvents: readonly TraceEventData[],\n metadata: MetaData,\n};\n\nexport interface Breadcrumb {\n window: TraceWindowMicroSeconds;\n child: Breadcrumb|null;\n}\n\nexport const enum DataOrigin {\n CPUProfile = 'CPUProfile',\n TraceEvents = 'TraceEvents',\n}\nexport interface Annotations {\n entriesFilterAnnotations: {\n hiddenEntriesIndexes: number[],\n modifiedEntriesIndexes: number[],\n };\n initialBreadcrumb: Breadcrumb;\n}\n\n/**\n * Trace metadata that we persist to the file. This will allow us to\n * store specifics for the trace, e.g., which tracks should be visible\n * on load.\n */\nexport interface MetaData {\n source?: 'DevTools';\n startTime?: string;\n networkThrottling?: string;\n cpuThrottling?: number;\n hardwareConcurrency?: number;\n dataOrigin?: DataOrigin;\n annotations?: Annotations;\n}\n\nexport type Contents = TraceFile|TraceEventData[];\n"]}
1
+ {"version":3,"file":"File.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {type TraceWindowMicroSeconds} from './Timing.js';\nimport {type ProcessID, type SampleIndex, type ThreadID, type TraceEventData} from './TraceEvents.js';\n\nexport type TraceFile = {\n traceEvents: readonly TraceEventData[],\n metadata: MetaData,\n};\n\nexport interface Breadcrumb {\n window: TraceWindowMicroSeconds;\n child: Breadcrumb|null;\n}\n\nexport const enum DataOrigin {\n CPUProfile = 'CPUProfile',\n TraceEvents = 'TraceEvents',\n}\n\n// Serializable keys are created for trace events to be able to save\n// references to timeline events in a trace file. These keys enable\n// user modifications that can be saved. See go/cpq:event-data-json for\n// more details on the key format.\nexport type RawEventKey = ['r', number];\nexport type ProfileCallKey = ['p', ProcessID, ThreadID, SampleIndex, Protocol.integer];\nexport type SyntheticEventKey = ['s', number];\nexport type TraceEventSerializableKey = RawEventKey|ProfileCallKey|SyntheticEventKey;\n\nexport interface Modifications {\n entriesModifications: {\n // Entries hidden by the user\n hiddenEntries: string[],\n // Entries that parent a hiddenEntry\n expandableEntries: string[],\n };\n initialBreadcrumb: Breadcrumb;\n}\n\n/**\n * Trace metadata that we persist to the file. This will allow us to\n * store specifics for the trace, e.g., which tracks should be visible\n * on load.\n */\nexport interface MetaData {\n source?: 'DevTools';\n startTime?: string;\n networkThrottling?: string;\n cpuThrottling?: number;\n hardwareConcurrency?: number;\n dataOrigin?: DataOrigin;\n modifications?: Modifications;\n}\n\nexport type Contents = TraceFile|TraceEventData[];\n"]}
@@ -63,6 +63,7 @@ export interface TraceEventCallFrame {
63
63
  lineNumber: number;
64
64
  url: string;
65
65
  }
66
+ export declare function objectIsTraceEventCallFrame(object: {}): object is TraceEventCallFrame;
66
67
  export interface TraceFrame {
67
68
  frame: string;
68
69
  name: string;
@@ -78,7 +79,7 @@ export interface TraceEventSample extends TraceEventData {
78
79
  * A fake trace event created to support CDP.Profiler.Profiles in the
79
80
  * trace engine.
80
81
  */
81
- export interface SyntheticCpuProfile extends TraceEventInstant {
82
+ export interface SyntheticCpuProfile extends TraceEventInstant, SyntheticBasedEvent<Phase.INSTANT> {
82
83
  name: 'CpuProfile';
83
84
  args: TraceEventArgs & {
84
85
  data: TraceEventArgsData & {
@@ -119,6 +120,10 @@ export interface TraceEventComplete extends TraceEventData {
119
120
  ph: Phase.COMPLETE;
120
121
  dur: MicroSeconds;
121
122
  }
123
+ export interface TraceEventRunTask extends TraceEventComplete {
124
+ name: KnownEventName.RunTask;
125
+ }
126
+ export declare function isTraceEventRunTask(event: TraceEventData): event is TraceEventRunTask;
122
127
  export interface TraceEventFireIdleCallback extends TraceEventComplete {
123
128
  name: KnownEventName.FireIdleCallback;
124
129
  args: TraceEventArgs & {
@@ -242,7 +247,8 @@ interface SyntheticArgsData {
242
247
  totalTime: MicroSeconds;
243
248
  waiting: MicroSeconds;
244
249
  }
245
- export interface SyntheticNetworkRequest extends TraceEventComplete {
250
+ export interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticBasedEvent<Phase.COMPLETE> {
251
+ rawSourceEvent: TraceEventData;
246
252
  args: TraceEventArgs & {
247
253
  data: TraceEventArgsData & {
248
254
  syntheticData: SyntheticArgsData;
@@ -300,7 +306,8 @@ export declare const enum AuctionWorkletType {
300
306
  SELLER = "seller",
301
307
  UNKNOWN = "unknown"
302
308
  }
303
- export interface SyntheticAuctionWorkletEvent extends TraceEventInstant {
309
+ export interface SyntheticAuctionWorkletEvent extends TraceEventInstant, SyntheticBasedEvent<Phase.INSTANT> {
310
+ rawSourceEvent: TraceEventData;
304
311
  name: 'SyntheticAuctionWorkletEvent';
305
312
  pid: ProcessID;
306
313
  host: string;
@@ -363,7 +370,8 @@ export interface TraceEventScreenshot extends TraceEventData {
363
370
  ph: Phase.OBJECT_SNAPSHOT;
364
371
  }
365
372
  export declare function isTraceEventScreenshot(event: TraceEventData): event is TraceEventScreenshot;
366
- export interface SyntheticScreenshot extends TraceEventData {
373
+ export interface SyntheticScreenshot extends TraceEventData, SyntheticBasedEvent {
374
+ rawSourceEvent: TraceEventScreenshot;
367
375
  /** This is the correct presentation timestamp. */
368
376
  ts: MicroSeconds;
369
377
  args: TraceEventArgs & {
@@ -620,7 +628,9 @@ export interface LayoutShiftParsedData {
620
628
  cumulativeWeightedScoreInWindow: number;
621
629
  sessionWindowData: LayoutShiftSessionWindowData;
622
630
  }
623
- export interface SyntheticLayoutShift extends TraceEventLayoutShift {
631
+ export interface SyntheticLayoutShift extends TraceEventLayoutShift, SyntheticBasedEvent<Phase.INSTANT> {
632
+ name: 'LayoutShift';
633
+ rawSourceEvent: TraceEventLayoutShift;
624
634
  args: TraceEventArgs & {
625
635
  frame: string;
626
636
  data?: LayoutShiftData & {
@@ -651,6 +661,7 @@ export interface TraceEventResourceSendRequest extends TraceEventInstant {
651
661
  requestMethod?: string;
652
662
  renderBlocking?: RenderBlocking;
653
663
  initiator?: Initiator;
664
+ isLinkPreload?: boolean;
654
665
  };
655
666
  };
656
667
  }
@@ -733,7 +744,6 @@ export interface TraceEventResourceReceiveResponse extends TraceEventInstant {
733
744
  responseTime: MilliSeconds;
734
745
  statusCode: number;
735
746
  timing: TraceEventResourceReceiveResponseTimingData;
736
- isLinkPreload?: boolean;
737
747
  connectionId: number;
738
748
  connectionReused: boolean;
739
749
  headers?: Array<{
@@ -842,6 +852,14 @@ export interface TraceEventScheduleStyleRecalculation extends TraceEventInstant
842
852
  };
843
853
  }
844
854
  export declare function isTraceEventScheduleStyleRecalculation(event: TraceEventData): event is TraceEventScheduleStyleRecalculation;
855
+ export interface TraceEventRenderFrameImplCreateChildFrame extends TraceEventData {
856
+ name: KnownEventName.RenderFrameImplCreateChildFrame;
857
+ args: TraceEventArgs & {
858
+ child_frame_token: string;
859
+ frame_token: string;
860
+ };
861
+ }
862
+ export declare function isTraceEventRenderFrameImplCreateChildFrame(event: TraceEventData): event is TraceEventRenderFrameImplCreateChildFrame;
845
863
  export interface TraceEventPrePaint extends TraceEventComplete {
846
864
  name: 'PrePaint';
847
865
  }
@@ -994,7 +1012,16 @@ export interface TraceEventPipelineReporter extends TraceEventData {
994
1012
  };
995
1013
  }
996
1014
  export declare function isTraceEventPipelineReporter(event: TraceEventData): event is TraceEventPipelineReporter;
997
- export interface SyntheticEventPair<T extends TraceEventPairableAsync = TraceEventPairableAsync> extends TraceEventData {
1015
+ export interface SyntheticBasedEvent<Ph extends Phase = Phase> extends SyntheticEntry {
1016
+ ph: Ph;
1017
+ rawSourceEvent: TraceEventData;
1018
+ }
1019
+ export type SyntheticEntry = TraceEventData & {
1020
+ _tag: 'SyntheticEntryTag';
1021
+ };
1022
+ export declare function isSyntheticBasedEvent(event: TraceEventData): event is SyntheticBasedEvent;
1023
+ export interface SyntheticEventPair<T extends TraceEventPairableAsync = TraceEventPairableAsync> extends SyntheticBasedEvent {
1024
+ rawSourceEvent: TraceEventData;
998
1025
  name: T['name'];
999
1026
  cat: T['cat'];
1000
1027
  id?: string;
@@ -1050,6 +1077,7 @@ export interface SyntheticProfileCall extends SyntheticTraceEntry {
1050
1077
  nodeId: Protocol.integer;
1051
1078
  sampleIndex: number;
1052
1079
  profileId: ProfileID;
1080
+ selfTime: MicroSeconds;
1053
1081
  }
1054
1082
  /**
1055
1083
  * A JS Sample reflects a single sample from the V8 CPU Profile
@@ -1237,7 +1265,7 @@ export interface TraceEventLayout extends TraceEventComplete {
1237
1265
  partialLayout: boolean;
1238
1266
  totalObjects: number;
1239
1267
  };
1240
- endData: {
1268
+ endData?: {
1241
1269
  layoutRoots: Array<{
1242
1270
  depth: number;
1243
1271
  nodeId: Protocol.DOM.BackendNodeId;
@@ -1267,6 +1295,11 @@ declare class CallFrameIdTag {
1267
1295
  }
1268
1296
  export type CallFrameID = number & CallFrameIdTag;
1269
1297
  export declare function CallFrameID(value: number): CallFrameID;
1298
+ declare class SampleIndexTag {
1299
+ #private;
1300
+ }
1301
+ export type SampleIndex = number & SampleIndexTag;
1302
+ export declare function SampleIndex(value: number): SampleIndex;
1270
1303
  declare class ProcessIdTag {
1271
1304
  #private;
1272
1305
  }
@@ -1526,12 +1559,64 @@ export interface TraceEventWebSocketCreate extends TraceEventInstant {
1526
1559
  identifier: number;
1527
1560
  url: string;
1528
1561
  frame?: string;
1562
+ workerId?: string;
1529
1563
  websocketProtocol?: string;
1530
1564
  stackTrace?: TraceEventCallFrame;
1531
1565
  };
1532
1566
  };
1533
1567
  }
1534
1568
  export declare function isTraceEventWebSocketCreate(event: TraceEventData): event is TraceEventWebSocketCreate;
1569
+ export interface TraceEventWebSocketInfo extends TraceEventInstant {
1570
+ name: KnownEventName.WebSocketDestroy | KnownEventName.WebSocketReceiveHandshake | KnownEventName.WebSocketReceiveHandshakeResponse;
1571
+ args: TraceEventArgs & {
1572
+ data: TraceEventArgsData & {
1573
+ identifier: number;
1574
+ url: string;
1575
+ frame?: string;
1576
+ workerId?: string;
1577
+ };
1578
+ };
1579
+ }
1580
+ export interface TraceEventWebSocketTransfer extends TraceEventInstant {
1581
+ name: KnownEventName.WebSocketSend | KnownEventName.WebSocketReceive;
1582
+ args: TraceEventArgs & {
1583
+ data: TraceEventArgsData & {
1584
+ identifier: number;
1585
+ url: string;
1586
+ frame?: string;
1587
+ workerId?: string;
1588
+ dataLength: number;
1589
+ };
1590
+ };
1591
+ }
1592
+ export declare function isTraceEventWebSocketInfo(traceEventData: TraceEventData): traceEventData is TraceEventWebSocketInfo;
1593
+ export declare function isTraceEventWebSocketTransfer(traceEventData: TraceEventData): traceEventData is TraceEventWebSocketTransfer;
1594
+ export interface TraceEventWebSocketSend extends TraceEventInstant {
1595
+ name: KnownEventName.WebSocketSend;
1596
+ args: TraceEventArgs & {
1597
+ data: TraceEventArgsData & {
1598
+ identifier: number;
1599
+ url: string;
1600
+ frame?: string;
1601
+ workerId?: string;
1602
+ dataLength: number;
1603
+ };
1604
+ };
1605
+ }
1606
+ export declare function isTraceEventWebSocketSend(event: TraceEventData): event is TraceEventWebSocketSend;
1607
+ export interface TraceEventWebSocketReceive extends TraceEventInstant {
1608
+ name: KnownEventName.WebSocketReceive;
1609
+ args: TraceEventArgs & {
1610
+ data: TraceEventArgsData & {
1611
+ identifier: number;
1612
+ url: string;
1613
+ frame?: string;
1614
+ workerId?: string;
1615
+ dataLength: number;
1616
+ };
1617
+ };
1618
+ }
1619
+ export declare function isTraceEventWebSocketReceive(event: TraceEventData): event is TraceEventWebSocketReceive;
1535
1620
  export interface TraceEventWebSocketSendHandshakeRequest extends TraceEventInstant {
1536
1621
  name: KnownEventName.WebSocketSendHandshakeRequest;
1537
1622
  args: TraceEventArgs & {
@@ -1562,7 +1647,8 @@ export interface TraceEventWebSocketDestroy extends TraceEventInstant {
1562
1647
  };
1563
1648
  }
1564
1649
  export declare function isTraceEventWebSocketDestroy(event: TraceEventData): event is TraceEventWebSocketDestroy;
1565
- export declare function isWebSocketTraceEvent(event: TraceEventData): event is TraceEventWebSocketCreate | TraceEventWebSocketDestroy | TraceEventWebSocketReceiveHandshakeResponse | TraceEventWebSocketSendHandshakeRequest;
1650
+ export declare function isWebSocketTraceEvent(event: TraceEventData): event is TraceEventWebSocketCreate | TraceEventWebSocketInfo | TraceEventWebSocketTransfer;
1651
+ export type WebSocketEvent = TraceEventWebSocketCreate | TraceEventWebSocketInfo | TraceEventWebSocketTransfer;
1566
1652
  export interface TraceEventV8Compile extends TraceEventComplete {
1567
1653
  name: KnownEventName.Compile;
1568
1654
  args: TraceEventArgs & {
@@ -1646,6 +1732,8 @@ export declare const enum KnownEventName {
1646
1732
  WebSocketSendHandshake = "WebSocketSendHandshakeRequest",
1647
1733
  WebSocketReceiveHandshake = "WebSocketReceiveHandshakeResponse",
1648
1734
  WebSocketDestroy = "WebSocketDestroy",
1735
+ WebSocketSend = "WebSocketSend",
1736
+ WebSocketReceive = "WebSocketReceive",
1649
1737
  CryptoDoEncrypt = "DoEncrypt",
1650
1738
  CryptoDoEncryptReply = "DoEncryptReply",
1651
1739
  CryptoDoDecrypt = "DoDecrypt",
@@ -1755,6 +1843,12 @@ export declare const enum KnownEventName {
1755
1843
  InputLatencyMouseWheel = "InputLatency::MouseWheel",
1756
1844
  ImplSideFling = "InputHandlerProxy::HandleGestureFling::started",
1757
1845
  SchedulePostMessage = "SchedulePostMessage",
1758
- HandlePostMessage = "HandlePostMessage"
1846
+ HandlePostMessage = "HandlePostMessage",
1847
+ RenderFrameImplCreateChildFrame = "RenderFrameImpl::createChildFrame"
1759
1848
  }
1849
+ export declare const Categories: {
1850
+ readonly Console: "blink.console";
1851
+ readonly UserTiming: "blink.user_timing";
1852
+ readonly Loading: "loading";
1853
+ };
1760
1854
  export {};