@atlaskit/react-ufo 3.3.2 → 3.3.3

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 +8 -0
  2. package/dist/cjs/create-payload/index.js +43 -15
  3. package/dist/cjs/interaction-metrics-init/index.js +11 -9
  4. package/dist/cjs/vc/index.js +6 -2
  5. package/dist/cjs/vc/vc-observer-new/get-element-name.js +19 -6
  6. package/dist/cjs/vc/vc-observer-new/index.js +6 -3
  7. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +4 -2
  8. package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +10 -11
  9. package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/index.js +23 -30
  10. package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/heatmap/index.js +7 -7
  11. package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/rect-sweeping-line/index.js +3 -3
  12. package/dist/cjs/vc/vc-observer-new/window-event-observer/index.js +5 -1
  13. package/dist/es2019/create-payload/index.js +3 -2
  14. package/dist/es2019/interaction-metrics-init/index.js +11 -9
  15. package/dist/es2019/vc/index.js +6 -2
  16. package/dist/es2019/vc/vc-observer-new/get-element-name.js +19 -6
  17. package/dist/es2019/vc/vc-observer-new/index.js +7 -3
  18. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +4 -0
  19. package/dist/es2019/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +1 -2
  20. package/dist/es2019/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/index.js +15 -12
  21. package/dist/es2019/vc/vc-observer-new/metric-calculator/percentile-calc/heatmap/index.js +5 -4
  22. package/dist/es2019/vc/vc-observer-new/metric-calculator/percentile-calc/rect-sweeping-line/index.js +3 -2
  23. package/dist/es2019/vc/vc-observer-new/window-event-observer/index.js +5 -1
  24. package/dist/esm/create-payload/index.js +43 -15
  25. package/dist/esm/interaction-metrics-init/index.js +11 -9
  26. package/dist/esm/vc/index.js +6 -2
  27. package/dist/esm/vc/vc-observer-new/get-element-name.js +19 -6
  28. package/dist/esm/vc/vc-observer-new/index.js +6 -3
  29. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +4 -2
  30. package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +10 -11
  31. package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/index.js +23 -30
  32. package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/heatmap/index.js +7 -7
  33. package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/rect-sweeping-line/index.js +3 -3
  34. package/dist/esm/vc/vc-observer-new/window-event-observer/index.js +5 -1
  35. package/dist/types/config/index.d.ts +1 -0
  36. package/dist/types/create-payload/index.d.ts +1 -1
  37. package/dist/types/vc/vc-observer-new/index.d.ts +3 -2
  38. package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  39. package/dist/types/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/index.d.ts +2 -2
  40. package/dist/types/vc/vc-observer-new/metric-calculator/percentile-calc/heatmap/index.d.ts +2 -1
  41. package/dist/types/vc/vc-observer-new/metric-calculator/percentile-calc/rect-sweeping-line/index.d.ts +2 -1
  42. package/dist/types/vc/vc-observer-new/metric-calculator/percentile-calc/types.d.ts +2 -0
  43. package/dist/types/vc/vc-observer-new/metric-calculator/types.d.ts +2 -0
  44. package/dist/types-ts4.5/config/index.d.ts +1 -0
  45. package/dist/types-ts4.5/create-payload/index.d.ts +1 -1
  46. package/dist/types-ts4.5/vc/vc-observer-new/index.d.ts +3 -2
  47. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  48. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/index.d.ts +2 -2
  49. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/percentile-calc/heatmap/index.d.ts +2 -1
  50. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/percentile-calc/rect-sweeping-line/index.d.ts +2 -1
  51. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/percentile-calc/types.d.ts +2 -0
  52. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/types.d.ts +2 -0
  53. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/ufo-interaction-ignore
2
2
 
3
+ ## 3.3.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#123538](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/123538)
8
+ [`2dd75c16ca0c4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2dd75c16ca0c4) -
9
+ fix handling of potentially invalid selectors in TTVC v3
10
+
3
11
  ## 3.3.2
4
12
 
5
13
  ### Patch Changes
@@ -838,19 +838,47 @@ function _createPayloads() {
838
838
  }));
839
839
  return _createPayloads.apply(this, arguments);
840
840
  }
841
- function createExperimentalMetricsPayload(interactionId, interaction) {
842
- var config = (0, _config.getConfig)();
843
- if (!config) {
844
- throw Error('UFO Configuration not provided');
845
- }
846
- var ufoName = (0, _utils.sanitizeUfoName)(interaction.ufoName);
847
- var rate = (0, _config.getExperimentalInteractionRate)(ufoName, interaction.type);
848
- if (!(0, _coinflip.default)(rate)) {
849
- return null;
850
- }
851
- var pageVisibilityState = (0, _hiddenTiming.getPageVisibilityState)(interaction.start, interaction.end);
852
- if (pageVisibilityState !== 'visible') {
853
- return null;
854
- }
855
- return createInteractionMetricsPayload(interaction, interactionId, true);
841
+ function createExperimentalMetricsPayload(_x6, _x7) {
842
+ return _createExperimentalMetricsPayload.apply(this, arguments);
843
+ }
844
+ function _createExperimentalMetricsPayload() {
845
+ _createExperimentalMetricsPayload = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(interactionId, interaction) {
846
+ var config, ufoName, rate, pageVisibilityState, result;
847
+ return _regenerator.default.wrap(function _callee3$(_context3) {
848
+ while (1) switch (_context3.prev = _context3.next) {
849
+ case 0:
850
+ config = (0, _config.getConfig)();
851
+ if (config) {
852
+ _context3.next = 3;
853
+ break;
854
+ }
855
+ throw Error('UFO Configuration not provided');
856
+ case 3:
857
+ ufoName = (0, _utils.sanitizeUfoName)(interaction.ufoName);
858
+ rate = (0, _config.getExperimentalInteractionRate)(ufoName, interaction.type);
859
+ if ((0, _coinflip.default)(rate)) {
860
+ _context3.next = 7;
861
+ break;
862
+ }
863
+ return _context3.abrupt("return", null);
864
+ case 7:
865
+ pageVisibilityState = (0, _hiddenTiming.getPageVisibilityState)(interaction.start, interaction.end);
866
+ if (!(pageVisibilityState !== 'visible')) {
867
+ _context3.next = 10;
868
+ break;
869
+ }
870
+ return _context3.abrupt("return", null);
871
+ case 10:
872
+ _context3.next = 12;
873
+ return createInteractionMetricsPayload(interaction, interactionId, true);
874
+ case 12:
875
+ result = _context3.sent;
876
+ return _context3.abrupt("return", result);
877
+ case 14:
878
+ case "end":
879
+ return _context3.stop();
880
+ }
881
+ }, _callee3);
882
+ }));
883
+ return _createExperimentalMetricsPayload.apply(this, arguments);
856
884
  }
@@ -39,17 +39,19 @@ function sinkInteraction(instance, payloadPackage) {
39
39
  function sinkExperimentalInteractionMetrics(instance, payloadPackage) {
40
40
  (0, _createExperimentalInteractionMetricsPayload.sinkExperimentalHandler)(function (interactionId, interaction) {
41
41
  (0, _scheduler.unstable_scheduleCallback)(_scheduler.unstable_IdlePriority, function () {
42
- var payload = payloadPackage.createExperimentalMetricsPayload(interactionId, interaction);
43
- if (payload) {
44
- if ((0, _platformFeatureFlags.fg)('enable_ufo_devtools_api_for_extra_events')) {
45
- // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
46
- var devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
47
- if (typeof devToolObserver === 'function') {
48
- devToolObserver === null || devToolObserver === void 0 || devToolObserver(payload);
42
+ var payloadPromise = payloadPackage.createExperimentalMetricsPayload(interactionId, interaction);
43
+ payloadPromise.then(function (payload) {
44
+ if (payload) {
45
+ if ((0, _platformFeatureFlags.fg)('enable_ufo_devtools_api_for_extra_events')) {
46
+ // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
47
+ var devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
48
+ if (typeof devToolObserver === 'function') {
49
+ devToolObserver === null || devToolObserver === void 0 || devToolObserver(payload);
50
+ }
49
51
  }
52
+ instance.sendOperationalEvent(payload);
50
53
  }
51
- instance.sendOperationalEvent(payload);
52
- }
54
+ });
53
55
  });
54
56
  });
55
57
  }
@@ -12,17 +12,19 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
12
12
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
13
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
14
14
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
+ var _config = require("../config");
15
16
  var _vcObserver = require("./vc-observer");
16
17
  var _vcObserverNew = _interopRequireDefault(require("./vc-observer-new"));
17
18
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
19
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
19
20
  var VCObserverWrapper = /*#__PURE__*/function () {
20
21
  function VCObserverWrapper() {
22
+ var _getConfig;
21
23
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
22
24
  (0, _classCallCheck2.default)(this, VCObserverWrapper);
23
25
  this.oldVCObserver = new _vcObserver.VCObserver(opts);
24
26
  this.newVCObserver = null;
25
- var isNewVCObserverEnabled = (0, _platformFeatureFlags.fg)('platform_ufo_vc_observer_new');
27
+ var isNewVCObserverEnabled = (0, _platformFeatureFlags.fg)('platform_ufo_vc_observer_new') || ((_getConfig = (0, _config.getConfig)()) === null || _getConfig === void 0 || (_getConfig = _getConfig.vc) === null || _getConfig === void 0 ? void 0 : _getConfig.enableVCObserverNew);
26
28
  if (isNewVCObserverEnabled) {
27
29
  this.newVCObserver = new _vcObserverNew.default({
28
30
  selectorConfig: opts.selectorConfig
@@ -34,7 +36,9 @@ var VCObserverWrapper = /*#__PURE__*/function () {
34
36
  value: function start(startArg) {
35
37
  var _this$oldVCObserver, _this$newVCObserver;
36
38
  (_this$oldVCObserver = this.oldVCObserver) === null || _this$oldVCObserver === void 0 || _this$oldVCObserver.start(startArg);
37
- (_this$newVCObserver = this.newVCObserver) === null || _this$newVCObserver === void 0 || _this$newVCObserver.start();
39
+ (_this$newVCObserver = this.newVCObserver) === null || _this$newVCObserver === void 0 || _this$newVCObserver.start({
40
+ startTime: startArg.startTime
41
+ });
38
42
  }
39
43
  }, {
40
44
  key: "stop",
@@ -10,7 +10,15 @@ function getAttributeSelector(element, attributeName) {
10
10
  if (!attrValue) {
11
11
  return '';
12
12
  }
13
- return "[".concat(attributeName, "=\"").concat(encodeURIComponent(attrValue), "\"]");
13
+ return "[".concat(attributeName, "=\"").concat(attrValue, "\"]");
14
+ }
15
+ function isValidSelector(selector) {
16
+ try {
17
+ document.querySelector(selector);
18
+ return true;
19
+ } catch (err) {
20
+ return false;
21
+ }
14
22
  }
15
23
  function isSelectorUnique(selector) {
16
24
  return document.querySelectorAll(selector).length === 1;
@@ -18,11 +26,13 @@ function isSelectorUnique(selector) {
18
26
  function getUniqueSelector(selectorConfig, element) {
19
27
  var currentElement = element;
20
28
  var parts = [];
21
- while (currentElement && currentElement.localName !== 'body') {
29
+ var MAX_DEPTH = 3;
30
+ var currentDepth = 0;
31
+ while (currentElement && currentElement.localName !== 'body' && currentDepth <= MAX_DEPTH) {
22
32
  var tagName = currentElement.localName;
23
33
  var selectorPart = tagName;
24
- if (selectorConfig.id && currentElement.id) {
25
- selectorPart += "#".concat(encodeURIComponent(currentElement.id));
34
+ if (selectorConfig.id && currentElement.id && isValidSelector("#".concat(currentElement.id))) {
35
+ selectorPart += "#".concat(currentElement.id);
26
36
  } else if (selectorConfig.dataVC) {
27
37
  selectorPart += getAttributeSelector(currentElement, 'data-vc');
28
38
  } else if (selectorConfig.testId) {
@@ -30,9 +40,11 @@ function getUniqueSelector(selectorConfig, element) {
30
40
  } else if (selectorConfig.role) {
31
41
  selectorPart += getAttributeSelector(currentElement, 'role');
32
42
  } else if (selectorConfig.className && currentElement.className) {
33
- var classNames = Array.from(currentElement.classList).map(encodeURIComponent).join('.');
43
+ var classNames = Array.from(currentElement.classList).join('.');
34
44
  if (classNames) {
35
- selectorPart += ".".concat(classNames);
45
+ if (isValidSelector(".".concat(classNames))) {
46
+ selectorPart += ".".concat(classNames);
47
+ }
36
48
  }
37
49
  }
38
50
  parts.unshift(selectorPart);
@@ -41,6 +53,7 @@ function getUniqueSelector(selectorConfig, element) {
41
53
  return _potentialSelector;
42
54
  }
43
55
  currentElement = currentElement.parentElement;
56
+ currentDepth++;
44
57
  }
45
58
  var potentialSelector = parts.join(' > ').trim();
46
59
  if (!potentialSelector) {
@@ -27,7 +27,6 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
27
27
  var _config$selectorConfi,
28
28
  _this = this;
29
29
  (0, _classCallCheck2.default)(this, VCObserverNew);
30
- (0, _defineProperty2.default)(this, "startTime", 0);
31
30
  (0, _defineProperty2.default)(this, "viewportObserver", null);
32
31
  (0, _defineProperty2.default)(this, "windowEventObserver", null);
33
32
  this.entriesTimeline = new _entriesTimeline.default();
@@ -75,10 +74,12 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
75
74
  }
76
75
  return (0, _createClass2.default)(VCObserverNew, [{
77
76
  key: "start",
78
- value: function start() {
77
+ value: function start(_ref2) {
79
78
  var _this$viewportObserve, _this$windowEventObse;
79
+ var startTime = _ref2.startTime;
80
80
  (_this$viewportObserve = this.viewportObserver) === null || _this$viewportObserve === void 0 || _this$viewportObserve.start();
81
81
  (_this$windowEventObse = this.windowEventObserver) === null || _this$windowEventObse === void 0 || _this$windowEventObse.start();
82
+ this.entriesTimeline.clear();
82
83
  }
83
84
  }, {
84
85
  key: "stop",
@@ -104,7 +105,9 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
104
105
  });
105
106
  _context.next = 6;
106
107
  return calculator_fy25_03.calculate({
107
- orderedEntries: orderedEntries
108
+ orderedEntries: orderedEntries,
109
+ startTime: start,
110
+ stopTime: stop
108
111
  });
109
112
  case 6:
110
113
  fy25_03 = _context.sent;
@@ -24,11 +24,11 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
24
24
  var _this = this,
25
25
  _vcDetails$90$t,
26
26
  _vcDetails$;
27
- var orderedEntries, filteredEntries, isVCClean, vcDetails;
27
+ var startTime, stopTime, orderedEntries, filteredEntries, isVCClean, vcDetails;
28
28
  return _regenerator.default.wrap(function _callee$(_context) {
29
29
  while (1) switch (_context.prev = _context.next) {
30
30
  case 0:
31
- orderedEntries = _ref.orderedEntries;
31
+ startTime = _ref.startTime, stopTime = _ref.stopTime, orderedEntries = _ref.orderedEntries;
32
32
  filteredEntries = orderedEntries.filter(function (entry) {
33
33
  return _this.isEntryIncluded(entry);
34
34
  });
@@ -49,6 +49,8 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
49
49
  width: (0, _getViewportWidth.default)(),
50
50
  height: (0, _getViewportHeight.default)()
51
51
  },
52
+ startTime: startTime,
53
+ stopTime: stopTime,
52
54
  orderedEntries: filteredEntries,
53
55
  percentiles: [25, 50, 75, 80, 85, 90, 95, 98, 99]
54
56
  });
@@ -228,17 +228,16 @@ function calculateDrawnPixelsRaw(_x, _x2, _x3) {
228
228
  }
229
229
  function _calculateDrawnPixelsRaw() {
230
230
  _calculateDrawnPixelsRaw = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(imageData, scaleFactor, arraySize) {
231
- var data, scaleCompensation, arr, i, color, colorIndex;
231
+ var data, arr, i, color, colorIndex;
232
232
  return _regenerator.default.wrap(function _callee2$(_context2) {
233
233
  while (1) switch (_context2.prev = _context2.next) {
234
234
  case 0:
235
235
  data = imageData.data;
236
- scaleCompensation = Math.round(1 / (scaleFactor * scaleFactor));
237
236
  arr = new Uint32Array(arraySize);
238
237
  i = 0;
239
- case 4:
238
+ case 3:
240
239
  if (!(i < data.length)) {
241
- _context2.next = 12;
240
+ _context2.next = 11;
242
241
  break;
243
242
  }
244
243
  // Check alpha
@@ -250,21 +249,21 @@ function _calculateDrawnPixelsRaw() {
250
249
  // The | operator combines all bits together
251
250
  color = data[i] << 16 | data[i + 1] << 8 | data[i + 2];
252
251
  colorIndex = color - 1;
253
- arr[colorIndex] = (arr[colorIndex] || 0) + scaleCompensation;
252
+ arr[colorIndex] = (arr[colorIndex] || 0) + 1;
254
253
  }
255
254
  if (!(i % 10000 === 0)) {
256
- _context2.next = 9;
255
+ _context2.next = 8;
257
256
  break;
258
257
  }
259
- _context2.next = 9;
258
+ _context2.next = 8;
260
259
  return (0, _taskYield.default)();
261
- case 9:
260
+ case 8:
262
261
  i += 4;
263
- _context2.next = 4;
262
+ _context2.next = 3;
264
263
  break;
265
- case 12:
264
+ case 11:
266
265
  return _context2.abrupt("return", arr);
267
- case 13:
266
+ case 12:
268
267
  case "end":
269
268
  return _context2.stop();
270
269
  }
@@ -19,22 +19,22 @@ function calculateTTVCPercentiles(_x) {
19
19
  }
20
20
  function _calculateTTVCPercentiles() {
21
21
  _calculateTTVCPercentiles = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref) {
22
- var viewport, orderedEntries, percentiles, canvas, elementMap, _iterator3, _step3, entry, rect, elementName, timePixelCounts, viewportTotalPixels;
22
+ var viewport, orderedEntries, percentiles, startTime, canvas, elementMap, _iterator2, _step2, entry, rect, elementName, timePixelCounts, canvasDimenstions, totalPixels;
23
23
  return _regenerator.default.wrap(function _callee$(_context) {
24
24
  while (1) switch (_context.prev = _context.next) {
25
25
  case 0:
26
- viewport = _ref.viewport, orderedEntries = _ref.orderedEntries, percentiles = _ref.percentiles;
26
+ viewport = _ref.viewport, orderedEntries = _ref.orderedEntries, percentiles = _ref.percentiles, startTime = _ref.startTime;
27
27
  canvas = new _canvasPixel.ViewportCanvas(viewport, (0, _platformFeatureFlags.fg)('platform_ufo_canvas_heatmap_full_precision') ? 1 : 0.25);
28
28
  elementMap = new Map();
29
- _iterator3 = _createForOfIteratorHelper(orderedEntries);
29
+ _iterator2 = _createForOfIteratorHelper(orderedEntries);
30
30
  _context.prev = 4;
31
- _iterator3.s();
31
+ _iterator2.s();
32
32
  case 6:
33
- if ((_step3 = _iterator3.n()).done) {
33
+ if ((_step2 = _iterator2.n()).done) {
34
34
  _context.next = 17;
35
35
  break;
36
36
  }
37
- entry = _step3.value;
37
+ entry = _step2.value;
38
38
  if ('rect' in entry.data) {
39
39
  _context.next = 10;
40
40
  break;
@@ -57,19 +57,20 @@ function _calculateTTVCPercentiles() {
57
57
  case 19:
58
58
  _context.prev = 19;
59
59
  _context.t0 = _context["catch"](4);
60
- _iterator3.e(_context.t0);
60
+ _iterator2.e(_context.t0);
61
61
  case 22:
62
62
  _context.prev = 22;
63
- _iterator3.f();
63
+ _iterator2.f();
64
64
  return _context.finish(22);
65
65
  case 25:
66
66
  _context.next = 27;
67
67
  return canvas.getPixelCounts();
68
68
  case 27:
69
69
  timePixelCounts = _context.sent;
70
- viewportTotalPixels = viewport.width * viewport.height;
71
- return _context.abrupt("return", calculatePercentiles(timePixelCounts, elementMap, percentiles, viewportTotalPixels));
72
- case 30:
70
+ canvasDimenstions = canvas.getScaledDimensions();
71
+ totalPixels = canvasDimenstions.width * canvasDimenstions.height;
72
+ return _context.abrupt("return", calculatePercentiles(timePixelCounts, elementMap, percentiles, totalPixels, startTime));
73
+ case 31:
73
74
  case "end":
74
75
  return _context.stop();
75
76
  }
@@ -77,7 +78,7 @@ function _calculateTTVCPercentiles() {
77
78
  }));
78
79
  return _calculateTTVCPercentiles.apply(this, arguments);
79
80
  }
80
- function calculatePercentiles(timePixelCounts, elementMap, unorderedPercentiles, totalPixels) {
81
+ function calculatePercentiles(timePixelCounts, elementMap, unorderedPercentiles, totalPixels, startTime) {
81
82
  var results = {};
82
83
  var cumulativePixels = 0;
83
84
  var percentiles = unorderedPercentiles.sort(function (a, b) {
@@ -110,7 +111,7 @@ function calculatePercentiles(timePixelCounts, elementMap, unorderedPercentiles,
110
111
  var matchesAnyCheckpoints = false;
111
112
  while (percentileIndex < percentiles.length && percentCovered >= percentiles[percentileIndex]) {
112
113
  results["".concat(percentiles[percentileIndex])] = {
113
- t: Number(time),
114
+ t: Math.round(Number(time - startTime)),
114
115
  e: Array.from(domElementsBuffer)
115
116
  };
116
117
  percentileIndex++;
@@ -123,29 +124,21 @@ function calculatePercentiles(timePixelCounts, elementMap, unorderedPercentiles,
123
124
  break;
124
125
  }
125
126
  }
126
-
127
- // Fill in any missing percentiles
128
127
  } catch (err) {
129
128
  _iterator.e(err);
130
129
  } finally {
131
130
  _iterator.f();
132
131
  }
133
- var _iterator2 = _createForOfIteratorHelper(percentiles),
134
- _step2;
135
- try {
136
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
137
- var percentile = _step2.value;
138
- if (!(percentile in results)) {
139
- results["".concat(percentile)] = {
140
- t: 0,
141
- e: []
142
- };
143
- }
132
+ var previousResult = {
133
+ t: 0,
134
+ e: []
135
+ };
136
+ for (var i = 0; i < percentiles.length; i++) {
137
+ var percentile = percentiles[i];
138
+ if (!(percentile in results)) {
139
+ results["".concat(percentile)] = previousResult;
144
140
  }
145
- } catch (err) {
146
- _iterator2.e(err);
147
- } finally {
148
- _iterator2.f();
141
+ previousResult = results["".concat(percentile)];
149
142
  }
150
143
  return results;
151
144
  }
@@ -243,7 +243,7 @@ var Heatmap = /*#__PURE__*/function () {
243
243
  }, {
244
244
  key: "getVCPercentMetrics",
245
245
  value: function () {
246
- var _getVCPercentMetrics = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(vcPercentCheckpoint) {
246
+ var _getVCPercentMetrics = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(vcPercentCheckpoint, startTime) {
247
247
  var sortedCheckpoints, flattenHeatmap, totalCells, timestampMap, i, _cellHead$time, _timestampMap$get, cell, cellHead, timestamp, elementName, curr, sortedTimings, totalCellPainted, result, domElementsBuffer, _i, _timestamp, timestampInfo, cellCount, domElements, currVCRatio, currVCPercent, matchesAnyCheckpoints, checkpoint, _domElements;
248
248
  return _regenerator.default.wrap(function _callee2$(_context2) {
249
249
  while (1) switch (_context2.prev = _context2.next) {
@@ -331,7 +331,7 @@ var Heatmap = /*#__PURE__*/function () {
331
331
  case 41:
332
332
  matchesAnyCheckpoints = true;
333
333
  result[checkpoint.toString()] = {
334
- t: _timestamp,
334
+ t: Math.round(_timestamp - startTime),
335
335
  e: _domElements
336
336
  };
337
337
  _context2.next = 36;
@@ -358,23 +358,23 @@ var Heatmap = /*#__PURE__*/function () {
358
358
  }
359
359
  }, _callee2, this);
360
360
  }));
361
- function getVCPercentMetrics(_x2) {
361
+ function getVCPercentMetrics(_x2, _x3) {
362
362
  return _getVCPercentMetrics.apply(this, arguments);
363
363
  }
364
364
  return getVCPercentMetrics;
365
365
  }()
366
366
  }]);
367
367
  }();
368
- function calculateTTVCPercentiles(_x3) {
368
+ function calculateTTVCPercentiles(_x4) {
369
369
  return _calculateTTVCPercentiles.apply(this, arguments);
370
370
  }
371
371
  function _calculateTTVCPercentiles() {
372
372
  _calculateTTVCPercentiles = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(_ref2) {
373
- var orderedEntries, viewport, percentiles, heatmap, vcDetails;
373
+ var orderedEntries, viewport, percentiles, startTime, heatmap, vcDetails;
374
374
  return _regenerator.default.wrap(function _callee3$(_context3) {
375
375
  while (1) switch (_context3.prev = _context3.next) {
376
376
  case 0:
377
- orderedEntries = _ref2.orderedEntries, viewport = _ref2.viewport, percentiles = _ref2.percentiles;
377
+ orderedEntries = _ref2.orderedEntries, viewport = _ref2.viewport, percentiles = _ref2.percentiles, startTime = _ref2.startTime;
378
378
  heatmap = new Heatmap({
379
379
  viewport: viewport,
380
380
  heatmapSize: 200
@@ -383,7 +383,7 @@ function _calculateTTVCPercentiles() {
383
383
  return heatmap.applyEntriesToHeatmap(orderedEntries);
384
384
  case 4:
385
385
  _context3.next = 6;
386
- return heatmap.getVCPercentMetrics(percentiles);
386
+ return heatmap.getVCPercentMetrics(percentiles, startTime);
387
387
  case 6:
388
388
  vcDetails = _context3.sent;
389
389
  return _context3.abrupt("return", vcDetails);
@@ -16,11 +16,11 @@ function calculateTTVCPercentiles(_x) {
16
16
  }
17
17
  function _calculateTTVCPercentiles() {
18
18
  _calculateTTVCPercentiles = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref) {
19
- var orderedEntries, viewport, percentiles, sortedPercentiles, viewportArea, checkpoints, activeRects, removeActiveRect, domElementsBuffer, i, iEntry, iEntryData, rect, elementName, exclusionArea, currentArea, currVCPercent, matchesAnyCheckpoints, _checkpoint, domElements;
19
+ var orderedEntries, viewport, percentiles, startTime, sortedPercentiles, viewportArea, checkpoints, activeRects, removeActiveRect, domElementsBuffer, i, iEntry, iEntryData, rect, elementName, exclusionArea, currentArea, currVCPercent, matchesAnyCheckpoints, _checkpoint, domElements;
20
20
  return _regenerator.default.wrap(function _callee$(_context) {
21
21
  while (1) switch (_context.prev = _context.next) {
22
22
  case 0:
23
- orderedEntries = _ref.orderedEntries, viewport = _ref.viewport, percentiles = _ref.percentiles;
23
+ orderedEntries = _ref.orderedEntries, viewport = _ref.viewport, percentiles = _ref.percentiles, startTime = _ref.startTime;
24
24
  sortedPercentiles = (0, _toConsumableArray2.default)(percentiles).sort(function (a, b) {
25
25
  return a - b;
26
26
  });
@@ -76,7 +76,7 @@ function _calculateTTVCPercentiles() {
76
76
  case 25:
77
77
  matchesAnyCheckpoints = true;
78
78
  checkpoints[_checkpoint.toString()] = {
79
- t: iEntry.time,
79
+ t: Math.round(iEntry.time - startTime),
80
80
  e: domElements
81
81
  };
82
82
  _context.next = 20;
@@ -22,6 +22,9 @@ var WindowEventObserver = exports.default = /*#__PURE__*/function () {
22
22
  var unbindCallback = (0, _bindEventListener.bind)(window, {
23
23
  type: type,
24
24
  listener: function listener(event) {
25
+ if (!event.isTrusted) {
26
+ return;
27
+ }
25
28
  _this.onEvent({
26
29
  time: event.timeStamp,
27
30
  type: type,
@@ -29,7 +32,8 @@ var WindowEventObserver = exports.default = /*#__PURE__*/function () {
29
32
  });
30
33
  },
31
34
  options: {
32
- passive: true
35
+ passive: true,
36
+ once: true
33
37
  }
34
38
  });
35
39
  this.unbindFns.push(unbindCallback);
@@ -817,7 +817,7 @@ export async function createPayloads(interactionId, interaction) {
817
817
  const interactionMetricsPayload = await createInteractionMetricsPayload(modifiedInteraction, interactionId);
818
818
  return [interactionMetricsPayload];
819
819
  }
820
- export function createExperimentalMetricsPayload(interactionId, interaction) {
820
+ export async function createExperimentalMetricsPayload(interactionId, interaction) {
821
821
  const config = getConfig();
822
822
  if (!config) {
823
823
  throw Error('UFO Configuration not provided');
@@ -831,5 +831,6 @@ export function createExperimentalMetricsPayload(interactionId, interaction) {
831
831
  if (pageVisibilityState !== 'visible') {
832
832
  return null;
833
833
  }
834
- return createInteractionMetricsPayload(interaction, interactionId, true);
834
+ const result = await createInteractionMetricsPayload(interaction, interactionId, true);
835
+ return result;
835
836
  }
@@ -28,17 +28,19 @@ function sinkInteraction(instance, payloadPackage) {
28
28
  function sinkExperimentalInteractionMetrics(instance, payloadPackage) {
29
29
  sinkExperimentalHandler((interactionId, interaction) => {
30
30
  scheduleCallback(idlePriority, () => {
31
- const payload = payloadPackage.createExperimentalMetricsPayload(interactionId, interaction);
32
- if (payload) {
33
- if (fg('enable_ufo_devtools_api_for_extra_events')) {
34
- // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
35
- const devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
36
- if (typeof devToolObserver === 'function') {
37
- devToolObserver === null || devToolObserver === void 0 ? void 0 : devToolObserver(payload);
31
+ const payloadPromise = payloadPackage.createExperimentalMetricsPayload(interactionId, interaction);
32
+ payloadPromise.then(payload => {
33
+ if (payload) {
34
+ if (fg('enable_ufo_devtools_api_for_extra_events')) {
35
+ // NOTE: This API is used by the UFO DevTool Chrome Extension and Criterion
36
+ const devToolObserver = globalThis.__ufo_devtool_onUfoPayload;
37
+ if (typeof devToolObserver === 'function') {
38
+ devToolObserver === null || devToolObserver === void 0 ? void 0 : devToolObserver(payload);
39
+ }
38
40
  }
41
+ instance.sendOperationalEvent(payload);
39
42
  }
40
- instance.sendOperationalEvent(payload);
41
- }
43
+ });
42
44
  });
43
45
  });
44
46
  }
@@ -1,11 +1,13 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags';
2
+ import { getConfig } from '../config';
2
3
  import { VCObserver } from './vc-observer';
3
4
  import VCObserverNew from './vc-observer-new';
4
5
  class VCObserverWrapper {
5
6
  constructor(opts = {}) {
7
+ var _getConfig, _getConfig$vc;
6
8
  this.oldVCObserver = new VCObserver(opts);
7
9
  this.newVCObserver = null;
8
- const isNewVCObserverEnabled = fg('platform_ufo_vc_observer_new');
10
+ const isNewVCObserverEnabled = fg('platform_ufo_vc_observer_new') || ((_getConfig = getConfig()) === null || _getConfig === void 0 ? void 0 : (_getConfig$vc = _getConfig.vc) === null || _getConfig$vc === void 0 ? void 0 : _getConfig$vc.enableVCObserverNew);
9
11
  if (isNewVCObserverEnabled) {
10
12
  this.newVCObserver = new VCObserverNew({
11
13
  selectorConfig: opts.selectorConfig
@@ -15,7 +17,9 @@ class VCObserverWrapper {
15
17
  start(startArg) {
16
18
  var _this$oldVCObserver, _this$newVCObserver;
17
19
  (_this$oldVCObserver = this.oldVCObserver) === null || _this$oldVCObserver === void 0 ? void 0 : _this$oldVCObserver.start(startArg);
18
- (_this$newVCObserver = this.newVCObserver) === null || _this$newVCObserver === void 0 ? void 0 : _this$newVCObserver.start();
20
+ (_this$newVCObserver = this.newVCObserver) === null || _this$newVCObserver === void 0 ? void 0 : _this$newVCObserver.start({
21
+ startTime: startArg.startTime
22
+ });
19
23
  }
20
24
  stop() {
21
25
  var _this$oldVCObserver2, _this$newVCObserver2;
@@ -4,7 +4,15 @@ function getAttributeSelector(element, attributeName) {
4
4
  if (!attrValue) {
5
5
  return '';
6
6
  }
7
- return `[${attributeName}="${encodeURIComponent(attrValue)}"]`;
7
+ return `[${attributeName}="${attrValue}"]`;
8
+ }
9
+ function isValidSelector(selector) {
10
+ try {
11
+ document.querySelector(selector);
12
+ return true;
13
+ } catch (err) {
14
+ return false;
15
+ }
8
16
  }
9
17
  function isSelectorUnique(selector) {
10
18
  return document.querySelectorAll(selector).length === 1;
@@ -12,11 +20,13 @@ function isSelectorUnique(selector) {
12
20
  function getUniqueSelector(selectorConfig, element) {
13
21
  let currentElement = element;
14
22
  const parts = [];
15
- while (currentElement && currentElement.localName !== 'body') {
23
+ const MAX_DEPTH = 3;
24
+ let currentDepth = 0;
25
+ while (currentElement && currentElement.localName !== 'body' && currentDepth <= MAX_DEPTH) {
16
26
  const tagName = currentElement.localName;
17
27
  let selectorPart = tagName;
18
- if (selectorConfig.id && currentElement.id) {
19
- selectorPart += `#${encodeURIComponent(currentElement.id)}`;
28
+ if (selectorConfig.id && currentElement.id && isValidSelector(`#${currentElement.id}`)) {
29
+ selectorPart += `#${currentElement.id}`;
20
30
  } else if (selectorConfig.dataVC) {
21
31
  selectorPart += getAttributeSelector(currentElement, 'data-vc');
22
32
  } else if (selectorConfig.testId) {
@@ -24,9 +34,11 @@ function getUniqueSelector(selectorConfig, element) {
24
34
  } else if (selectorConfig.role) {
25
35
  selectorPart += getAttributeSelector(currentElement, 'role');
26
36
  } else if (selectorConfig.className && currentElement.className) {
27
- const classNames = Array.from(currentElement.classList).map(encodeURIComponent).join('.');
37
+ const classNames = Array.from(currentElement.classList).join('.');
28
38
  if (classNames) {
29
- selectorPart += `.${classNames}`;
39
+ if (isValidSelector(`.${classNames}`)) {
40
+ selectorPart += `.${classNames}`;
41
+ }
30
42
  }
31
43
  }
32
44
  parts.unshift(selectorPart);
@@ -35,6 +47,7 @@ function getUniqueSelector(selectorConfig, element) {
35
47
  return potentialSelector;
36
48
  }
37
49
  currentElement = currentElement.parentElement;
50
+ currentDepth++;
38
51
  }
39
52
  const potentialSelector = parts.join(' > ').trim();
40
53
  if (!potentialSelector) {