@atlaskit/react-ufo 2.10.0 → 2.12.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 (49) 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 +49 -18
  4. package/dist/cjs/create-experimental-interaction-metrics-payload/index.js +114 -0
  5. package/dist/cjs/create-payload/index.js +51 -10
  6. package/dist/cjs/interaction-metrics/common/constants.js +2 -3
  7. package/dist/cjs/interaction-metrics/index.js +130 -55
  8. package/dist/cjs/interaction-metrics/post-interaction-log.js +20 -10
  9. package/dist/cjs/interaction-metrics-init/index.js +28 -7
  10. package/dist/cjs/load-hold/UFOLoadHold.js +5 -3
  11. package/dist/cjs/segment/segment.js +9 -8
  12. package/dist/cjs/vc/vc-observer/observers/index.js +3 -1
  13. package/dist/es2019/config/index.js +30 -0
  14. package/dist/es2019/create-experimental-interaction-metrics-payload/index.js +85 -0
  15. package/dist/es2019/create-payload/index.js +50 -8
  16. package/dist/es2019/interaction-metrics/common/constants.js +1 -2
  17. package/dist/es2019/interaction-metrics/index.js +109 -28
  18. package/dist/es2019/interaction-metrics/post-interaction-log.js +21 -11
  19. package/dist/es2019/interaction-metrics-init/index.js +26 -7
  20. package/dist/es2019/load-hold/UFOLoadHold.js +5 -3
  21. package/dist/es2019/segment/segment.js +8 -11
  22. package/dist/es2019/vc/vc-observer/observers/index.js +3 -1
  23. package/dist/esm/config/index.js +47 -18
  24. package/dist/esm/create-experimental-interaction-metrics-payload/index.js +104 -0
  25. package/dist/esm/create-payload/index.js +51 -11
  26. package/dist/esm/interaction-metrics/common/constants.js +1 -2
  27. package/dist/esm/interaction-metrics/index.js +102 -27
  28. package/dist/esm/interaction-metrics/post-interaction-log.js +20 -10
  29. package/dist/esm/interaction-metrics-init/index.js +26 -7
  30. package/dist/esm/load-hold/UFOLoadHold.js +5 -3
  31. package/dist/esm/segment/segment.js +9 -8
  32. package/dist/esm/vc/vc-observer/observers/index.js +3 -1
  33. package/dist/types/common/common/types.d.ts +6 -4
  34. package/dist/types/config/index.d.ts +8 -0
  35. package/dist/types/create-experimental-interaction-metrics-payload/index.d.ts +16 -0
  36. package/dist/types/create-payload/index.d.ts +5922 -0
  37. package/dist/types/interaction-context/index.d.ts +1 -0
  38. package/dist/types/interaction-metrics/common/constants.d.ts +1 -2
  39. package/dist/types/interaction-metrics/index.d.ts +1 -1
  40. package/dist/types/load-hold/UFOLoadHold.d.ts +1 -2
  41. package/dist/types-ts4.5/common/common/types.d.ts +6 -4
  42. package/dist/types-ts4.5/config/index.d.ts +8 -0
  43. package/dist/types-ts4.5/create-experimental-interaction-metrics-payload/index.d.ts +16 -0
  44. package/dist/types-ts4.5/create-payload/index.d.ts +5922 -0
  45. package/dist/types-ts4.5/interaction-context/index.d.ts +1 -0
  46. package/dist/types-ts4.5/interaction-metrics/common/constants.d.ts +1 -2
  47. package/dist/types-ts4.5/interaction-metrics/index.d.ts +1 -1
  48. package/dist/types-ts4.5/load-hold/UFOLoadHold.d.ts +1 -2
  49. package/package.json +3 -5
@@ -9,6 +9,7 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
9
9
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
+ var _config = require("../../../config");
12
13
  var _vcUtils = require("../media-wrapper/vc-utils");
13
14
  var _editorLnv = require("./editor-lnv");
14
15
  var _ssrPlaceholders = require("./ssr-placeholders");
@@ -140,6 +141,7 @@ var Observers = exports.Observers = /*#__PURE__*/function () {
140
141
  key: "getMutationObserver",
141
142
  value: function getMutationObserver() {
142
143
  var _this2 = this;
144
+ var shouldHandleEditorLnvLocal = (0, _config.shouldHandleEditorLnv)();
143
145
  return this.isBrowserSupported() ? new MutationObserver(function (mutations) {
144
146
  _this2.measureStart();
145
147
  mutations.forEach(function (mutation) {
@@ -185,7 +187,7 @@ var Observers = exports.Observers = /*#__PURE__*/function () {
185
187
  });
186
188
  return;
187
189
  }
188
- if ((0, _platformFeatureFlags.fg)('platform_editor_ed-25557_lnv_add_ssr_placeholder')) {
190
+ if (shouldHandleEditorLnvLocal) {
189
191
  if (_this2.editorLnvHandler.shouldHandleAddedNode(node)) {
190
192
  _this2.editorLnvHandler.handleAddedNode(node).then(function (_ref) {
191
193
  var shouldIgnore = _ref.shouldIgnore;
@@ -67,6 +67,28 @@ export function getInteractionRate(name, interactionKind) {
67
67
  return 0;
68
68
  }
69
69
  }
70
+ export function getExperimentalInteractionRate(name, interactionType) {
71
+ try {
72
+ if (!config) {
73
+ return 0;
74
+ }
75
+ const {
76
+ experimentalInteractionMetrics
77
+ } = config;
78
+ if (!(experimentalInteractionMetrics !== null && experimentalInteractionMetrics !== void 0 && experimentalInteractionMetrics.enabled)) {
79
+ return 0;
80
+ }
81
+ if (experimentalInteractionMetrics.rates && typeof experimentalInteractionMetrics.rates[name] === 'number') {
82
+ return experimentalInteractionMetrics.rates[name];
83
+ }
84
+ if (experimentalInteractionMetrics.kind && typeof experimentalInteractionMetrics.kind[interactionType] === 'number') {
85
+ return experimentalInteractionMetrics.kind[interactionType];
86
+ }
87
+ return 0;
88
+ } catch (e) {
89
+ return 0;
90
+ }
91
+ }
70
92
  export function getPostInteractionRate(name, interactionType) {
71
93
  try {
72
94
  if (!config) {
@@ -234,4 +256,12 @@ export function getDoNotAbortActivePressInteractionOnTransition() {
234
256
  } catch (e) {
235
257
  return undefined;
236
258
  }
259
+ }
260
+ export function shouldHandleEditorLnv() {
261
+ try {
262
+ var _config$enableEditorL, _config;
263
+ return (_config$enableEditorL = (_config = config) === null || _config === void 0 ? void 0 : _config.enableEditorLnvHandler) !== null && _config$enableEditorL !== void 0 ? _config$enableEditorL : false;
264
+ } catch (e) {
265
+ return false;
266
+ }
237
267
  }
@@ -0,0 +1,85 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { getPageVisibilityState } from '../hidden-timing';
3
+ import { VCObserver } from '../vc/vc-observer';
4
+ const interactionBuffer = [];
5
+ let bufferInteractionData = (interactionId, data) => {
6
+ interactionBuffer.push({
7
+ interactionId,
8
+ data
9
+ });
10
+ };
11
+ function clearInteractionBuffer() {
12
+ interactionBuffer.length = 0;
13
+ }
14
+ function appendInteractionData(interactionId, data) {
15
+ bufferInteractionData(interactionId, data);
16
+ }
17
+ export function installInteractionSink(handler) {
18
+ for (const {
19
+ interactionId,
20
+ data
21
+ } of interactionBuffer) {
22
+ handler(interactionId, data);
23
+ }
24
+ clearInteractionBuffer();
25
+ bufferInteractionData = handler;
26
+ }
27
+ export function sinkExperimentalHandler(sinkFn) {
28
+ installInteractionSink(sinkFn);
29
+ }
30
+ export function onExperimentalInteractionComplete(interactionId, data, endTime = performance.now()) {
31
+ if (data.ufoName) {
32
+ data.end = endTime;
33
+ appendInteractionData(interactionId, data);
34
+ clearInteractionBuffer();
35
+ }
36
+ }
37
+ export class ExperimentalVCMetrics {
38
+ constructor() {
39
+ _defineProperty(this, "vcObserver", null);
40
+ }
41
+ initialize(options) {
42
+ if (this.vcObserver === null) {
43
+ this.vcObserver = new VCObserver({
44
+ ...options,
45
+ isPostInteraction: true
46
+ });
47
+ }
48
+ return this;
49
+ }
50
+ start({
51
+ startTime
52
+ }) {
53
+ var _this$vcObserver;
54
+ (_this$vcObserver = this.vcObserver) === null || _this$vcObserver === void 0 ? void 0 : _this$vcObserver.start({
55
+ startTime
56
+ });
57
+ }
58
+ }
59
+ export const experimentalVC = new ExperimentalVCMetrics();
60
+ export const getExperimentalVCMetrics = interaction => {
61
+ if (experimentalVC.vcObserver) {
62
+ var _interaction$apdex, _interaction$apdex$;
63
+ const prefix = 'ufo-experimental';
64
+ const result = experimentalVC.vcObserver.getVCResult({
65
+ start: interaction.start,
66
+ stop: interaction.end,
67
+ tti: (_interaction$apdex = interaction.apdex) === null || _interaction$apdex === void 0 ? void 0 : (_interaction$apdex$ = _interaction$apdex[0]) === null || _interaction$apdex$ === void 0 ? void 0 : _interaction$apdex$.stopTime,
68
+ prefix,
69
+ vc: interaction.vc
70
+ });
71
+ const VC = result === null || result === void 0 ? void 0 : result['metrics:vc'];
72
+ if (!VC || !(result !== null && result !== void 0 && result[`${prefix}:vc:clean`])) {
73
+ return result;
74
+ }
75
+ const pageVisibilityUpToTTAI = getPageVisibilityState(interaction.start, interaction.end);
76
+ if (interaction.abortReason || pageVisibilityUpToTTAI !== 'visible') {
77
+ return result;
78
+ }
79
+ return {
80
+ ...result,
81
+ 'metric:experimental:vc90': VC['90']
82
+ };
83
+ }
84
+ return null;
85
+ };
@@ -2,8 +2,10 @@ import Bowser from 'bowser-ultralight';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { getLighthouseMetrics } from '../additional-payload';
4
4
  import * as bundleEvalTiming from '../bundle-eval-timing';
5
+ import coinflip from '../coinflip';
5
6
  import { REACT_UFO_VERSION } from '../common/constants';
6
- import { getConfig, getUfoNameOverrides } from '../config';
7
+ import { getConfig, getExperimentalInteractionRate, getUfoNameOverrides } from '../config';
8
+ import { getExperimentalVCMetrics } from '../create-experimental-interaction-metrics-payload';
7
9
  import { getBm3Timings } from '../custom-timings';
8
10
  import { getGlobalErrorCount } from '../global-error-handler';
9
11
  import { getPageVisibilityState } from '../hidden-timing';
@@ -28,7 +30,6 @@ function getUfoNameOverride(interaction) {
28
30
  }
29
31
  }
30
32
  return ufoName;
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
33
  } catch (e) {
33
34
  return ufoName;
34
35
  }
@@ -155,8 +156,16 @@ const getPaintMetrics = type => {
155
156
  });
156
157
  return metrics;
157
158
  };
159
+ const getTTAI = interaction => {
160
+ const {
161
+ start,
162
+ end
163
+ } = interaction;
164
+ const pageVisibilityUpToTTAI = getPageVisibilityUpToTTAI(interaction);
165
+ return !interaction.abortReason && pageVisibilityUpToTTAI === 'visible' ? Math.round(end - start) : undefined;
166
+ };
158
167
  const getVCMetrics = interaction => {
159
- var _config$vc, _config$vc$ssrWhiteli, _interaction$apdex, _interaction$apdex$;
168
+ var _config$vc, _config$vc$ssrWhiteli, _interaction$apdex, _interaction$apdex$, _config$experimentalI;
160
169
  const config = getConfig();
161
170
  if (!(config !== null && config !== void 0 && (_config$vc = config.vc) !== null && _config$vc !== void 0 && _config$vc.enabled)) {
162
171
  return {};
@@ -179,6 +188,9 @@ const getVCMetrics = interaction => {
179
188
  vc: interaction.vc,
180
189
  ...ssr
181
190
  });
191
+ if ((_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
192
+ getVCObserver().stop();
193
+ }
182
194
  postInteractionLog.setLastInteractionFinishVCResult(result);
183
195
  const VC = result === null || result === void 0 ? void 0 : result['metrics:vc'];
184
196
  if (!VC || !(result !== null && result !== void 0 && result[`${prefix}:vc:clean`])) {
@@ -641,13 +653,15 @@ function getStylesheetMetrics() {
641
653
  return {};
642
654
  }
643
655
  }
656
+ let regularTTAI;
657
+ let expTTAI;
644
658
  function getErrorCounts(interaction) {
645
659
  return {
646
660
  'ufo:errors:globalCount': getGlobalErrorCount(),
647
661
  'ufo:errors:count': interaction.errors.length
648
662
  };
649
663
  }
650
- function createInteractionMetricsPayload(interaction, interactionId) {
664
+ function createInteractionMetricsPayload(interaction, interactionId, experimental) {
651
665
  var _window$location, _config$additionalPay;
652
666
  const interactionPayloadStart = performance.now();
653
667
  const config = getConfig();
@@ -699,7 +713,7 @@ function createInteractionMetricsPayload(interaction, interactionId) {
699
713
  };
700
714
  // Detailed payload. Page visibility = visible
701
715
  const getDetailedInteractionMetrics = () => {
702
- if (window.__UFO_COMPACT_PAYLOAD__ || !isDetailedPayload) {
716
+ if (experimental || window.__UFO_COMPACT_PAYLOAD__ || !isDetailedPayload) {
703
717
  return {};
704
718
  }
705
719
  const spans = [...interaction.spans, ...atlaskitInteractionSpans];
@@ -714,7 +728,7 @@ function createInteractionMetricsPayload(interaction, interactionId) {
714
728
  })),
715
729
  holdActive: [...interaction.holdActive.values()],
716
730
  redirects: optimizeRedirects(interaction.redirects, start),
717
- holdInfo: optimizeHoldInfo(interaction.holdInfo, start),
731
+ holdInfo: optimizeHoldInfo(experimental ? interaction.holdExpInfo : interaction.holdInfo, start),
718
732
  spans: optimizeSpans(spans, start),
719
733
  requestInfo: optimizeRequestInfo(interaction.requestInfo, start),
720
734
  customTimings: optimizeCustomTimings(interaction.customTimings, start),
@@ -734,6 +748,11 @@ function createInteractionMetricsPayload(interaction, interactionId) {
734
748
  SSRTimings: config !== null && config !== void 0 && (_config$ssr4 = config.ssr) !== null && _config$ssr4 !== void 0 && _config$ssr4.getSSRTimings ? config.ssr.getSSRTimings() : objectToArray(ssr.getSSRTimings())
735
749
  };
736
750
  };
751
+ if (experimental) {
752
+ expTTAI = getTTAI(interaction);
753
+ } else {
754
+ regularTTAI = getTTAI(interaction);
755
+ }
737
756
  const newUFOName = sanitizeUfoName(ufoName);
738
757
  const payload = {
739
758
  actionSubject: 'experience',
@@ -754,7 +773,7 @@ function createInteractionMetricsPayload(interaction, interactionId) {
754
773
  payloadSource: 'platform'
755
774
  },
756
775
  'event:region': config.region || 'unknown',
757
- 'experience:key': 'custom.interaction-metrics',
776
+ 'experience:key': experimental ? 'custom.experimental-interaction-metrics' : 'custom.interaction-metrics',
758
777
  'experience:name': newUFOName,
759
778
  // root
760
779
  ...getBrowserMetadata(),
@@ -763,6 +782,7 @@ function createInteractionMetricsPayload(interaction, interactionId) {
763
782
  ...getPaintMetrics(type),
764
783
  ...getNavigationMetrics(type),
765
784
  ...getVCMetrics(interaction),
785
+ ...(experimental ? getExperimentalVCMetrics(interaction) : undefined),
766
786
  ...((_config$additionalPay = config.additionalPayloadData) === null || _config$additionalPay === void 0 ? void 0 : _config$additionalPay.call(config, interaction)),
767
787
  ...getTracingContextData(interaction),
768
788
  ...getStylesheetMetrics(),
@@ -802,12 +822,18 @@ function createInteractionMetricsPayload(interaction, interactionId) {
802
822
  ...getPageLoadInteractionMetrics(),
803
823
  ...getDetailedInteractionMetrics(),
804
824
  ...getPageLoadDetailedInteractionMetrics(),
805
- ...getBm3TrackerTimings(interaction)
825
+ ...getBm3TrackerTimings(interaction),
826
+ 'metric:ttai': experimental ? regularTTAI || expTTAI : undefined,
827
+ 'metric:experimental:ttai': expTTAI
806
828
  },
807
829
  'ufo:payloadTime': roundEpsilon(performance.now() - interactionPayloadStart)
808
830
  }
809
831
  }
810
832
  };
833
+ if (experimental) {
834
+ regularTTAI = undefined;
835
+ expTTAI = undefined;
836
+ }
811
837
  payload.attributes.properties['event:sizeInKb'] = getPayloadSize(payload.attributes.properties);
812
838
  return payload;
813
839
  }
@@ -819,4 +845,20 @@ export function createPayloads(interactionId, interaction) {
819
845
  };
820
846
  const interactionMetricsPayload = createInteractionMetricsPayload(modifiedInteraction, interactionId);
821
847
  return [interactionMetricsPayload];
848
+ }
849
+ export function createExperimentalMetricsPayload(interactionId, interaction) {
850
+ const config = getConfig();
851
+ if (!config) {
852
+ throw Error('UFO Configuration not provided');
853
+ }
854
+ const ufoName = sanitizeUfoName(interaction.ufoName);
855
+ const rate = getExperimentalInteractionRate(ufoName, interaction.type);
856
+ if (!coinflip(rate)) {
857
+ return null;
858
+ }
859
+ const pageVisibilityState = getPageVisibilityState(interaction.start, interaction.end);
860
+ if (pageVisibilityState !== 'visible') {
861
+ return null;
862
+ }
863
+ return createInteractionMetricsPayload(interaction, interactionId, true);
822
864
  }
@@ -1,2 +1 @@
1
- const interactions = new Map();
2
- export default interactions;
1
+ export const interactions = new Map();
@@ -1,11 +1,12 @@
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';
4
5
  import { clearActiveTrace } from '../experience-trace-id-context';
5
6
  import { allFeatureFlagsAccessed, currentFeatureFlagsAccessed } from '../feature-flags-accessed';
6
7
  import { getInteractionId } from '../interaction-id-context';
7
8
  import { getVCObserver } from '../vc';
8
- import interactions from './common/constants';
9
+ import { interactions } from './common/constants';
9
10
  import PostInteractionLog from './post-interaction-log';
10
11
  const PreviousInteractionLog = {
11
12
  name: undefined,
@@ -218,16 +219,29 @@ function removeHoldCriterion(id) {
218
219
  }
219
220
  window.__CRITERION__.removeUFOHold(id);
220
221
  }
221
- export function addHold(interactionId, labelStack, name) {
222
+ export function addHold(interactionId, labelStack, name, experimental) {
222
223
  const interaction = interactions.get(interactionId);
223
224
  const id = createUUID();
224
225
  if (interaction != null) {
226
+ var _getConfig2, _getConfig2$experimen;
225
227
  const start = performance.now();
226
- interaction.holdActive.set(id, {
228
+ const holdActive = {
227
229
  labelStack,
228
230
  name,
229
231
  start
230
- });
232
+ };
233
+ if ((_getConfig2 = getConfig()) !== null && _getConfig2 !== void 0 && (_getConfig2$experimen = _getConfig2.experimentalInteractionMetrics) !== null && _getConfig2$experimen !== void 0 && _getConfig2$experimen.enabled && experimental) {
234
+ interaction.holdExpActive.set(id, {
235
+ ...holdActive,
236
+ start
237
+ });
238
+ }
239
+ if (!experimental) {
240
+ interaction.holdActive.set(id, {
241
+ ...holdActive,
242
+ start
243
+ });
244
+ }
231
245
  addHoldCriterion(id, labelStack, name, start);
232
246
  return () => {
233
247
  const end = performance.now();
@@ -245,12 +259,22 @@ export function addHold(interactionId, labelStack, name) {
245
259
  removeHoldCriterion(id);
246
260
  const currentInteraction = interactions.get(interactionId);
247
261
  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);
262
+ const expHold = interaction.holdExpActive.get(id);
263
+ if (currentInteraction != null) {
264
+ if (currentHold != null) {
265
+ currentInteraction.holdInfo.push({
266
+ ...currentHold,
267
+ end
268
+ });
269
+ interaction.holdActive.delete(id);
270
+ }
271
+ if (expHold != null) {
272
+ currentInteraction.holdExpInfo.push({
273
+ ...expHold,
274
+ end
275
+ });
276
+ interaction.holdExpActive.delete(id);
277
+ }
254
278
  }
255
279
  };
256
280
  }
@@ -353,7 +377,7 @@ export function addErrorToAll(name, labelStack, errorType, errorMessage, errorSt
353
377
  });
354
378
  }
355
379
  export const addProfilerTimings = (interactionId, labelStack, type, actualDuration, baseDuration, startTime, commitTime) => {
356
- var _getConfig2, _getConfig2$postInter;
380
+ var _getConfig3, _getConfig3$postInter;
357
381
  if (isPerformanceTracingEnabled()) {
358
382
  try {
359
383
  // for Firefox 102 and older
@@ -375,7 +399,7 @@ export const addProfilerTimings = (interactionId, labelStack, type, actualDurati
375
399
  startTime,
376
400
  commitTime
377
401
  });
378
- } else if ((_getConfig2 = getConfig()) !== null && _getConfig2 !== void 0 && (_getConfig2$postInter = _getConfig2.postInteractionLog) !== null && _getConfig2$postInter !== void 0 && _getConfig2$postInter.enabled) {
402
+ } else if ((_getConfig3 = getConfig()) !== null && _getConfig3 !== void 0 && (_getConfig3$postInter = _getConfig3.postInteractionLog) !== null && _getConfig3$postInter !== void 0 && _getConfig3$postInter.enabled) {
379
403
  postInteractionLog.addProfilerTimings(labelStack, type, actualDuration, baseDuration, startTime, commitTime);
380
404
  }
381
405
  };
@@ -392,8 +416,7 @@ function callCleanUpCallbacks(interaction) {
392
416
  });
393
417
  }
394
418
  const finishInteraction = (id, data, endTime = performance.now()) => {
395
- var _getConfig3, _getConfig3$vc;
396
- // eslint-disable-next-line no-param-reassign
419
+ var _getConfig4, _getConfig4$vc, _getConfig5, _getConfig5$experimen;
397
420
  data.end = endTime;
398
421
  try {
399
422
  // for Firefox 102 and older
@@ -405,15 +428,16 @@ const finishInteraction = (id, data, endTime = performance.now()) => {
405
428
  // do nothing
406
429
  }
407
430
  if (data.featureFlags) {
408
- // eslint-disable-next-line no-param-reassign
409
431
  data.featureFlags.during = Object.fromEntries(currentFeatureFlagsAccessed);
410
432
  }
411
433
  clearActiveTrace();
412
434
  callCleanUpCallbacks(data);
413
- if ((_getConfig3 = getConfig()) !== null && _getConfig3 !== void 0 && (_getConfig3$vc = _getConfig3.vc) !== null && _getConfig3$vc !== void 0 && _getConfig3$vc.stopVCAtInteractionFinish) {
435
+ if ((_getConfig4 = getConfig()) !== null && _getConfig4 !== void 0 && (_getConfig4$vc = _getConfig4.vc) !== null && _getConfig4$vc !== void 0 && _getConfig4$vc.stopVCAtInteractionFinish) {
414
436
  data.vc = getVCObserver().getVCRawData();
415
437
  }
416
- remove(id);
438
+ if (!((_getConfig5 = getConfig()) !== null && _getConfig5 !== void 0 && (_getConfig5$experimen = _getConfig5.experimentalInteractionMetrics) !== null && _getConfig5$experimen !== void 0 && _getConfig5$experimen.enabled)) {
439
+ remove(id);
440
+ }
417
441
  PreviousInteractionLog.name = data.ufoName || 'unknown';
418
442
  PreviousInteractionLog.isAborted = data.abortReason != null;
419
443
  if (data.ufoName) {
@@ -470,15 +494,51 @@ export const sinkInteractionHandler = sinkFn => {
470
494
  export const sinkPostInteractionLogHandler = sinkFn => {
471
495
  postInteractionLog.sinkHandler(sinkFn);
472
496
  };
497
+
498
+ // a flag to prevent multiple submitting
499
+ let activeSubmitted = false;
473
500
  export function tryComplete(interactionId, endTime) {
474
501
  const interaction = interactions.get(interactionId);
475
502
  if (interaction != null) {
476
- const noMoreHolds = interaction.holdActive.size === 0;
477
- if (noMoreHolds) {
478
- var _getConfig4, _getConfig4$postInter;
479
- finishInteraction(interactionId, interaction, endTime);
480
- if ((_getConfig4 = getConfig()) !== null && _getConfig4 !== void 0 && (_getConfig4$postInter = _getConfig4.postInteractionLog) !== null && _getConfig4$postInter !== void 0 && _getConfig4$postInter.enabled) {
481
- postInteractionLog.onInteractionComplete(interaction);
503
+ const noMoreActiveHolds = interaction.holdActive.size === 0;
504
+ const noMoreExpHolds = interaction.holdExpActive.size === 0;
505
+ const postInteraction = () => {
506
+ var _getConfig6, _getConfig6$postInter, _getConfig8, _getConfig8$experimen;
507
+ if ((_getConfig6 = getConfig()) !== null && _getConfig6 !== void 0 && (_getConfig6$postInter = _getConfig6.postInteractionLog) !== null && _getConfig6$postInter !== void 0 && _getConfig6$postInter.enabled) {
508
+ var _getConfig7, _getConfig7$experimen;
509
+ let experimentalVC90;
510
+ let experimentalTTAI;
511
+ if ((_getConfig7 = getConfig()) !== null && _getConfig7 !== void 0 && (_getConfig7$experimen = _getConfig7.experimentalInteractionMetrics) !== null && _getConfig7$experimen !== void 0 && _getConfig7$experimen.enabled) {
512
+ var _getExperimentalVCMet;
513
+ experimentalVC90 = (_getExperimentalVCMet = getExperimentalVCMetrics(interaction)) === null || _getExperimentalVCMet === void 0 ? void 0 : _getExperimentalVCMet['metric:experimental:vc90'];
514
+ const {
515
+ start,
516
+ end
517
+ } = interaction;
518
+ experimentalTTAI = !interaction.abortReason ? Math.round(end - start) : undefined;
519
+ }
520
+ postInteractionLog.onInteractionComplete({
521
+ ...interaction,
522
+ experimentalTTAI,
523
+ experimentalVC90
524
+ });
525
+ }
526
+ if ((_getConfig8 = getConfig()) !== null && _getConfig8 !== void 0 && (_getConfig8$experimen = _getConfig8.experimentalInteractionMetrics) !== null && _getConfig8$experimen !== void 0 && _getConfig8$experimen.enabled) {
527
+ remove(interactionId);
528
+ }
529
+ activeSubmitted = false;
530
+ };
531
+ if (noMoreActiveHolds) {
532
+ if (!activeSubmitted) {
533
+ finishInteraction(interactionId, interaction, endTime);
534
+ activeSubmitted = true;
535
+ }
536
+ if (noMoreExpHolds) {
537
+ var _getConfig9, _getConfig9$experimen;
538
+ if ((_getConfig9 = getConfig()) !== null && _getConfig9 !== void 0 && (_getConfig9$experimen = _getConfig9.experimentalInteractionMetrics) !== null && _getConfig9$experimen !== void 0 && _getConfig9$experimen.enabled) {
539
+ onExperimentalInteractionComplete(interactionId, interaction, endTime);
540
+ }
541
+ postInteraction();
482
542
  }
483
543
  }
484
544
  }
@@ -491,33 +551,46 @@ function callCancelCallbacks(interaction) {
491
551
  export function abort(interactionId, abortReason) {
492
552
  const interaction = interactions.get(interactionId);
493
553
  if (interaction != null) {
554
+ var _getConfig10, _getConfig10$experime;
494
555
  callCancelCallbacks(interaction);
495
556
  interaction.abortReason = abortReason;
496
557
  finishInteraction(interactionId, interaction);
558
+ if ((_getConfig10 = getConfig()) !== null && _getConfig10 !== void 0 && (_getConfig10$experime = _getConfig10.experimentalInteractionMetrics) !== null && _getConfig10$experime !== void 0 && _getConfig10$experime.enabled) {
559
+ onExperimentalInteractionComplete(interactionId, interaction);
560
+ remove(interactionId);
561
+ }
497
562
  }
498
563
  }
499
564
  export function abortByNewInteraction(interactionId, interactionName) {
500
565
  const interaction = interactions.get(interactionId);
501
566
  if (interaction != null) {
567
+ var _getConfig11, _getConfig11$experime;
502
568
  callCancelCallbacks(interaction);
503
569
  interaction.abortReason = 'new_interaction';
504
570
  interaction.abortedByInteractionName = interactionName;
505
571
  finishInteraction(interactionId, interaction);
572
+ if ((_getConfig11 = getConfig()) !== null && _getConfig11 !== void 0 && (_getConfig11$experime = _getConfig11.experimentalInteractionMetrics) !== null && _getConfig11$experime !== void 0 && _getConfig11$experime.enabled) {
573
+ onExperimentalInteractionComplete(interactionId, interaction);
574
+ remove(interactionId);
575
+ }
506
576
  }
507
577
  }
508
578
  export function abortAll(abortReason, abortedByInteractionName) {
509
579
  interactions.forEach((interaction, interactionId) => {
580
+ var _getConfig12, _getConfig12$experime;
510
581
  const noMoreHolds = interaction.holdActive.size === 0;
511
582
  if (!noMoreHolds) {
512
583
  callCancelCallbacks(interaction);
513
- // eslint-disable-next-line no-param-reassign
514
584
  interaction.abortReason = abortReason;
515
585
  if (abortedByInteractionName != null) {
516
- // eslint-disable-next-line no-param-reassign
517
586
  interaction.abortedByInteractionName = abortedByInteractionName;
518
587
  }
519
588
  }
520
589
  finishInteraction(interactionId, interaction);
590
+ if ((_getConfig12 = getConfig()) !== null && _getConfig12 !== void 0 && (_getConfig12$experime = _getConfig12.experimentalInteractionMetrics) !== null && _getConfig12$experime !== void 0 && _getConfig12$experime.enabled) {
591
+ onExperimentalInteractionComplete(interactionId, interaction);
592
+ remove(interactionId);
593
+ }
521
594
  });
522
595
  }
523
596
  export function addOnCancelCallback(id, cancelCallback) {
@@ -525,8 +598,8 @@ export function addOnCancelCallback(id, cancelCallback) {
525
598
  interaction === null || interaction === void 0 ? void 0 : interaction.cancelCallbacks.push(cancelCallback);
526
599
  }
527
600
  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) {
601
+ var _getConfig13, _getConfig13$postInte;
602
+ if ((_getConfig13 = getConfig()) !== null && _getConfig13 !== void 0 && (_getConfig13$postInte = _getConfig13.postInteractionLog) !== null && _getConfig13$postInte !== void 0 && _getConfig13$postInte.enabled) {
530
603
  postInteractionLog.reset();
531
604
  }
532
605
  let previousTime = startTime;
@@ -566,9 +639,11 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
566
639
  requestInfo: [],
567
640
  reactProfilerTimings: [],
568
641
  holdInfo: [],
642
+ holdExpInfo: [],
569
643
  holdActive: new Map(),
644
+ holdExpActive: new Map(),
570
645
  // measure when we execute this code
571
- // from this we can measure the input delay -
646
+ // from this, we can measure the input delay -
572
647
  // how long the browser took to hand execution back to JS)
573
648
  measureStart: performance.now(),
574
649
  rate,
@@ -612,12 +687,18 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
612
687
  addHoldByID(interactionId, [], ufoName, ufoName, true);
613
688
  }
614
689
  if (type === 'transition') {
690
+ var _getConfig14, _getConfig14$experime;
615
691
  getVCObserver().start({
616
692
  startTime
617
693
  });
618
694
  postInteractionLog.startVCObserver({
619
695
  startTime
620
696
  });
697
+ if ((_getConfig14 = getConfig()) !== null && _getConfig14 !== void 0 && (_getConfig14$experime = _getConfig14.experimentalInteractionMetrics) !== null && _getConfig14$experime !== void 0 && _getConfig14$experime.enabled) {
698
+ experimentalVC.start({
699
+ startTime
700
+ });
701
+ }
621
702
  }
622
703
  }
623
704
  export function addBrowserMetricEvent(event) {
@@ -86,23 +86,33 @@ export default class PostInteractionLog {
86
86
  * Send the log if there is data
87
87
  */
88
88
  sendPostInteractionLog() {
89
- var _this$vcObserver2;
89
+ var _this$vcObserver3, _getConfig2, _getConfig2$experimen;
90
90
  if (!this.hasData() || !this.lastInteractionFinish || !this.sinkHandlerFn) {
91
+ var _getConfig, _getConfig$experiment;
91
92
  this.reset();
93
+ if ((_getConfig = getConfig()) !== null && _getConfig !== void 0 && (_getConfig$experiment = _getConfig.experimentalInteractionMetrics) !== null && _getConfig$experiment !== void 0 && _getConfig$experiment.enabled) {
94
+ var _this$vcObserver2;
95
+ (_this$vcObserver2 = this.vcObserver) === null || _this$vcObserver2 === void 0 ? void 0 : _this$vcObserver2.stop();
96
+ }
92
97
  return;
93
98
  }
99
+ const postInteractionFinishVCResult = (_this$vcObserver3 = this.vcObserver) === null || _this$vcObserver3 === void 0 ? void 0 : _this$vcObserver3.getVCResult({
100
+ start: this.lastInteractionFinish.start,
101
+ stop: performance.now(),
102
+ tti: -1,
103
+ // no need for TTI value here
104
+ prefix: 'ufo',
105
+ ...this.vcObserverSSRConfig
106
+ });
107
+ if ((_getConfig2 = getConfig()) !== null && _getConfig2 !== void 0 && (_getConfig2$experimen = _getConfig2.experimentalInteractionMetrics) !== null && _getConfig2$experimen !== void 0 && _getConfig2$experimen.enabled) {
108
+ var _this$vcObserver4;
109
+ (_this$vcObserver4 = this.vcObserver) === null || _this$vcObserver4 === void 0 ? void 0 : _this$vcObserver4.stop();
110
+ }
94
111
  this.sinkHandlerFn({
95
112
  lastInteractionFinish: this.lastInteractionFinish,
96
113
  reactProfilerTimings: this.reactProfilerTimings,
97
114
  // NOTE: invoking `getVCResult` at latest possible point in time here (not earlier) to get the most accurate result (from performance.now())
98
- postInteractionFinishVCResult: (_this$vcObserver2 = this.vcObserver) === null || _this$vcObserver2 === void 0 ? void 0 : _this$vcObserver2.getVCResult({
99
- start: this.lastInteractionFinish.start,
100
- stop: performance.now(),
101
- tti: -1,
102
- // no need for TTI value here
103
- prefix: 'ufo',
104
- ...this.vcObserverSSRConfig
105
- }),
115
+ postInteractionFinishVCResult,
106
116
  lastInteractionFinishVCResult: this.lastInteractionFinishVCResult
107
117
  });
108
118
  this.reset();
@@ -125,7 +135,7 @@ export default class PostInteractionLog {
125
135
  experimentalTTAI,
126
136
  experimentalVC90
127
137
  }) {
128
- var _getConfig;
138
+ var _getConfig3;
129
139
  this.lastInteractionFinish = {
130
140
  ufoName,
131
141
  start,
@@ -138,7 +148,7 @@ export default class PostInteractionLog {
138
148
  experimentalTTAI,
139
149
  experimentalVC90
140
150
  };
141
- const timeout = ((_getConfig = getConfig()) === null || _getConfig === void 0 ? void 0 : _getConfig.timeWindowForLateMutationsInMilliseconds) || POST_INTERACTION_LOG_SEND_DEFAULT_TIMEOUT;
151
+ const timeout = ((_getConfig3 = getConfig()) === null || _getConfig3 === void 0 ? void 0 : _getConfig3.timeWindowForLateMutationsInMilliseconds) || POST_INTERACTION_LOG_SEND_DEFAULT_TIMEOUT;
142
152
  this.sinkTimeoutId = window.setTimeout(() => {
143
153
  this.sendPostInteractionLog();
144
154
  }, timeout);