@atlaskit/react-ufo 2.4.6 → 2.4.7

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 (66) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/create-experimental-interaction-metrics-payload/package.json +15 -0
  3. package/dist/cjs/config/index.js +40 -18
  4. package/dist/cjs/create-experimental-interaction-metrics-payload/index.js +89 -0
  5. package/dist/cjs/create-payload/common/utils/index.js +85 -1
  6. package/dist/cjs/create-payload/index.js +37 -77
  7. package/dist/cjs/create-post-interaction-log-payload/index.js +1 -4
  8. package/dist/cjs/interaction-metrics/common/constants.js +7 -1
  9. package/dist/cjs/interaction-metrics/common/index.js +151 -0
  10. package/dist/cjs/interaction-metrics/index.js +139 -204
  11. package/dist/cjs/interaction-metrics/post-interaction-log.js +6 -2
  12. package/dist/cjs/interaction-metrics-init/index.js +27 -9
  13. package/dist/cjs/load-hold/UFOLoadHold.js +3 -4
  14. package/dist/cjs/segment/segment.js +7 -9
  15. package/dist/cjs/trace-pageload/index.js +2 -1
  16. package/dist/es2019/config/index.js +22 -0
  17. package/dist/es2019/create-experimental-interaction-metrics-payload/index.js +67 -0
  18. package/dist/es2019/create-payload/common/utils/index.js +86 -1
  19. package/dist/es2019/create-payload/index.js +28 -74
  20. package/dist/es2019/create-post-interaction-log-payload/index.js +1 -4
  21. package/dist/es2019/interaction-metrics/common/constants.js +6 -0
  22. package/dist/es2019/interaction-metrics/common/index.js +103 -0
  23. package/dist/es2019/interaction-metrics/index.js +92 -129
  24. package/dist/es2019/interaction-metrics/post-interaction-log.js +6 -2
  25. package/dist/es2019/interaction-metrics-init/index.js +21 -8
  26. package/dist/es2019/load-hold/UFOLoadHold.js +3 -4
  27. package/dist/es2019/segment/segment.js +6 -12
  28. package/dist/es2019/trace-pageload/index.js +1 -1
  29. package/dist/esm/config/index.js +39 -18
  30. package/dist/esm/create-experimental-interaction-metrics-payload/index.js +81 -0
  31. package/dist/esm/create-payload/common/utils/index.js +80 -1
  32. package/dist/esm/create-payload/index.js +33 -75
  33. package/dist/esm/create-post-interaction-log-payload/index.js +1 -4
  34. package/dist/esm/interaction-metrics/common/constants.js +6 -0
  35. package/dist/esm/interaction-metrics/common/index.js +132 -0
  36. package/dist/esm/interaction-metrics/index.js +87 -156
  37. package/dist/esm/interaction-metrics/post-interaction-log.js +6 -2
  38. package/dist/esm/interaction-metrics-init/index.js +24 -10
  39. package/dist/esm/load-hold/UFOLoadHold.js +3 -4
  40. package/dist/esm/segment/segment.js +7 -9
  41. package/dist/esm/trace-pageload/index.js +1 -1
  42. package/dist/types/common/common/types.d.ts +9 -5
  43. package/dist/types/config/index.d.ts +6 -0
  44. package/dist/types/create-experimental-interaction-metrics-payload/index.d.ts +31 -0
  45. package/dist/types/create-payload/common/utils/index.d.ts +12 -0
  46. package/dist/types/create-payload/index.d.ts +13 -5660
  47. package/dist/types/create-post-interaction-log-payload/index.d.ts +2 -0
  48. package/dist/types/interaction-metrics/common/constants.d.ts +31 -1
  49. package/dist/types/interaction-metrics/common/index.d.ts +16 -0
  50. package/dist/types/interaction-metrics/index.d.ts +4 -15
  51. package/dist/types/interaction-metrics/post-interaction-log.d.ts +1 -1
  52. package/dist/types/load-hold/UFOLoadHold.d.ts +1 -2
  53. package/dist/types/trace-pageload/index.d.ts +1 -0
  54. package/dist/types-ts4.5/common/common/types.d.ts +9 -5
  55. package/dist/types-ts4.5/config/index.d.ts +6 -0
  56. package/dist/types-ts4.5/create-experimental-interaction-metrics-payload/index.d.ts +31 -0
  57. package/dist/types-ts4.5/create-payload/common/utils/index.d.ts +12 -0
  58. package/dist/types-ts4.5/create-payload/index.d.ts +13 -5660
  59. package/dist/types-ts4.5/create-post-interaction-log-payload/index.d.ts +2 -0
  60. package/dist/types-ts4.5/interaction-metrics/common/constants.d.ts +31 -1
  61. package/dist/types-ts4.5/interaction-metrics/common/index.d.ts +16 -0
  62. package/dist/types-ts4.5/interaction-metrics/index.d.ts +4 -15
  63. package/dist/types-ts4.5/interaction-metrics/post-interaction-log.d.ts +1 -1
  64. package/dist/types-ts4.5/load-hold/UFOLoadHold.d.ts +1 -2
  65. package/dist/types-ts4.5/trace-pageload/index.d.ts +1 -0
  66. package/package.json +2 -1
@@ -0,0 +1,103 @@
1
+ import { getConfig } from '../../config';
2
+ import { interactionQueue, segmentCache, segmentObservers } from './constants';
3
+ export function isPerformanceTracingEnabled() {
4
+ var _getConfig;
5
+ return ((_getConfig = getConfig()) === null || _getConfig === void 0 ? void 0 : _getConfig.enableAdditionalPerformanceMarks) || window.__REACT_UFO_ENABLE_PERF_TRACING || process.env.NODE_ENV !== 'production';
6
+ }
7
+ export function labelStackToString(labelStack, name) {
8
+ var _stack$map;
9
+ const stack = [...(labelStack !== null && labelStack !== void 0 ? labelStack : [])];
10
+ if (name) {
11
+ stack.push({
12
+ name
13
+ });
14
+ }
15
+ return (_stack$map = stack.map(l => l.name)) === null || _stack$map === void 0 ? void 0 : _stack$map.join('/');
16
+ }
17
+ export function labelStackToIdString(labelStack) {
18
+ var _labelStack$map;
19
+ return labelStack === null || labelStack === void 0 ? void 0 : (_labelStack$map = labelStack.map(l => 'segmentId' in l ? `${l.name}:${l.segmentId}` : `${l.name}`)) === null || _labelStack$map === void 0 ? void 0 : _labelStack$map.join('/');
20
+ }
21
+ export function addSegmentObserver(observer) {
22
+ segmentObservers.push(observer);
23
+ for (const segmentInfo of segmentCache.values()) {
24
+ observer.onAdd(segmentInfo);
25
+ }
26
+ }
27
+ export function removeSegmentObserver(observer) {
28
+ const index = segmentObservers.findIndex(obs => obs === observer);
29
+ if (index !== -1) {
30
+ segmentObservers.splice(index, 1);
31
+ }
32
+ }
33
+ export function addHoldCriterion(id, labelStack, name, startTime) {
34
+ var _window$__CRITERION__;
35
+ if (!((_window$__CRITERION__ = window.__CRITERION__) !== null && _window$__CRITERION__ !== void 0 && _window$__CRITERION__.addUFOHold)) {
36
+ return;
37
+ }
38
+ window.__CRITERION__.addUFOHold(id, labelStackToString(labelStack), name, startTime);
39
+ }
40
+ export function removeHoldCriterion(id) {
41
+ var _window$__CRITERION__2;
42
+ if (!((_window$__CRITERION__2 = window.__CRITERION__) !== null && _window$__CRITERION__2 !== void 0 && _window$__CRITERION__2.removeUFOHold)) {
43
+ return;
44
+ }
45
+ window.__CRITERION__.removeUFOHold(id);
46
+ }
47
+ export const pushToQueue = (id, data) => {
48
+ interactionQueue.push({
49
+ id,
50
+ data
51
+ });
52
+ };
53
+ export function callCleanUpCallbacks(interaction) {
54
+ interaction.cleanupCallbacks.reverse().forEach(cleanUpCallback => {
55
+ cleanUpCallback();
56
+ });
57
+ }
58
+ export function reactProfilerTimingMap(data) {
59
+ const profilerTimingMap = new Map();
60
+ data.reactProfilerTimings.forEach(profilerTiming => {
61
+ const labelStackId = labelStackToIdString(profilerTiming.labelStack);
62
+ if (labelStackId) {
63
+ var _profilerTimingMap$ge, _timing$start, _timing$end;
64
+ const timing = (_profilerTimingMap$ge = profilerTimingMap.get(labelStackId)) !== null && _profilerTimingMap$ge !== void 0 ? _profilerTimingMap$ge : {
65
+ labelStack: profilerTiming.labelStack
66
+ };
67
+ timing.start = profilerTiming.startTime < ((_timing$start = timing.start) !== null && _timing$start !== void 0 ? _timing$start : Number.MAX_SAFE_INTEGER) ? profilerTiming.startTime : timing.start;
68
+ timing.end = profilerTiming.commitTime > ((_timing$end = timing.end) !== null && _timing$end !== void 0 ? _timing$end : Number.MIN_SAFE_INTEGER) ? profilerTiming.commitTime : timing.end;
69
+ profilerTimingMap.set(labelStackId, timing);
70
+ }
71
+ });
72
+ try {
73
+ // for Firefox 102 and older
74
+ for (const [, {
75
+ labelStack,
76
+ start,
77
+ end
78
+ }] of profilerTimingMap.entries()) {
79
+ performance.measure(`🛸 ${labelStackToString(labelStack)} [segment_ttai]`, {
80
+ start,
81
+ end
82
+ });
83
+ }
84
+ } catch (e) {
85
+ // do nothing
86
+ }
87
+ }
88
+ export function callCancelCallbacks(interaction) {
89
+ interaction.cancelCallbacks.reverse().forEach(cancelCallback => {
90
+ cancelCallback();
91
+ });
92
+ }
93
+ export function isSegmentLabel(obj) {
94
+ return obj && typeof obj.name === 'string' && typeof obj.segmentId === 'string';
95
+ }
96
+ export function getSegmentCacheKey(labelStack) {
97
+ return labelStack.map(l => {
98
+ if (isSegmentLabel(l)) {
99
+ return `${l.name}_${l.segmentId}`;
100
+ }
101
+ return l.name;
102
+ }).join('|');
103
+ }
@@ -1,22 +1,21 @@
1
1
  import { v4 as createUUID } from 'uuid';
2
2
  import coinflip from '../coinflip';
3
3
  import { getAwaitBM3TTIList, getCapabilityRate, getConfig } from '../config';
4
+ import { ExperimentalInteractionMetrics } from '../create-experimental-interaction-metrics-payload';
5
+ import { getExperimentalVCMetrics, getTTAI } from '../create-payload/common/utils';
4
6
  import { clearActiveTrace } from '../experience-trace-id-context';
5
7
  import { allFeatureFlagsAccessed, currentFeatureFlagsAccessed } from '../feature-flags-accessed';
6
8
  import { getInteractionId } from '../interaction-id-context';
7
9
  import { getVCObserver } from '../vc';
8
- import interactions from './common/constants';
10
+ import { addHoldCriterion, addSegmentObserver, callCancelCallbacks, callCleanUpCallbacks, getSegmentCacheKey, isPerformanceTracingEnabled, labelStackToString, pushToQueue, reactProfilerTimingMap, removeHoldCriterion, removeSegmentObserver } from './common';
11
+ import interactions, { CLEANUP_TIMEOUT, CLEANUP_TIMEOUT_AFTER_APDEX, interactionQueue, moduleLoadingRequests, segmentCache, segmentObservers } from './common/constants';
9
12
  import PostInteractionLog from './post-interaction-log';
10
13
  const PreviousInteractionLog = {
11
14
  name: undefined,
12
15
  isAborted: undefined
13
16
  };
14
17
  export const postInteractionLog = new PostInteractionLog();
15
- const interactionQueue = [];
16
- const segmentCache = new Map();
17
- const CLEANUP_TIMEOUT = 60 * 1000;
18
- const CLEANUP_TIMEOUT_AFTER_APDEX = 15 * 1000;
19
- const segmentObservers = [];
18
+ export const experimentalInteractionLog = new ExperimentalInteractionMetrics();
20
19
  export function getActiveInteraction() {
21
20
  const interactionId = getInteractionId();
22
21
  if (!interactionId.current) {
@@ -24,36 +23,6 @@ export function getActiveInteraction() {
24
23
  }
25
24
  return interactions.get(interactionId.current);
26
25
  }
27
- function isPerformanceTracingEnabled() {
28
- var _getConfig;
29
- return ((_getConfig = getConfig()) === null || _getConfig === void 0 ? void 0 : _getConfig.enableAdditionalPerformanceMarks) || window.__REACT_UFO_ENABLE_PERF_TRACING || process.env.NODE_ENV !== 'production';
30
- }
31
- function labelStackToString(labelStack, name) {
32
- var _stack$map;
33
- const stack = [...(labelStack !== null && labelStack !== void 0 ? labelStack : [])];
34
- if (name) {
35
- stack.push({
36
- name
37
- });
38
- }
39
- return (_stack$map = stack.map(l => l.name)) === null || _stack$map === void 0 ? void 0 : _stack$map.join('/');
40
- }
41
- function labelStackToIdString(labelStack) {
42
- var _labelStack$map;
43
- return labelStack === null || labelStack === void 0 ? void 0 : (_labelStack$map = labelStack.map(l => 'segmentId' in l ? `${l.name}:${l.segmentId}` : `${l.name}`)) === null || _labelStack$map === void 0 ? void 0 : _labelStack$map.join('/');
44
- }
45
- function addSegmentObserver(observer) {
46
- segmentObservers.push(observer);
47
- for (const segmentInfo of segmentCache.values()) {
48
- observer.onAdd(segmentInfo);
49
- }
50
- }
51
- function removeSegmentObserver(observer) {
52
- const index = segmentObservers.findIndex(obs => obs === observer);
53
- if (index !== -1) {
54
- segmentObservers.splice(index, 1);
55
- }
56
- }
57
26
  export function remove(interactionId) {
58
27
  interactions.delete(interactionId);
59
28
  }
@@ -196,7 +165,6 @@ export function addPreload(moduleId, timestamp) {
196
165
  export function addLoad(identifier, start, end) {
197
166
  addSpanToAll('bundle_load', identifier, null, start, end - start);
198
167
  }
199
- const moduleLoadingRequests = {};
200
168
  export function extractModuleName(input) {
201
169
  let result = input !== null && input !== void 0 ? input : '';
202
170
  result = result.replace(/^\.\/src\/packages\//, '');
@@ -204,30 +172,29 @@ export function extractModuleName(input) {
204
172
  result = result.replace(/(\/src)?\/(index|main)\.(tsx|ts|js|jsx)$/, '');
205
173
  return result;
206
174
  }
207
- function addHoldCriterion(id, labelStack, name, startTime) {
208
- var _window$__CRITERION__;
209
- if (!((_window$__CRITERION__ = window.__CRITERION__) !== null && _window$__CRITERION__ !== void 0 && _window$__CRITERION__.addUFOHold)) {
210
- return;
211
- }
212
- window.__CRITERION__.addUFOHold(id, labelStackToString(labelStack), name, startTime);
213
- }
214
- function removeHoldCriterion(id) {
215
- var _window$__CRITERION__2;
216
- if (!((_window$__CRITERION__2 = window.__CRITERION__) !== null && _window$__CRITERION__2 !== void 0 && _window$__CRITERION__2.removeUFOHold)) {
217
- return;
218
- }
219
- window.__CRITERION__.removeUFOHold(id);
220
- }
221
- export function addHold(interactionId, labelStack, name) {
175
+ export function addHold(interactionId, labelStack, name, experimental) {
222
176
  const interaction = interactions.get(interactionId);
223
177
  const id = createUUID();
224
178
  if (interaction != null) {
225
- const start = performance.now();
226
- interaction.holdActive.set(id, {
179
+ var _getConfig, _getConfig$experiment;
180
+ const holdActive = {
227
181
  labelStack,
228
182
  name,
229
- start
230
- });
183
+ start: 0
184
+ };
185
+ const start = performance.now();
186
+ if ((_getConfig = getConfig()) !== null && _getConfig !== void 0 && (_getConfig$experiment = _getConfig.experimentalInteractionMetrics) !== null && _getConfig$experiment !== void 0 && _getConfig$experiment.enabled && experimental) {
187
+ interaction.holdExpActive.set(id, {
188
+ ...holdActive,
189
+ start
190
+ });
191
+ }
192
+ if (!experimental) {
193
+ interaction.holdActive.set(id, {
194
+ ...holdActive,
195
+ start
196
+ });
197
+ }
231
198
  addHoldCriterion(id, labelStack, name, start);
232
199
  return () => {
233
200
  const end = performance.now();
@@ -245,12 +212,22 @@ export function addHold(interactionId, labelStack, name) {
245
212
  removeHoldCriterion(id);
246
213
  const currentInteraction = interactions.get(interactionId);
247
214
  const currentHold = interaction.holdActive.get(id);
248
- if (currentInteraction != null && currentHold != null) {
249
- currentInteraction.holdInfo.push({
250
- ...currentHold,
251
- end
252
- });
253
- interaction.holdActive.delete(id);
215
+ const expHold = interaction.holdExpActive.get(id);
216
+ if (currentInteraction != null) {
217
+ if (currentHold != null) {
218
+ currentInteraction.holdInfo.push({
219
+ ...currentHold,
220
+ end
221
+ });
222
+ interaction.holdActive.delete(id);
223
+ }
224
+ if (expHold != null) {
225
+ currentInteraction.holdExpInfo.push({
226
+ ...expHold,
227
+ end
228
+ });
229
+ interaction.holdExpActive.delete(id);
230
+ }
254
231
  }
255
232
  };
256
233
  }
@@ -379,21 +356,9 @@ export const addProfilerTimings = (interactionId, labelStack, type, actualDurati
379
356
  postInteractionLog.addProfilerTimings(labelStack, type, actualDuration, baseDuration, startTime, commitTime);
380
357
  }
381
358
  };
382
- const pushToQueue = (id, data) => {
383
- interactionQueue.push({
384
- id,
385
- data
386
- });
387
- };
388
359
  let handleInteraction = pushToQueue;
389
- function callCleanUpCallbacks(interaction) {
390
- interaction.cleanupCallbacks.reverse().forEach(cleanUpCallback => {
391
- cleanUpCallback();
392
- });
393
- }
394
360
  const finishInteraction = (id, data, endTime = performance.now()) => {
395
361
  var _getConfig3, _getConfig3$vc;
396
- // eslint-disable-next-line no-param-reassign
397
362
  data.end = endTime;
398
363
  try {
399
364
  // for Firefox 102 and older
@@ -405,7 +370,6 @@ const finishInteraction = (id, data, endTime = performance.now()) => {
405
370
  // do nothing
406
371
  }
407
372
  if (data.featureFlags) {
408
- // eslint-disable-next-line no-param-reassign
409
373
  data.featureFlags.during = Object.fromEntries(currentFeatureFlagsAccessed);
410
374
  }
411
375
  clearActiveTrace();
@@ -413,41 +377,13 @@ const finishInteraction = (id, data, endTime = performance.now()) => {
413
377
  if ((_getConfig3 = getConfig()) !== null && _getConfig3 !== void 0 && (_getConfig3$vc = _getConfig3.vc) !== null && _getConfig3$vc !== void 0 && _getConfig3$vc.stopVCAtInteractionFinish) {
414
378
  data.vc = getVCObserver().getVCRawData();
415
379
  }
416
- remove(id);
417
380
  PreviousInteractionLog.name = data.ufoName || 'unknown';
418
381
  PreviousInteractionLog.isAborted = data.abortReason != null;
419
382
  if (data.ufoName) {
420
383
  handleInteraction(id, data);
421
384
  }
422
385
  if (isPerformanceTracingEnabled()) {
423
- const profilerTimingMap = new Map();
424
- data.reactProfilerTimings.forEach(profilerTiming => {
425
- const labelStackId = labelStackToIdString(profilerTiming.labelStack);
426
- if (labelStackId) {
427
- var _profilerTimingMap$ge, _timing$start, _timing$end;
428
- const timing = (_profilerTimingMap$ge = profilerTimingMap.get(labelStackId)) !== null && _profilerTimingMap$ge !== void 0 ? _profilerTimingMap$ge : {
429
- labelStack: profilerTiming.labelStack
430
- };
431
- timing.start = profilerTiming.startTime < ((_timing$start = timing.start) !== null && _timing$start !== void 0 ? _timing$start : Number.MAX_SAFE_INTEGER) ? profilerTiming.startTime : timing.start;
432
- timing.end = profilerTiming.commitTime > ((_timing$end = timing.end) !== null && _timing$end !== void 0 ? _timing$end : Number.MIN_SAFE_INTEGER) ? profilerTiming.commitTime : timing.end;
433
- profilerTimingMap.set(labelStackId, timing);
434
- }
435
- });
436
- try {
437
- // for Firefox 102 and older
438
- for (const [, {
439
- labelStack,
440
- start,
441
- end
442
- }] of profilerTimingMap.entries()) {
443
- performance.measure(`🛸 ${labelStackToString(labelStack)} [segment_ttai]`, {
444
- start,
445
- end
446
- });
447
- }
448
- } catch (e) {
449
- // do nothing
450
- }
386
+ reactProfilerTimingMap(data);
451
387
  }
452
388
  try {
453
389
  // dispatch a global window event to notify the measure is completed
@@ -467,57 +403,93 @@ export const sinkInteractionHandler = sinkFn => {
467
403
  interactionQueue.length = 0;
468
404
  }
469
405
  };
406
+ export const sinkExperimentalHandler = sinkFn => {
407
+ experimentalInteractionLog.sinkHandler(sinkFn);
408
+ };
470
409
  export const sinkPostInteractionLogHandler = sinkFn => {
471
410
  postInteractionLog.sinkHandler(sinkFn);
472
411
  };
412
+
413
+ // a flag to prevent mutliple submittions
414
+ let activeSubmitted = false;
473
415
  export function tryComplete(interactionId, endTime) {
474
416
  const interaction = interactions.get(interactionId);
475
417
  if (interaction != null) {
476
- const noMoreHolds = interaction.holdActive.size === 0;
477
- if (noMoreHolds) {
418
+ const noMoreActiveHolds = interaction.holdActive.size === 0;
419
+ const noMoreExpHolds = interaction.holdExpActive.size === 0;
420
+ const postInteraction = () => {
478
421
  var _getConfig4, _getConfig4$postInter;
479
- finishInteraction(interactionId, interaction, endTime);
480
422
  if ((_getConfig4 = getConfig()) !== null && _getConfig4 !== void 0 && (_getConfig4$postInter = _getConfig4.postInteractionLog) !== null && _getConfig4$postInter !== void 0 && _getConfig4$postInter.enabled) {
481
- postInteractionLog.onInteractionComplete(interaction);
423
+ var _getExperimentalVCMet;
424
+ const experimentalVC90 = (_getExperimentalVCMet = getExperimentalVCMetrics(interaction)) === null || _getExperimentalVCMet === void 0 ? void 0 : _getExperimentalVCMet['metric:experimental:vc90'];
425
+ const experimentalTTAI = getTTAI(interaction);
426
+ postInteractionLog.onInteractionComplete({
427
+ ...interaction,
428
+ experimentalTTAI,
429
+ experimentalVC90
430
+ });
431
+ }
432
+ remove(interactionId);
433
+ activeSubmitted = false;
434
+ };
435
+ if (noMoreActiveHolds) {
436
+ if (!activeSubmitted) {
437
+ finishInteraction(interactionId, interaction, endTime);
438
+ activeSubmitted = true;
439
+ }
440
+ if (noMoreExpHolds) {
441
+ var _getConfig5, _getConfig5$experimen;
442
+ if ((_getConfig5 = getConfig()) !== null && _getConfig5 !== void 0 && (_getConfig5$experimen = _getConfig5.experimentalInteractionMetrics) !== null && _getConfig5$experimen !== void 0 && _getConfig5$experimen.enabled) {
443
+ experimentalInteractionLog.onInteractionComplete(interactionId, interaction, endTime);
444
+ }
445
+ postInteraction();
482
446
  }
483
447
  }
484
448
  }
485
449
  }
486
- function callCancelCallbacks(interaction) {
487
- interaction.cancelCallbacks.reverse().forEach(cancelCallback => {
488
- cancelCallback();
489
- });
490
- }
491
450
  export function abort(interactionId, abortReason) {
492
451
  const interaction = interactions.get(interactionId);
493
452
  if (interaction != null) {
453
+ var _getConfig6, _getConfig6$experimen;
494
454
  callCancelCallbacks(interaction);
495
455
  interaction.abortReason = abortReason;
496
456
  finishInteraction(interactionId, interaction);
457
+ if ((_getConfig6 = getConfig()) !== null && _getConfig6 !== void 0 && (_getConfig6$experimen = _getConfig6.experimentalInteractionMetrics) !== null && _getConfig6$experimen !== void 0 && _getConfig6$experimen.enabled) {
458
+ experimentalInteractionLog.onInteractionComplete(interactionId, interaction);
459
+ }
460
+ remove(interactionId);
497
461
  }
498
462
  }
499
463
  export function abortByNewInteraction(interactionId, interactionName) {
500
464
  const interaction = interactions.get(interactionId);
501
465
  if (interaction != null) {
466
+ var _getConfig7, _getConfig7$experimen;
502
467
  callCancelCallbacks(interaction);
503
468
  interaction.abortReason = 'new_interaction';
504
469
  interaction.abortedByInteractionName = interactionName;
505
470
  finishInteraction(interactionId, interaction);
471
+ if ((_getConfig7 = getConfig()) !== null && _getConfig7 !== void 0 && (_getConfig7$experimen = _getConfig7.experimentalInteractionMetrics) !== null && _getConfig7$experimen !== void 0 && _getConfig7$experimen.enabled) {
472
+ experimentalInteractionLog.onInteractionComplete(interactionId, interaction);
473
+ }
474
+ remove(interactionId);
506
475
  }
507
476
  }
508
477
  export function abortAll(abortReason, abortedByInteractionName) {
509
478
  interactions.forEach((interaction, interactionId) => {
479
+ var _getConfig8, _getConfig8$experimen;
510
480
  const noMoreHolds = interaction.holdActive.size === 0;
511
481
  if (!noMoreHolds) {
512
482
  callCancelCallbacks(interaction);
513
- // eslint-disable-next-line no-param-reassign
514
483
  interaction.abortReason = abortReason;
515
484
  if (abortedByInteractionName != null) {
516
- // eslint-disable-next-line no-param-reassign
517
485
  interaction.abortedByInteractionName = abortedByInteractionName;
518
486
  }
519
487
  }
520
488
  finishInteraction(interactionId, interaction);
489
+ if ((_getConfig8 = getConfig()) !== null && _getConfig8 !== void 0 && (_getConfig8$experimen = _getConfig8.experimentalInteractionMetrics) !== null && _getConfig8$experimen !== void 0 && _getConfig8$experimen.enabled) {
490
+ experimentalInteractionLog.onInteractionComplete(interactionId, interaction);
491
+ }
492
+ remove(interactionId);
521
493
  });
522
494
  }
523
495
  export function addOnCancelCallback(id, cancelCallback) {
@@ -525,8 +497,8 @@ export function addOnCancelCallback(id, cancelCallback) {
525
497
  interaction === null || interaction === void 0 ? void 0 : interaction.cancelCallbacks.push(cancelCallback);
526
498
  }
527
499
  export function addNewInteraction(interactionId, ufoName, type, startTime, rate, labelStack, routeName, trace = null) {
528
- var _getConfig5, _getConfig5$postInter;
529
- if ((_getConfig5 = getConfig()) !== null && _getConfig5 !== void 0 && (_getConfig5$postInter = _getConfig5.postInteractionLog) !== null && _getConfig5$postInter !== void 0 && _getConfig5$postInter.enabled) {
500
+ var _getConfig9, _getConfig9$postInter;
501
+ if ((_getConfig9 = getConfig()) !== null && _getConfig9 !== void 0 && (_getConfig9$postInter = _getConfig9.postInteractionLog) !== null && _getConfig9$postInter !== void 0 && _getConfig9$postInter.enabled) {
530
502
  postInteractionLog.reset();
531
503
  }
532
504
  let previousTime = startTime;
@@ -566,9 +538,11 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
566
538
  requestInfo: [],
567
539
  reactProfilerTimings: [],
568
540
  holdInfo: [],
541
+ holdExpInfo: [],
569
542
  holdActive: new Map(),
543
+ holdExpActive: new Map(),
570
544
  // measure when we execute this code
571
- // from this we can measure the input delay -
545
+ // from this, we can measure the input delay -
572
546
  // how long the browser took to hand execution back to JS)
573
547
  measureStart: performance.now(),
574
548
  rate,
@@ -680,17 +654,6 @@ export function addRequestInfo(interactionId, labelStack, requestInfo) {
680
654
  });
681
655
  }
682
656
  }
683
- function isSegmentLabel(obj) {
684
- return obj && typeof obj.name === 'string' && typeof obj.segmentId === 'string';
685
- }
686
- function getSegmentCacheKey(labelStack) {
687
- return labelStack.map(l => {
688
- if (isSegmentLabel(l)) {
689
- return `${l.name}_${l.segmentId}`;
690
- }
691
- return l.name;
692
- }).join('|');
693
- }
694
657
  export function addSegment(labelStack) {
695
658
  const key = getSegmentCacheKey(labelStack);
696
659
  const existingSegment = segmentCache.get(key);
@@ -121,7 +121,9 @@ export default class PostInteractionLog {
121
121
  abortReason,
122
122
  abortedByInteractionName,
123
123
  routeName,
124
- type
124
+ type,
125
+ experimentalTTAI,
126
+ experimentalVC90
125
127
  }) {
126
128
  var _getConfig;
127
129
  this.lastInteractionFinish = {
@@ -132,7 +134,9 @@ export default class PostInteractionLog {
132
134
  abortReason,
133
135
  abortedByInteractionName,
134
136
  routeName,
135
- type
137
+ type,
138
+ experimentalTTAI,
139
+ experimentalVC90
136
140
  };
137
141
  const timeout = ((_getConfig = getConfig()) === null || _getConfig === void 0 ? void 0 : _getConfig.timeWindowForLateMutationsInMilliseconds) || POST_INTERACTION_LOG_SEND_DEFAULT_TIMEOUT;
138
142
  this.sinkTimeoutId = window.setTimeout(() => {
@@ -2,7 +2,7 @@ import { unstable_IdlePriority as idlePriority, unstable_scheduleCallback as sch
2
2
  import { startLighthouseObserver } from '../additional-payload';
3
3
  import { setUFOConfig } from '../config';
4
4
  import { setupHiddenTimingCapture } from '../hidden-timing';
5
- import { postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
5
+ import { experimentalInteractionLog, postInteractionLog, sinkExperimentalHandler, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
6
6
  import { getVCObserver } from '../vc';
7
7
  let initialized = false;
8
8
  function sinkInteraction(instance, payloadPackage) {
@@ -15,6 +15,14 @@ function sinkInteraction(instance, payloadPackage) {
15
15
  });
16
16
  });
17
17
  }
18
+ function sinkExperimentalInteractionMetrics(instance, payloadPackage) {
19
+ sinkExperimentalHandler((interactionId, interaction) => {
20
+ scheduleCallback(idlePriority, () => {
21
+ const payload = payloadPackage.createExperimentalInteractionMetricsPayload(interactionId, interaction);
22
+ instance.sendOperationalEvent(payload);
23
+ });
24
+ });
25
+ }
18
26
  function sinkPostInteractionLog(instance, createPostInteractionLogPayload) {
19
27
  sinkPostInteractionLogHandler(logOutput => {
20
28
  scheduleCallback(idlePriority, () => {
@@ -45,27 +53,32 @@ export const init = (analyticsWebClientAsync, config) => {
45
53
  postInteractionLog.startVCObserver({
46
54
  startTime: 0
47
55
  });
56
+ experimentalInteractionLog.initializeVCObserver(vcOptions).startVCObserver({
57
+ startTime: 0
58
+ });
48
59
  }
49
60
  setupHiddenTimingCapture();
50
61
  startLighthouseObserver();
51
62
  initialized = true;
52
- Promise.all([analyticsWebClientAsync,
53
- // eslint-disable-next-line import/dynamic-import-chunkname
54
- import( /* webpackChunkName: "create-payloads" */'../create-payload'),
55
- // eslint-disable-next-line import/dynamic-import-chunkname
56
- import( /* webpackChunkName: "create-post-intreaction-log-payload" */'../create-post-interaction-log-payload')]).then(([awc, payloadPackage, createPostInteractionLogPayloadPackage]) => {
63
+ Promise.all([analyticsWebClientAsync, import( /* webpackChunkName: "create-payloads" */'../create-payload'), import( /* webpackChunkName: "create-experimental-interaction-metrics-payload" */'../create-experimental-interaction-metrics-payload'), import( /* webpackChunkName: "create-post-interaction-log-payload" */'../create-post-interaction-log-payload')]).then(([awc, payloadPackage, createExperimentalInteractionMetricsPayload, createPostInteractionLogPayloadPackage]) => {
57
64
  if (awc.getAnalyticsWebClientPromise) {
58
65
  awc.getAnalyticsWebClientPromise().then(client => {
59
- var _config$postInteracti;
66
+ var _config$experimentalI, _config$postInteracti;
60
67
  const instance = client.getInstance();
61
68
  sinkInteraction(instance, payloadPackage);
69
+ if (config !== null && config !== void 0 && (_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
70
+ sinkExperimentalInteractionMetrics(instance, createExperimentalInteractionMetricsPayload);
71
+ }
62
72
  if ((_config$postInteracti = config.postInteractionLog) !== null && _config$postInteracti !== void 0 && _config$postInteracti.enabled) {
63
73
  sinkPostInteractionLog(instance, createPostInteractionLogPayloadPackage.default);
64
74
  }
65
75
  });
66
76
  } else if (awc.sendOperationalEvent) {
67
- var _config$postInteracti2;
77
+ var _config$experimentalI2, _config$postInteracti2;
68
78
  sinkInteraction(awc, payloadPackage);
79
+ if (config !== null && config !== void 0 && (_config$experimentalI2 = config.experimentalInteractionMetrics) !== null && _config$experimentalI2 !== void 0 && _config$experimentalI2.enabled) {
80
+ sinkExperimentalInteractionMetrics(awc, createExperimentalInteractionMetricsPayload);
81
+ }
69
82
  if ((_config$postInteracti2 = config.postInteractionLog) !== null && _config$postInteracti2 !== void 0 && _config$postInteracti2.enabled) {
70
83
  sinkPostInteractionLog(awc, createPostInteractionLogPayloadPackage.default);
71
84
  }
@@ -22,8 +22,7 @@ const useLayoutEffectSAFE = typeof window === 'undefined' ? useEffect : useLayou
22
22
  * return (
23
23
  * <>
24
24
  * <Skeleton />
25
- * <UFOLoadHold name="card">
26
- * </UFOLoadHold>
25
+ * <UFOLoadHold name="card" />
27
26
  * )
28
27
  * }
29
28
  * ```
@@ -57,8 +56,8 @@ export default function UFOLoadHold({
57
56
  // react-18: useId instead
58
57
  const context = useContext(UFOInteractionContext);
59
58
  useLayoutEffectSAFE(() => {
60
- if (hold && !experimental && context != null) {
61
- return context.hold(name);
59
+ if (hold && context != null) {
60
+ return context.hold(name, experimental);
62
61
  }
63
62
  }, [hold, context, name]);
64
63
 
@@ -67,15 +67,13 @@ export default function UFOSegment({
67
67
  }
68
68
  }
69
69
  }
70
- function _internalHold(labelStack, name
71
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
72
- ) {
70
+ function _internalHold(labelStack, name, experimental = false) {
73
71
  if (interactionId.current != null) {
74
72
  if (parentContext) {
75
- return parentContext._internalHold(labelStack, name);
73
+ return parentContext._internalHold(labelStack, name, experimental);
76
74
  } else {
77
75
  const capturedInteractionId = interactionId.current;
78
- const disposeHold = addHold(interactionId.current, labelStack, name);
76
+ const disposeHold = addHold(interactionId.current, labelStack, name, experimental);
79
77
  return () => {
80
78
  if (capturedInteractionId === interactionId.current) {
81
79
  disposeHold();
@@ -84,9 +82,7 @@ export default function UFOSegment({
84
82
  }
85
83
  }
86
84
  }
87
- function _internalHoldByID(labelStack, id, name, remove
88
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
89
- ) {
85
+ function _internalHoldByID(labelStack, id, name, remove) {
90
86
  if (interactionId.current != null) {
91
87
  if (parentContext) {
92
88
  parentContext._internalHoldByID(labelStack, name, id, remove);
@@ -108,10 +104,8 @@ export default function UFOSegment({
108
104
  }
109
105
  return {
110
106
  labelStack,
111
- hold(name = 'unknown'
112
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
113
- ) {
114
- return this._internalHold(this.labelStack, name);
107
+ hold(name = 'unknown', experimental) {
108
+ return this._internalHold(this.labelStack, name, experimental);
115
109
  },
116
110
  addHoldByID(labelStack, id, name = 'unknown') {
117
111
  this._internalHoldByID(labelStack, id, name, false);
@@ -5,7 +5,7 @@ import { getActiveTrace } from '../experience-trace-id-context';
5
5
  import { DefaultInteractionID } from '../interaction-id-context';
6
6
  import { abort, addHoldByID, addNewInteraction, getActiveInteraction, removeHoldByID, updatePageLoadInteractionName } from '../interaction-metrics';
7
7
  import UFORouteName from '../route-name-context';
8
- const AWAITING_PAGELOAD_NAME = 'awaiting_pageload_name';
8
+ export const AWAITING_PAGELOAD_NAME = 'awaiting_pageload_name';
9
9
  export default function traceUFOPageLoad(ufoName, routeName = ufoName) {
10
10
  const activeInteraction = getActiveInteraction();
11
11
  if (activeInteraction && !ufoName) {