@atlaskit/react-ufo 4.6.0 → 4.6.2

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 (29) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/create-post-interaction-log-payload/get-late-mutations.js +15 -3
  3. package/dist/cjs/create-post-interaction-log-payload/index.js +2 -1
  4. package/dist/cjs/hidden-timing/index.js +11 -7
  5. package/dist/cjs/vc/vc-observer-new/index.js +74 -11
  6. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +101 -60
  7. package/dist/es2019/create-post-interaction-log-payload/get-late-mutations.js +12 -3
  8. package/dist/es2019/create-post-interaction-log-payload/index.js +2 -1
  9. package/dist/es2019/hidden-timing/index.js +11 -7
  10. package/dist/es2019/vc/vc-observer-new/index.js +67 -10
  11. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +42 -11
  12. package/dist/esm/create-post-interaction-log-payload/get-late-mutations.js +15 -3
  13. package/dist/esm/create-post-interaction-log-payload/index.js +2 -1
  14. package/dist/esm/hidden-timing/index.js +11 -7
  15. package/dist/esm/vc/vc-observer-new/index.js +74 -11
  16. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +101 -60
  17. package/dist/types/common/react-ufo-payload-schema.d.ts +2 -0
  18. package/dist/types/common/vc/types.d.ts +7 -0
  19. package/dist/types/create-post-interaction-log-payload/get-late-mutations.d.ts +2 -2
  20. package/dist/types/vc/vc-observer/getVCRevisionDebugDetails.d.ts +1 -1
  21. package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -0
  22. package/dist/types/vc/vc-observer-new/types.d.ts +5 -0
  23. package/dist/types-ts4.5/common/react-ufo-payload-schema.d.ts +2 -0
  24. package/dist/types-ts4.5/common/vc/types.d.ts +7 -0
  25. package/dist/types-ts4.5/create-post-interaction-log-payload/get-late-mutations.d.ts +2 -2
  26. package/dist/types-ts4.5/vc/vc-observer/getVCRevisionDebugDetails.d.ts +1 -1
  27. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -0
  28. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +5 -0
  29. package/package.json +7 -4
@@ -1,4 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { fg } from '@atlaskit/platform-feature-flags';
2
3
  import { SSRPlaceholderHandlers } from '../vc-observer/observers/ssr-placeholders';
3
4
  import EntriesTimeline from './entries-timeline';
4
5
  import getElementName from './get-element-name';
@@ -61,18 +62,27 @@ export default class VCObserverNew {
61
62
  if (element) {
62
63
  elementName = this.getElementName(element);
63
64
  }
65
+ const data = {
66
+ type,
67
+ elementName,
68
+ rect,
69
+ previousRect,
70
+ visible,
71
+ attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
72
+ oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
73
+ newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
74
+ };
75
+ if (element && this.isPostInteraction && fg('platform_ufo_enable_late_mutation_label_stacks')) {
76
+ const labelStacks = getLabelStacks(element);
77
+ if (labelStacks) {
78
+ Object.assign(data, {
79
+ labelStacks
80
+ });
81
+ }
82
+ }
64
83
  this.entriesTimeline.push({
65
84
  time,
66
- data: {
67
- type,
68
- elementName,
69
- rect,
70
- previousRect,
71
- visible,
72
- attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
73
- oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
74
- newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
75
- }
85
+ data
76
86
  });
77
87
  },
78
88
  // Pass SSR context to ViewportObserver
@@ -245,4 +255,51 @@ export default class VCObserverNew {
245
255
  getElementName(element) {
246
256
  return getElementName(this.selectorConfig, element);
247
257
  }
258
+ }
259
+ function labelStackFromFiber(fiber) {
260
+ var _fiber$child, _fiber$child$memoized;
261
+ const value = fiber === null || fiber === void 0 ? void 0 : (_fiber$child = fiber.child) === null || _fiber$child === void 0 ? void 0 : (_fiber$child$memoized = _fiber$child.memoizedProps) === null || _fiber$child$memoized === void 0 ? void 0 : _fiber$child$memoized.value;
262
+ return Array.isArray(value === null || value === void 0 ? void 0 : value.labelStack) ? value.labelStack : [];
263
+ }
264
+ function labelStackToString(labelStack) {
265
+ return labelStack.map(label => label.name).join('/');
266
+ }
267
+ function labelStackToSegment(labelStack) {
268
+ let segmentIndex = -1;
269
+ for (let i = labelStack.length - 1; i >= 0; i--) {
270
+ if (labelStack[i].segmentId) {
271
+ segmentIndex = i;
272
+ break;
273
+ }
274
+ }
275
+ return labelStack.slice(0, segmentIndex + 1).map(label => label.name).join('/');
276
+ }
277
+ function traverseFiber(fiber) {
278
+ let segment = 'unknown';
279
+ let labelStackString = 'unknown';
280
+ let currentFiber = fiber;
281
+ while (currentFiber) {
282
+ if (currentFiber.type) {
283
+ const componentName = currentFiber.type.displayName || currentFiber.type.name;
284
+ if (componentName === 'UFOSegment' || componentName === 'UFOLabel') {
285
+ const labelStack = labelStackFromFiber(currentFiber);
286
+ labelStackString = labelStackToString(labelStack) || 'unknown';
287
+ segment = labelStackToSegment(labelStack) || 'unknown';
288
+ break;
289
+ }
290
+ }
291
+ currentFiber = currentFiber.return;
292
+ }
293
+ return {
294
+ segment,
295
+ labelStack: labelStackString
296
+ };
297
+ }
298
+ function getLabelStacks(element) {
299
+ const reactFiberKey = Object.keys(element).find(key => key.startsWith('__reactFiber$'));
300
+ if (!reactFiberKey) {
301
+ return null;
302
+ }
303
+ const fiber = element[reactFiberKey];
304
+ return fiber ? traverseFiber(fiber) : null;
248
305
  }
@@ -1,4 +1,7 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags';
2
+ import getPageVisibilityUpToTTAI from '../../../create-payload/utils/get-page-visibility-up-to-ttai';
3
+ import { getInteractionId } from '../../../interaction-id-context';
4
+ import { interactions } from '../../../interaction-metrics/common/constants';
2
5
  import { cssIssueOccurrence } from '../viewport-observer/utils/track-display-content-occurrence';
3
6
  import { calculateTTVCPercentilesWithDebugInfo } from './percentile-calc';
4
7
  import getViewportHeight from './utils/get-viewport-height';
@@ -40,12 +43,21 @@ export default class AbstractVCCalculatorBase {
40
43
  }
41
44
  return ratios;
42
45
  }
46
+ getLabelStacks(filteredEntries) {
47
+ const labelStacks = {};
48
+ for (const entry of filteredEntries) {
49
+ if ('elementName' in entry.data && entry.data.labelStacks) {
50
+ labelStacks[entry.data.elementName] = {
51
+ segment: entry.data.labelStacks.segment,
52
+ labelStack: entry.data.labelStacks.labelStack
53
+ };
54
+ }
55
+ }
56
+ return labelStacks;
57
+ }
43
58
  async calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, allEntries, include3p) {
44
59
  var _window, _window2, _window3, _window5;
45
- const percentiles = [25, 50, 75, 80, 85, 90, 95, 98, 99];
46
- if (fg('platform_ufo_send_vc_100')) {
47
- percentiles.push(100);
48
- }
60
+ const percentiles = [25, 50, 75, 80, 85, 90, 95, 98, 99, 100];
49
61
  const viewportEntries = this.filterViewportEntries(filteredEntries);
50
62
  const vcLogs = await calculateTTVCPercentilesWithDebugInfo({
51
63
  viewport: {
@@ -199,13 +211,29 @@ export default class AbstractVCCalculatorBase {
199
211
  // Only create debug details if callbacks exist
200
212
  let v3RevisionDebugDetails = null;
201
213
  if (shouldCalculateDebugDetails) {
202
- v3RevisionDebugDetails = {
203
- revision: this.revisionNo,
204
- isClean: isVCClean,
205
- abortReason: dirtyReason,
206
- vcLogs: enhancedVcLogs,
207
- interactionId
208
- };
214
+ if (fg('platform_ufo_unify_abort_status_in_ttvc_debug_data')) {
215
+ var _activeInteractionId$;
216
+ // NOTE: using this instead of directly calling `getActiveInteraction()` to get around circular dependencies
217
+ const activeInteractionId = getInteractionId();
218
+ const activeInteraction = interactions.get((_activeInteractionId$ = activeInteractionId.current) !== null && _activeInteractionId$ !== void 0 ? _activeInteractionId$ : '');
219
+ const pageVisibilityUpToTTAI = activeInteraction ? getPageVisibilityUpToTTAI(activeInteraction) : null;
220
+ const isBackgrounded = pageVisibilityUpToTTAI !== 'visible';
221
+ v3RevisionDebugDetails = {
222
+ revision: this.revisionNo,
223
+ isClean: isVCClean && !(activeInteraction !== null && activeInteraction !== void 0 && activeInteraction.abortReason) && !isBackgrounded,
224
+ abortReason: isBackgrounded ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : activeInteraction === null || activeInteraction === void 0 ? void 0 : activeInteraction.abortReason,
225
+ vcLogs: enhancedVcLogs,
226
+ interactionId
227
+ };
228
+ } else {
229
+ v3RevisionDebugDetails = {
230
+ revision: this.revisionNo,
231
+ isClean: isVCClean,
232
+ abortReason: dirtyReason,
233
+ vcLogs: enhancedVcLogs,
234
+ interactionId
235
+ };
236
+ }
209
237
  }
210
238
 
211
239
  // Handle devtool callback
@@ -275,6 +303,9 @@ export default class AbstractVCCalculatorBase {
275
303
  vcDetails: vcDetails !== null && vcDetails !== void 0 ? vcDetails : undefined
276
304
  };
277
305
  result.ratios = this.calculateRatios(filteredEntries);
306
+ if (isPostInteraction) {
307
+ result.labelStacks = this.getLabelStacks(filteredEntries);
308
+ }
278
309
  if (fg('platform_ufo_display_content_track_occurrence')) {
279
310
  result.displayContentsOccurrence = cssIssueOccurrence;
280
311
  }
@@ -1,7 +1,11 @@
1
1
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
2
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
3
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
- function getLateMutations(vcDetails, lastInteractionFinish, postInteractionFinishVCRatios) {
4
+ import { fg } from '@atlaskit/platform-feature-flags';
5
+ function getLateMutations(vcDetails) {
6
+ var labelStacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7
+ var lastInteractionFinish = arguments.length > 2 ? arguments[2] : undefined;
8
+ var postInteractionFinishVCRatios = arguments.length > 3 ? arguments[3] : undefined;
5
9
  // Map to track which elements are already seen for each timestamp
6
10
  var seen = new Map();
7
11
  var result = [];
@@ -23,11 +27,19 @@ function getLateMutations(vcDetails, lastInteractionFinish, postInteractionFinis
23
27
  continue;
24
28
  }
25
29
  seenElements.add(element);
26
- result.push({
30
+ var lateMutation = {
27
31
  time: details.t,
28
32
  element: element,
29
33
  viewportHeatmapPercentage: (postInteractionFinishVCRatios === null || postInteractionFinishVCRatios === void 0 ? void 0 : postInteractionFinishVCRatios[element]) || 0
30
- });
34
+ };
35
+ if (labelStacks && fg('platform_ufo_enable_late_mutation_label_stacks')) {
36
+ var labels = labelStacks[element];
37
+ if (labels) {
38
+ lateMutation.segment = labels.segment;
39
+ lateMutation.labelStack = labels.labelStack;
40
+ }
41
+ }
42
+ result.push(lateMutation);
31
43
  }
32
44
  } catch (err) {
33
45
  _iterator.e(err);
@@ -183,8 +183,9 @@ function createPostInteractionLogPayload(_ref2) {
183
183
  revisedVC90 = (_postInteractionFinis = postInteractionFinishRevision['metric:vc90']) !== null && _postInteractionFinis !== void 0 ? _postInteractionFinis : null;
184
184
  }
185
185
  var vcDetails = postInteractionFinishRevision.vcDetails;
186
+ var labelStacks = postInteractionFinishRevision.labelStacks;
186
187
  if (vcDetails) {
187
- lateMutations = getLateMutations(vcDetails, lastInteractionFinish, postInteractionFinishVCRatios);
188
+ lateMutations = getLateMutations(vcDetails, labelStacks, lastInteractionFinish, postInteractionFinishVCRatios);
188
189
  }
189
190
  }
190
191
  return {
@@ -57,6 +57,11 @@ export function setupHiddenTimingCapture() {
57
57
  }
58
58
  }
59
59
  export function getPageVisibilityState(start, end) {
60
+ // Input validation - return default for invalid inputs
61
+ if (!Number.isFinite(start) || !Number.isFinite(end)) {
62
+ return 'visible';
63
+ }
64
+
60
65
  // Desirable default value is visible
61
66
  if (timings.length === 0) {
62
67
  return 'visible';
@@ -69,19 +74,18 @@ export function getPageVisibilityState(start, end) {
69
74
  // currentSize is capped at SIZE.
70
75
  for (var i = 0; i < currentSize; i++) {
71
76
  var tmpIdx = (insertIndex + i) % currentSize;
72
- if (timings[tmpIdx].time <= end) {
77
+ // Add bounds checking before accessing array element
78
+ if (timings[tmpIdx] && timings[tmpIdx].time <= end) {
73
79
  endIdx = tmpIdx;
74
80
  if (timings[tmpIdx].time <= start) {
75
81
  startIdx = tmpIdx;
76
82
  }
77
83
  }
78
84
  }
79
- if (endIdx - startIdx === 0) {
80
- if (timings[startIdx].hidden) {
81
- hiddenState = 'hidden';
82
- } else {
83
- hiddenState = 'visible';
84
- }
85
+
86
+ // Add bounds checking before accessing timings array
87
+ if (endIdx - startIdx === 0 && timings[startIdx]) {
88
+ hiddenState = timings[startIdx].hidden ? 'hidden' : 'visible';
85
89
  }
86
90
  return hiddenState;
87
91
  }
@@ -5,6 +5,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
5
5
  import _createClass from "@babel/runtime/helpers/createClass";
6
6
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
7
7
  import _regeneratorRuntime from "@babel/runtime/regenerator";
8
+ import { fg } from '@atlaskit/platform-feature-flags';
8
9
  import { SSRPlaceholderHandlers } from '../vc-observer/observers/ssr-placeholders';
9
10
  import EntriesTimeline from './entries-timeline';
10
11
  import _getElementName from './get-element-name';
@@ -68,18 +69,27 @@ var VCObserverNew = /*#__PURE__*/function () {
68
69
  if (element) {
69
70
  elementName = _this.getElementName(element);
70
71
  }
72
+ var data = {
73
+ type: type,
74
+ elementName: elementName,
75
+ rect: rect,
76
+ previousRect: previousRect,
77
+ visible: visible,
78
+ attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
79
+ oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
80
+ newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
81
+ };
82
+ if (element && _this.isPostInteraction && fg('platform_ufo_enable_late_mutation_label_stacks')) {
83
+ var labelStacks = getLabelStacks(element);
84
+ if (labelStacks) {
85
+ Object.assign(data, {
86
+ labelStacks: labelStacks
87
+ });
88
+ }
89
+ }
71
90
  _this.entriesTimeline.push({
72
91
  time: time,
73
- data: {
74
- type: type,
75
- elementName: elementName,
76
- rect: rect,
77
- previousRect: previousRect,
78
- visible: visible,
79
- attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
80
- oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
81
- newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
82
- }
92
+ data: data
83
93
  });
84
94
  },
85
95
  // Pass SSR context to ViewportObserver
@@ -302,4 +312,57 @@ var VCObserverNew = /*#__PURE__*/function () {
302
312
  }
303
313
  }]);
304
314
  }();
305
- export { VCObserverNew as default };
315
+ export { VCObserverNew as default };
316
+ function labelStackFromFiber(fiber) {
317
+ var _fiber$child;
318
+ var value = fiber === null || fiber === void 0 || (_fiber$child = fiber.child) === null || _fiber$child === void 0 || (_fiber$child = _fiber$child.memoizedProps) === null || _fiber$child === void 0 ? void 0 : _fiber$child.value;
319
+ return Array.isArray(value === null || value === void 0 ? void 0 : value.labelStack) ? value.labelStack : [];
320
+ }
321
+ function labelStackToString(labelStack) {
322
+ return labelStack.map(function (label) {
323
+ return label.name;
324
+ }).join('/');
325
+ }
326
+ function labelStackToSegment(labelStack) {
327
+ var segmentIndex = -1;
328
+ for (var i = labelStack.length - 1; i >= 0; i--) {
329
+ if (labelStack[i].segmentId) {
330
+ segmentIndex = i;
331
+ break;
332
+ }
333
+ }
334
+ return labelStack.slice(0, segmentIndex + 1).map(function (label) {
335
+ return label.name;
336
+ }).join('/');
337
+ }
338
+ function traverseFiber(fiber) {
339
+ var segment = 'unknown';
340
+ var labelStackString = 'unknown';
341
+ var currentFiber = fiber;
342
+ while (currentFiber) {
343
+ if (currentFiber.type) {
344
+ var componentName = currentFiber.type.displayName || currentFiber.type.name;
345
+ if (componentName === 'UFOSegment' || componentName === 'UFOLabel') {
346
+ var labelStack = labelStackFromFiber(currentFiber);
347
+ labelStackString = labelStackToString(labelStack) || 'unknown';
348
+ segment = labelStackToSegment(labelStack) || 'unknown';
349
+ break;
350
+ }
351
+ }
352
+ currentFiber = currentFiber.return;
353
+ }
354
+ return {
355
+ segment: segment,
356
+ labelStack: labelStackString
357
+ };
358
+ }
359
+ function getLabelStacks(element) {
360
+ var reactFiberKey = Object.keys(element).find(function (key) {
361
+ return key.startsWith('__reactFiber$');
362
+ });
363
+ if (!reactFiberKey) {
364
+ return null;
365
+ }
366
+ var fiber = element[reactFiberKey];
367
+ return fiber ? traverseFiber(fiber) : null;
368
+ }
@@ -11,6 +11,9 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
11
11
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
12
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
13
  import { fg } from '@atlaskit/platform-feature-flags';
14
+ import getPageVisibilityUpToTTAI from '../../../create-payload/utils/get-page-visibility-up-to-ttai';
15
+ import { getInteractionId } from '../../../interaction-id-context';
16
+ import { interactions } from '../../../interaction-metrics/common/constants';
14
17
  import { cssIssueOccurrence } from '../viewport-observer/utils/track-display-content-occurrence';
15
18
  import { calculateTTVCPercentilesWithDebugInfo } from './percentile-calc';
16
19
  import getViewportHeight from './utils/get-viewport-height';
@@ -76,21 +79,41 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
76
79
  }
77
80
  return ratios;
78
81
  }
82
+ }, {
83
+ key: "getLabelStacks",
84
+ value: function getLabelStacks(filteredEntries) {
85
+ var labelStacks = {};
86
+ var _iterator3 = _createForOfIteratorHelper(filteredEntries),
87
+ _step3;
88
+ try {
89
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
90
+ var _entry2 = _step3.value;
91
+ if ('elementName' in _entry2.data && _entry2.data.labelStacks) {
92
+ labelStacks[_entry2.data.elementName] = {
93
+ segment: _entry2.data.labelStacks.segment,
94
+ labelStack: _entry2.data.labelStacks.labelStack
95
+ };
96
+ }
97
+ }
98
+ } catch (err) {
99
+ _iterator3.e(err);
100
+ } finally {
101
+ _iterator3.f();
102
+ }
103
+ return labelStacks;
104
+ }
79
105
  }, {
80
106
  key: "calculateWithDebugInfo",
81
107
  value: function () {
82
108
  var _calculateWithDebugInfo = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionId, dirtyReason, allEntries, include3p) {
83
109
  var _window, _window2, _window3, _window5;
84
- var percentiles, viewportEntries, vcLogs, vcDetails, percentileIndex, entryDataBuffer, _iterator3, _step3, _entry2, time, viewportPercentage, entries, elementNames, previousResult, i, percentile, enhancedVcLogs, shouldCalculate3p, shouldCalculateDebugDetails, sortedVcLogs, maxViewportPercentageAtTime, maxSoFar, _iterator4, _step4, log, getBiggestPreviousViewportPercentage, ignoredEntriesByTime, _iterator5, _step5, _entry3, _ignoredEntriesByTime, _viewportData$rect, _viewportData$previou, viewportData, timestamp, additionalVcLogs, _iterator6, _step6, _step6$value, _timestamp, ignoredEntries, _viewportPercentage, v3RevisionDebugDetails, _window4, _window4$__ufo_devtoo, _window6, _window6$__on_ufo_vc_;
110
+ var percentiles, viewportEntries, vcLogs, vcDetails, percentileIndex, entryDataBuffer, _iterator4, _step4, _entry3, time, viewportPercentage, entries, elementNames, previousResult, i, percentile, enhancedVcLogs, shouldCalculate3p, shouldCalculateDebugDetails, sortedVcLogs, maxViewportPercentageAtTime, maxSoFar, _iterator5, _step5, log, getBiggestPreviousViewportPercentage, ignoredEntriesByTime, _iterator6, _step6, _entry4, _ignoredEntriesByTime, _viewportData$rect, _viewportData$previou, viewportData, timestamp, additionalVcLogs, _iterator7, _step7, _step7$value, _timestamp, ignoredEntries, _viewportPercentage, v3RevisionDebugDetails, _activeInteractionId$, activeInteractionId, activeInteraction, pageVisibilityUpToTTAI, isBackgrounded, _window4, _window4$__ufo_devtoo, _window6, _window6$__on_ufo_vc_;
85
111
  return _regeneratorRuntime.wrap(function _callee$(_context) {
86
112
  while (1) switch (_context.prev = _context.next) {
87
113
  case 0:
88
- percentiles = [25, 50, 75, 80, 85, 90, 95, 98, 99];
89
- if (fg('platform_ufo_send_vc_100')) {
90
- percentiles.push(100);
91
- }
114
+ percentiles = [25, 50, 75, 80, 85, 90, 95, 98, 99, 100];
92
115
  viewportEntries = this.filterViewportEntries(filteredEntries);
93
- _context.next = 5;
116
+ _context.next = 4;
94
117
  return calculateTTVCPercentilesWithDebugInfo({
95
118
  viewport: {
96
119
  width: getViewportWidth(),
@@ -100,31 +123,31 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
100
123
  stopTime: stopTime,
101
124
  orderedEntries: viewportEntries
102
125
  });
103
- case 5:
126
+ case 4:
104
127
  vcLogs = _context.sent;
105
128
  vcDetails = {};
106
129
  percentileIndex = 0;
107
130
  entryDataBuffer = new Set();
108
131
  if (!vcLogs) {
109
- _context.next = 29;
132
+ _context.next = 28;
110
133
  break;
111
134
  }
112
- _iterator3 = _createForOfIteratorHelper(vcLogs);
113
- _context.prev = 11;
114
- _iterator3.s();
115
- case 13:
116
- if ((_step3 = _iterator3.n()).done) {
117
- _context.next = 21;
135
+ _iterator4 = _createForOfIteratorHelper(vcLogs);
136
+ _context.prev = 10;
137
+ _iterator4.s();
138
+ case 12:
139
+ if ((_step4 = _iterator4.n()).done) {
140
+ _context.next = 20;
118
141
  break;
119
142
  }
120
- _entry2 = _step3.value;
121
- time = _entry2.time, viewportPercentage = _entry2.viewportPercentage, entries = _entry2.entries; // Only process entries if we haven't reached all percentiles
143
+ _entry3 = _step4.value;
144
+ time = _entry3.time, viewportPercentage = _entry3.viewportPercentage, entries = _entry3.entries; // Only process entries if we haven't reached all percentiles
122
145
  if (!(percentileIndex >= percentiles.length)) {
123
- _context.next = 18;
146
+ _context.next = 17;
124
147
  break;
125
148
  }
126
- return _context.abrupt("break", 21);
127
- case 18:
149
+ return _context.abrupt("break", 20);
150
+ case 17:
128
151
  // Check if this entry matches any checkpoint percentiles
129
152
  if (viewportPercentage >= percentiles[percentileIndex]) {
130
153
  elementNames = entries.map(function (e) {
@@ -146,21 +169,21 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
146
169
  return entryDataBuffer.add(e);
147
170
  });
148
171
  }
149
- case 19:
150
- _context.next = 13;
172
+ case 18:
173
+ _context.next = 12;
151
174
  break;
152
- case 21:
153
- _context.next = 26;
175
+ case 20:
176
+ _context.next = 25;
154
177
  break;
155
- case 23:
156
- _context.prev = 23;
157
- _context.t0 = _context["catch"](11);
158
- _iterator3.e(_context.t0);
159
- case 26:
160
- _context.prev = 26;
161
- _iterator3.f();
162
- return _context.finish(26);
163
- case 29:
178
+ case 22:
179
+ _context.prev = 22;
180
+ _context.t0 = _context["catch"](10);
181
+ _iterator4.e(_context.t0);
182
+ case 25:
183
+ _context.prev = 25;
184
+ _iterator4.f();
185
+ return _context.finish(25);
186
+ case 28:
164
187
  // Fill in any missing percentiles with the last known values
165
188
  previousResult = {
166
189
  t: 0,
@@ -196,10 +219,10 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
196
219
  }); // Pre-calculate max viewport percentage up to each time for efficient lookups
197
220
  maxViewportPercentageAtTime = new Map();
198
221
  maxSoFar = 0;
199
- _iterator4 = _createForOfIteratorHelper(sortedVcLogs);
222
+ _iterator5 = _createForOfIteratorHelper(sortedVcLogs);
200
223
  try {
201
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
202
- log = _step4.value;
224
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
225
+ log = _step5.value;
203
226
  if (log.viewportPercentage !== null) {
204
227
  maxSoFar = Math.max(maxSoFar, log.viewportPercentage);
205
228
  maxViewportPercentageAtTime.set(log.time, maxSoFar);
@@ -208,9 +231,9 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
208
231
 
209
232
  // Helper function to find the biggest previous viewport percentage
210
233
  } catch (err) {
211
- _iterator4.e(err);
234
+ _iterator5.e(err);
212
235
  } finally {
213
- _iterator4.f();
236
+ _iterator5.f();
214
237
  }
215
238
  getBiggestPreviousViewportPercentage = function getBiggestPreviousViewportPercentage(targetTime) {
216
239
  // Binary search for the largest time <= targetTime
@@ -229,13 +252,13 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
229
252
  return result >= 0 ? maxViewportPercentageAtTime.get(sortedVcLogs[result].time) || null : null;
230
253
  }; // Group ignored entries by timestamp
231
254
  ignoredEntriesByTime = new Map();
232
- _iterator5 = _createForOfIteratorHelper(allEntries);
255
+ _iterator6 = _createForOfIteratorHelper(allEntries);
233
256
  try {
234
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
235
- _entry3 = _step5.value;
236
- if ('rect' in _entry3.data && !this.isEntryIncluded(_entry3, include3p)) {
237
- viewportData = _entry3.data;
238
- timestamp = Math.round(_entry3.time);
257
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
258
+ _entry4 = _step6.value;
259
+ if ('rect' in _entry4.data && !this.isEntryIncluded(_entry4, include3p)) {
260
+ viewportData = _entry4.data;
261
+ timestamp = Math.round(_entry4.time);
239
262
  if (!ignoredEntriesByTime.has(timestamp)) {
240
263
  ignoredEntriesByTime.set(timestamp, []);
241
264
  }
@@ -250,15 +273,15 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
250
273
 
251
274
  // Add ignored entries to vcLogs
252
275
  } catch (err) {
253
- _iterator5.e(err);
276
+ _iterator6.e(err);
254
277
  } finally {
255
- _iterator5.f();
278
+ _iterator6.f();
256
279
  }
257
280
  additionalVcLogs = [];
258
- _iterator6 = _createForOfIteratorHelper(ignoredEntriesByTime);
281
+ _iterator7 = _createForOfIteratorHelper(ignoredEntriesByTime);
259
282
  try {
260
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
261
- _step6$value = _slicedToArray(_step6.value, 2), _timestamp = _step6$value[0], ignoredEntries = _step6$value[1];
283
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
284
+ _step7$value = _slicedToArray(_step7.value, 2), _timestamp = _step7$value[0], ignoredEntries = _step7$value[1];
262
285
  if (ignoredEntries.length > 0) {
263
286
  _viewportPercentage = getBiggestPreviousViewportPercentage(_timestamp);
264
287
  additionalVcLogs.push({
@@ -271,9 +294,9 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
271
294
 
272
295
  // Combine and sort all vcLogs
273
296
  } catch (err) {
274
- _iterator6.e(err);
297
+ _iterator7.e(err);
275
298
  } finally {
276
- _iterator6.f();
299
+ _iterator7.f();
277
300
  }
278
301
  enhancedVcLogs = [].concat(_toConsumableArray(enhancedVcLogs), additionalVcLogs).sort(function (a, b) {
279
302
  return a.time - b.time;
@@ -283,13 +306,28 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
283
306
  // Only create debug details if callbacks exist
284
307
  v3RevisionDebugDetails = null;
285
308
  if (shouldCalculateDebugDetails) {
286
- v3RevisionDebugDetails = {
287
- revision: this.revisionNo,
288
- isClean: isVCClean,
289
- abortReason: dirtyReason,
290
- vcLogs: enhancedVcLogs,
291
- interactionId: interactionId
292
- };
309
+ if (fg('platform_ufo_unify_abort_status_in_ttvc_debug_data')) {
310
+ // NOTE: using this instead of directly calling `getActiveInteraction()` to get around circular dependencies
311
+ activeInteractionId = getInteractionId();
312
+ activeInteraction = interactions.get((_activeInteractionId$ = activeInteractionId.current) !== null && _activeInteractionId$ !== void 0 ? _activeInteractionId$ : '');
313
+ pageVisibilityUpToTTAI = activeInteraction ? getPageVisibilityUpToTTAI(activeInteraction) : null;
314
+ isBackgrounded = pageVisibilityUpToTTAI !== 'visible';
315
+ v3RevisionDebugDetails = {
316
+ revision: this.revisionNo,
317
+ isClean: isVCClean && !(activeInteraction !== null && activeInteraction !== void 0 && activeInteraction.abortReason) && !isBackgrounded,
318
+ abortReason: isBackgrounded ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : activeInteraction === null || activeInteraction === void 0 ? void 0 : activeInteraction.abortReason,
319
+ vcLogs: enhancedVcLogs,
320
+ interactionId: interactionId
321
+ };
322
+ } else {
323
+ v3RevisionDebugDetails = {
324
+ revision: this.revisionNo,
325
+ isClean: isVCClean,
326
+ abortReason: dirtyReason,
327
+ vcLogs: enhancedVcLogs,
328
+ interactionId: interactionId
329
+ };
330
+ }
293
331
  }
294
332
 
295
333
  // Handle devtool callback
@@ -320,11 +358,11 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
320
358
  }
321
359
  }
322
360
  return _context.abrupt("return", vcDetails);
323
- case 41:
361
+ case 40:
324
362
  case "end":
325
363
  return _context.stop();
326
364
  }
327
- }, _callee, this, [[11, 23, 26, 29]]);
365
+ }, _callee, this, [[10, 22, 25, 28]]);
328
366
  }));
329
367
  function calculateWithDebugInfo(_x, _x2, _x3, _x4, _x5, _x6, _x7, _x8, _x9) {
330
368
  return _calculateWithDebugInfo.apply(this, arguments);
@@ -373,11 +411,14 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
373
411
  vcDetails: vcDetails !== null && vcDetails !== void 0 ? vcDetails : undefined
374
412
  };
375
413
  result.ratios = this.calculateRatios(filteredEntries);
414
+ if (isPostInteraction) {
415
+ result.labelStacks = this.getLabelStacks(filteredEntries);
416
+ }
376
417
  if (fg('platform_ufo_display_content_track_occurrence')) {
377
418
  result.displayContentsOccurrence = cssIssueOccurrence;
378
419
  }
379
420
  return _context2.abrupt("return", result);
380
- case 14:
421
+ case 15:
381
422
  case "end":
382
423
  return _context2.stop();
383
424
  }
@@ -201,6 +201,8 @@ export type LateMutation = {
201
201
  time: number;
202
202
  element: string;
203
203
  viewportHeatmapPercentage: number;
204
+ segment?: string;
205
+ labelStack?: string;
204
206
  };
205
207
  export type PostInteractionLogPayload = {
206
208
  actionSubject: 'experience';