@atlaskit/react-ufo 2.5.3 → 2.7.0

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 (53) hide show
  1. package/CHANGELOG.md +20 -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 +100 -0
  5. package/dist/cjs/create-payload/common/utils/index.js +66 -2
  6. package/dist/cjs/create-payload/index.js +55 -78
  7. package/dist/cjs/interaction-metrics/common/constants.js +8 -3
  8. package/dist/cjs/interaction-metrics/common/index.js +151 -0
  9. package/dist/cjs/interaction-metrics/index.js +166 -238
  10. package/dist/cjs/interaction-metrics-init/index.js +31 -9
  11. package/dist/cjs/load-hold/UFOLoadHold.js +5 -3
  12. package/dist/cjs/segment/segment.js +9 -8
  13. package/dist/es2019/config/index.js +22 -0
  14. package/dist/es2019/create-experimental-interaction-metrics-payload/index.js +71 -0
  15. package/dist/es2019/create-payload/common/utils/index.js +68 -1
  16. package/dist/es2019/create-payload/index.js +48 -77
  17. package/dist/es2019/interaction-metrics/common/constants.js +7 -2
  18. package/dist/es2019/interaction-metrics/common/index.js +103 -0
  19. package/dist/es2019/interaction-metrics/index.js +91 -131
  20. package/dist/es2019/interaction-metrics-init/index.js +28 -8
  21. package/dist/es2019/load-hold/UFOLoadHold.js +5 -3
  22. package/dist/es2019/segment/segment.js +8 -11
  23. package/dist/esm/config/index.js +39 -18
  24. package/dist/esm/create-experimental-interaction-metrics-payload/index.js +90 -0
  25. package/dist/esm/create-payload/common/utils/index.js +63 -1
  26. package/dist/esm/create-payload/index.js +53 -78
  27. package/dist/esm/interaction-metrics/common/constants.js +7 -2
  28. package/dist/esm/interaction-metrics/common/index.js +132 -0
  29. package/dist/esm/interaction-metrics/index.js +86 -158
  30. package/dist/esm/interaction-metrics-init/index.js +28 -8
  31. package/dist/esm/load-hold/UFOLoadHold.js +5 -3
  32. package/dist/esm/segment/segment.js +9 -8
  33. package/dist/types/common/common/types.d.ts +6 -4
  34. package/dist/types/config/index.d.ts +7 -0
  35. package/dist/types/create-experimental-interaction-metrics-payload/index.d.ts +16 -0
  36. package/dist/types/create-payload/common/utils/index.d.ts +9 -0
  37. package/dist/types/create-payload/index.d.ts +13 -5660
  38. package/dist/types/interaction-context/index.d.ts +1 -0
  39. package/dist/types/interaction-metrics/common/constants.d.ts +32 -3
  40. package/dist/types/interaction-metrics/common/index.d.ts +16 -0
  41. package/dist/types/interaction-metrics/index.d.ts +1 -17
  42. package/dist/types/load-hold/UFOLoadHold.d.ts +1 -2
  43. package/dist/types-ts4.5/common/common/types.d.ts +6 -4
  44. package/dist/types-ts4.5/config/index.d.ts +7 -0
  45. package/dist/types-ts4.5/create-experimental-interaction-metrics-payload/index.d.ts +16 -0
  46. package/dist/types-ts4.5/create-payload/common/utils/index.d.ts +9 -0
  47. package/dist/types-ts4.5/create-payload/index.d.ts +13 -5660
  48. package/dist/types-ts4.5/interaction-context/index.d.ts +1 -0
  49. package/dist/types-ts4.5/interaction-metrics/common/constants.d.ts +32 -3
  50. package/dist/types-ts4.5/interaction-metrics/common/index.d.ts +16 -0
  51. package/dist/types-ts4.5/interaction-metrics/index.d.ts +1 -17
  52. package/dist/types-ts4.5/load-hold/UFOLoadHold.d.ts +1 -2
  53. package/package.json +3 -2
@@ -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,18 @@
1
1
  import { v4 as createUUID } from 'uuid';
2
2
  import coinflip from '../coinflip';
3
3
  import { getAwaitBM3TTIList, getCapabilityRate, getConfig } from '../config';
4
+ import { experimentalVC, getExperimentalVCMetrics, onExperimentalInteractionComplete } from '../create-experimental-interaction-metrics-payload';
5
+ import { getTTAI, postInteractionLog } 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';
9
- import PostInteractionLog from './post-interaction-log';
10
+ import { addHoldCriterion, addSegmentObserver, callCancelCallbacks, callCleanUpCallbacks, getSegmentCacheKey, isPerformanceTracingEnabled, labelStackToString, pushToQueue, reactProfilerTimingMap, removeHoldCriterion, removeSegmentObserver } from './common';
11
+ import { CLEANUP_TIMEOUT, CLEANUP_TIMEOUT_AFTER_APDEX, interactionQueue, interactions, moduleLoadingRequests, segmentCache, segmentObservers } from './common/constants';
10
12
  const PreviousInteractionLog = {
11
13
  name: undefined,
12
14
  isAborted: undefined
13
15
  };
14
- 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 = [];
20
16
  export function getActiveInteraction() {
21
17
  const interactionId = getInteractionId();
22
18
  if (!interactionId.current) {
@@ -24,36 +20,6 @@ export function getActiveInteraction() {
24
20
  }
25
21
  return interactions.get(interactionId.current);
26
22
  }
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
23
  export function remove(interactionId) {
58
24
  interactions.delete(interactionId);
59
25
  }
@@ -196,7 +162,6 @@ export function addPreload(moduleId, timestamp) {
196
162
  export function addLoad(identifier, start, end) {
197
163
  addSpanToAll('bundle_load', identifier, null, start, end - start);
198
164
  }
199
- const moduleLoadingRequests = {};
200
165
  export function extractModuleName(input) {
201
166
  let result = input !== null && input !== void 0 ? input : '';
202
167
  result = result.replace(/^\.\/src\/packages\//, '');
@@ -204,30 +169,29 @@ export function extractModuleName(input) {
204
169
  result = result.replace(/(\/src)?\/(index|main)\.(tsx|ts|js|jsx)$/, '');
205
170
  return result;
206
171
  }
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) {
172
+ export function addHold(interactionId, labelStack, name, experimental) {
222
173
  const interaction = interactions.get(interactionId);
223
174
  const id = createUUID();
224
175
  if (interaction != null) {
225
- const start = performance.now();
226
- interaction.holdActive.set(id, {
176
+ var _getConfig, _getConfig$experiment;
177
+ const holdActive = {
227
178
  labelStack,
228
179
  name,
229
- start
230
- });
180
+ start: 0
181
+ };
182
+ const start = performance.now();
183
+ if ((_getConfig = getConfig()) !== null && _getConfig !== void 0 && (_getConfig$experiment = _getConfig.experimentalInteractionMetrics) !== null && _getConfig$experiment !== void 0 && _getConfig$experiment.enabled && experimental) {
184
+ interaction.holdExpActive.set(id, {
185
+ ...holdActive,
186
+ start
187
+ });
188
+ }
189
+ if (!experimental) {
190
+ interaction.holdActive.set(id, {
191
+ ...holdActive,
192
+ start
193
+ });
194
+ }
231
195
  addHoldCriterion(id, labelStack, name, start);
232
196
  return () => {
233
197
  const end = performance.now();
@@ -245,12 +209,22 @@ export function addHold(interactionId, labelStack, name) {
245
209
  removeHoldCriterion(id);
246
210
  const currentInteraction = interactions.get(interactionId);
247
211
  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);
212
+ const expHold = interaction.holdExpActive.get(id);
213
+ if (currentInteraction != null) {
214
+ if (currentHold != null) {
215
+ currentInteraction.holdInfo.push({
216
+ ...currentHold,
217
+ end
218
+ });
219
+ interaction.holdActive.delete(id);
220
+ }
221
+ if (expHold != null) {
222
+ currentInteraction.holdExpInfo.push({
223
+ ...expHold,
224
+ end
225
+ });
226
+ interaction.holdExpActive.delete(id);
227
+ }
254
228
  }
255
229
  };
256
230
  }
@@ -379,21 +353,9 @@ export const addProfilerTimings = (interactionId, labelStack, type, actualDurati
379
353
  postInteractionLog.addProfilerTimings(labelStack, type, actualDuration, baseDuration, startTime, commitTime);
380
354
  }
381
355
  };
382
- const pushToQueue = (id, data) => {
383
- interactionQueue.push({
384
- id,
385
- data
386
- });
387
- };
388
356
  let handleInteraction = pushToQueue;
389
- function callCleanUpCallbacks(interaction) {
390
- interaction.cleanupCallbacks.reverse().forEach(cleanUpCallback => {
391
- cleanUpCallback();
392
- });
393
- }
394
357
  const finishInteraction = (id, data, endTime = performance.now()) => {
395
358
  var _getConfig3, _getConfig3$vc;
396
- // eslint-disable-next-line no-param-reassign
397
359
  data.end = endTime;
398
360
  try {
399
361
  // for Firefox 102 and older
@@ -405,7 +367,6 @@ const finishInteraction = (id, data, endTime = performance.now()) => {
405
367
  // do nothing
406
368
  }
407
369
  if (data.featureFlags) {
408
- // eslint-disable-next-line no-param-reassign
409
370
  data.featureFlags.during = Object.fromEntries(currentFeatureFlagsAccessed);
410
371
  }
411
372
  clearActiveTrace();
@@ -413,41 +374,13 @@ const finishInteraction = (id, data, endTime = performance.now()) => {
413
374
  if ((_getConfig3 = getConfig()) !== null && _getConfig3 !== void 0 && (_getConfig3$vc = _getConfig3.vc) !== null && _getConfig3$vc !== void 0 && _getConfig3$vc.stopVCAtInteractionFinish) {
414
375
  data.vc = getVCObserver().getVCRawData();
415
376
  }
416
- remove(id);
417
377
  PreviousInteractionLog.name = data.ufoName || 'unknown';
418
378
  PreviousInteractionLog.isAborted = data.abortReason != null;
419
379
  if (data.ufoName) {
420
380
  handleInteraction(id, data);
421
381
  }
422
382
  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
- }
383
+ reactProfilerTimingMap(data);
451
384
  }
452
385
  try {
453
386
  // dispatch a global window event to notify the measure is completed
@@ -470,54 +403,86 @@ export const sinkInteractionHandler = sinkFn => {
470
403
  export const sinkPostInteractionLogHandler = sinkFn => {
471
404
  postInteractionLog.sinkHandler(sinkFn);
472
405
  };
406
+
407
+ // a flag to prevent multiple submitting
408
+ let activeSubmitted = false;
473
409
  export function tryComplete(interactionId, endTime) {
474
410
  const interaction = interactions.get(interactionId);
475
411
  if (interaction != null) {
476
- const noMoreHolds = interaction.holdActive.size === 0;
477
- if (noMoreHolds) {
412
+ const noMoreActiveHolds = interaction.holdActive.size === 0;
413
+ const noMoreExpHolds = interaction.holdExpActive.size === 0;
414
+ const postInteraction = () => {
478
415
  var _getConfig4, _getConfig4$postInter;
479
- finishInteraction(interactionId, interaction, endTime);
480
416
  if ((_getConfig4 = getConfig()) !== null && _getConfig4 !== void 0 && (_getConfig4$postInter = _getConfig4.postInteractionLog) !== null && _getConfig4$postInter !== void 0 && _getConfig4$postInter.enabled) {
481
- postInteractionLog.onInteractionComplete(interaction);
417
+ var _getExperimentalVCMet;
418
+ const experimentalVC90 = (_getExperimentalVCMet = getExperimentalVCMetrics(interaction)) === null || _getExperimentalVCMet === void 0 ? void 0 : _getExperimentalVCMet['metric:experimental:vc90'];
419
+ const experimentalTTAI = getTTAI(interaction);
420
+ postInteractionLog.onInteractionComplete({
421
+ ...interaction,
422
+ experimentalTTAI,
423
+ experimentalVC90
424
+ });
425
+ }
426
+ remove(interactionId);
427
+ };
428
+ if (noMoreActiveHolds) {
429
+ if (!activeSubmitted) {
430
+ finishInteraction(interactionId, interaction, endTime);
431
+ activeSubmitted = true;
432
+ }
433
+ if (noMoreExpHolds) {
434
+ var _getConfig5, _getConfig5$experimen;
435
+ if ((_getConfig5 = getConfig()) !== null && _getConfig5 !== void 0 && (_getConfig5$experimen = _getConfig5.experimentalInteractionMetrics) !== null && _getConfig5$experimen !== void 0 && _getConfig5$experimen.enabled) {
436
+ onExperimentalInteractionComplete(interactionId, interaction, endTime);
437
+ }
438
+ postInteraction();
482
439
  }
483
440
  }
484
441
  }
485
442
  }
486
- function callCancelCallbacks(interaction) {
487
- interaction.cancelCallbacks.reverse().forEach(cancelCallback => {
488
- cancelCallback();
489
- });
490
- }
491
443
  export function abort(interactionId, abortReason) {
492
444
  const interaction = interactions.get(interactionId);
493
445
  if (interaction != null) {
446
+ var _getConfig6, _getConfig6$experimen;
494
447
  callCancelCallbacks(interaction);
495
448
  interaction.abortReason = abortReason;
496
449
  finishInteraction(interactionId, interaction);
450
+ if ((_getConfig6 = getConfig()) !== null && _getConfig6 !== void 0 && (_getConfig6$experimen = _getConfig6.experimentalInteractionMetrics) !== null && _getConfig6$experimen !== void 0 && _getConfig6$experimen.enabled) {
451
+ onExperimentalInteractionComplete(interactionId, interaction);
452
+ }
453
+ remove(interactionId);
497
454
  }
498
455
  }
499
456
  export function abortByNewInteraction(interactionId, interactionName) {
500
457
  const interaction = interactions.get(interactionId);
501
458
  if (interaction != null) {
459
+ var _getConfig7, _getConfig7$experimen;
502
460
  callCancelCallbacks(interaction);
503
461
  interaction.abortReason = 'new_interaction';
504
462
  interaction.abortedByInteractionName = interactionName;
505
463
  finishInteraction(interactionId, interaction);
464
+ if ((_getConfig7 = getConfig()) !== null && _getConfig7 !== void 0 && (_getConfig7$experimen = _getConfig7.experimentalInteractionMetrics) !== null && _getConfig7$experimen !== void 0 && _getConfig7$experimen.enabled) {
465
+ onExperimentalInteractionComplete(interactionId, interaction);
466
+ }
467
+ remove(interactionId);
506
468
  }
507
469
  }
508
470
  export function abortAll(abortReason, abortedByInteractionName) {
509
471
  interactions.forEach((interaction, interactionId) => {
472
+ var _getConfig8, _getConfig8$experimen;
510
473
  const noMoreHolds = interaction.holdActive.size === 0;
511
474
  if (!noMoreHolds) {
512
475
  callCancelCallbacks(interaction);
513
- // eslint-disable-next-line no-param-reassign
514
476
  interaction.abortReason = abortReason;
515
477
  if (abortedByInteractionName != null) {
516
- // eslint-disable-next-line no-param-reassign
517
478
  interaction.abortedByInteractionName = abortedByInteractionName;
518
479
  }
519
480
  }
520
481
  finishInteraction(interactionId, interaction);
482
+ if ((_getConfig8 = getConfig()) !== null && _getConfig8 !== void 0 && (_getConfig8$experimen = _getConfig8.experimentalInteractionMetrics) !== null && _getConfig8$experimen !== void 0 && _getConfig8$experimen.enabled) {
483
+ onExperimentalInteractionComplete(interactionId, interaction);
484
+ }
485
+ remove(interactionId);
521
486
  });
522
487
  }
523
488
  export function addOnCancelCallback(id, cancelCallback) {
@@ -525,8 +490,8 @@ export function addOnCancelCallback(id, cancelCallback) {
525
490
  interaction === null || interaction === void 0 ? void 0 : interaction.cancelCallbacks.push(cancelCallback);
526
491
  }
527
492
  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) {
493
+ var _getConfig9, _getConfig9$postInter;
494
+ if ((_getConfig9 = getConfig()) !== null && _getConfig9 !== void 0 && (_getConfig9$postInter = _getConfig9.postInteractionLog) !== null && _getConfig9$postInter !== void 0 && _getConfig9$postInter.enabled) {
530
495
  postInteractionLog.reset();
531
496
  }
532
497
  let previousTime = startTime;
@@ -566,9 +531,11 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
566
531
  requestInfo: [],
567
532
  reactProfilerTimings: [],
568
533
  holdInfo: [],
534
+ holdExpInfo: [],
569
535
  holdActive: new Map(),
536
+ holdExpActive: new Map(),
570
537
  // measure when we execute this code
571
- // from this we can measure the input delay -
538
+ // from this, we can measure the input delay -
572
539
  // how long the browser took to hand execution back to JS)
573
540
  measureStart: performance.now(),
574
541
  rate,
@@ -618,6 +585,10 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
618
585
  postInteractionLog.startVCObserver({
619
586
  startTime
620
587
  });
588
+ experimentalVC.start({
589
+ startTime
590
+ });
591
+ activeSubmitted = false;
621
592
  }
622
593
  }
623
594
  export function addBrowserMetricEvent(event) {
@@ -680,17 +651,6 @@ export function addRequestInfo(interactionId, labelStack, requestInfo) {
680
651
  });
681
652
  }
682
653
  }
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
654
  export function addSegment(labelStack) {
695
655
  const key = getSegmentCacheKey(labelStack);
696
656
  const existingSegment = segmentCache.get(key);
@@ -1,8 +1,10 @@
1
1
  import { unstable_IdlePriority as idlePriority, unstable_scheduleCallback as scheduleCallback } from 'scheduler';
2
2
  import { startLighthouseObserver } from '../additional-payload';
3
3
  import { setUFOConfig } from '../config';
4
+ import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-interaction-metrics-payload';
5
+ import { postInteractionLog } from '../create-payload/common/utils';
4
6
  import { setupHiddenTimingCapture } from '../hidden-timing';
5
- import { postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
7
+ import { sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
6
8
  import { getVCObserver } from '../vc';
7
9
  let initialized = false;
8
10
  function sinkInteraction(instance, payloadPackage) {
@@ -15,6 +17,16 @@ function sinkInteraction(instance, payloadPackage) {
15
17
  });
16
18
  });
17
19
  }
20
+ function sinkExperimentalInteractionMetrics(instance, payloadPackage) {
21
+ sinkExperimentalHandler((interactionId, interaction) => {
22
+ scheduleCallback(idlePriority, () => {
23
+ const payload = payloadPackage.createExperimentalMetricsPayload(interactionId, interaction);
24
+ if (payload) {
25
+ instance.sendOperationalEvent(payload);
26
+ }
27
+ });
28
+ });
29
+ }
18
30
  function sinkPostInteractionLog(instance, createPostInteractionLogPayload) {
19
31
  sinkPostInteractionLogHandler(logOutput => {
20
32
  scheduleCallback(idlePriority, () => {
@@ -32,6 +44,7 @@ export const init = (analyticsWebClientAsync, config) => {
32
44
  }
33
45
  setUFOConfig(config);
34
46
  if ((_config$vc = config.vc) !== null && _config$vc !== void 0 && _config$vc.enabled) {
47
+ var _config$experimentalI;
35
48
  const vcOptions = {
36
49
  heatmapSize: config.vc.heatmapSize,
37
50
  oldDomUpdates: config.vc.oldDomUpdates,
@@ -45,27 +58,34 @@ export const init = (analyticsWebClientAsync, config) => {
45
58
  postInteractionLog.startVCObserver({
46
59
  startTime: 0
47
60
  });
61
+ if (config !== null && config !== void 0 && (_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
62
+ experimentalVC.initialize(vcOptions).start({
63
+ startTime: 0
64
+ });
65
+ }
48
66
  }
49
67
  setupHiddenTimingCapture();
50
68
  startLighthouseObserver();
51
69
  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]) => {
70
+ Promise.all([analyticsWebClientAsync, import( /* webpackChunkName: "create-payloads" */'../create-payload'), import( /* webpackChunkName: "create-post-interaction-log-payload" */'../create-post-interaction-log-payload')]).then(([awc, payloadPackage, createPostInteractionLogPayloadPackage]) => {
57
71
  if (awc.getAnalyticsWebClientPromise) {
58
72
  awc.getAnalyticsWebClientPromise().then(client => {
59
- var _config$postInteracti;
73
+ var _config$experimentalI2, _config$postInteracti;
60
74
  const instance = client.getInstance();
61
75
  sinkInteraction(instance, payloadPackage);
76
+ if (config !== null && config !== void 0 && (_config$experimentalI2 = config.experimentalInteractionMetrics) !== null && _config$experimentalI2 !== void 0 && _config$experimentalI2.enabled) {
77
+ sinkExperimentalInteractionMetrics(instance, payloadPackage);
78
+ }
62
79
  if ((_config$postInteracti = config.postInteractionLog) !== null && _config$postInteracti !== void 0 && _config$postInteracti.enabled) {
63
80
  sinkPostInteractionLog(instance, createPostInteractionLogPayloadPackage.default);
64
81
  }
65
82
  });
66
83
  } else if (awc.sendOperationalEvent) {
67
- var _config$postInteracti2;
84
+ var _config$experimentalI3, _config$postInteracti2;
68
85
  sinkInteraction(awc, payloadPackage);
86
+ if (config !== null && config !== void 0 && (_config$experimentalI3 = config.experimentalInteractionMetrics) !== null && _config$experimentalI3 !== void 0 && _config$experimentalI3.enabled) {
87
+ sinkExperimentalInteractionMetrics(awc, payloadPackage);
88
+ }
69
89
  if ((_config$postInteracti2 = config.postInteractionLog) !== null && _config$postInteracti2 !== void 0 && _config$postInteracti2.enabled) {
70
90
  sinkPostInteractionLog(awc, createPostInteractionLogPayloadPackage.default);
71
91
  }
@@ -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,7 +56,10 @@ 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) {
59
+ if (hold && context != null) {
60
+ if (experimental && context.holdExperimental) {
61
+ return context.holdExperimental(name);
62
+ }
61
63
  return context.hold(name);
62
64
  }
63
65
  }, [hold, context, name]);
@@ -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,11 +104,12 @@ 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
- ) {
107
+ hold(name = 'unknown') {
114
108
  return this._internalHold(this.labelStack, name);
115
109
  },
110
+ holdExperimental(name = 'unknown') {
111
+ return this._internalHold(this.labelStack, name, true);
112
+ },
116
113
  addHoldByID(labelStack, id, name = 'unknown') {
117
114
  this._internalHoldByID(labelStack, id, name, false);
118
115
  },