@atlaskit/react-ufo 4.15.4 → 4.15.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/create-payload/index.js +6 -4
  3. package/dist/cjs/vc/vc-observer/observers/ssr-placeholders/index.js +7 -0
  4. package/dist/cjs/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  5. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +290 -191
  6. package/dist/cjs/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +45 -2
  7. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/get-mutated-elements.js +15 -4
  8. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-zero-dimension-rectangle.js +9 -0
  9. package/dist/es2019/create-payload/index.js +4 -2
  10. package/dist/es2019/vc/vc-observer/observers/ssr-placeholders/index.js +5 -0
  11. package/dist/es2019/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  12. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +158 -81
  13. package/dist/es2019/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +33 -2
  14. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/get-mutated-elements.js +15 -4
  15. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-zero-dimension-rectangle.js +3 -0
  16. package/dist/esm/create-payload/index.js +6 -4
  17. package/dist/esm/vc/vc-observer/observers/ssr-placeholders/index.js +7 -0
  18. package/dist/esm/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  19. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +288 -189
  20. package/dist/esm/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +45 -2
  21. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/get-mutated-elements.js +15 -4
  22. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-zero-dimension-rectangle.js +3 -0
  23. package/dist/types/vc/vc-observer/observers/ssr-placeholders/index.d.ts +1 -0
  24. package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
  25. package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-zero-dimension-rectangle.d.ts +1 -0
  26. package/dist/types-ts4.5/vc/vc-observer/observers/ssr-placeholders/index.d.ts +1 -0
  27. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
  28. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-zero-dimension-rectangle.d.ts +1 -0
  29. package/package.json +10 -1
@@ -10,9 +10,21 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
10
10
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
11
11
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
12
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
+ function isElementStyledWithDisplayContents(element) {
14
+ var _window2;
15
+ // To minimise calling `getComputedStyle`, we are making an assumption that if an element is from the Entrypoints framework, then it will have `display: contents` styling
16
+ // as per https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/e4ccf437262ef4c0fd3c651ffb7ad4770b15aed4/jira/src/packages/platform/entry-points/entry-point-placeholder/src/index.tsx#lines-136
17
+ if ((0, _platformFeatureFlags.fg)('platform_ufo_detect_entrypoint_parent')) {
18
+ var _window;
19
+ if (element.hasAttribute('data-ep-placeholder-id')) {
20
+ return true;
21
+ }
22
+ return ((_window = window) === null || _window === void 0 || (_window = _window.getComputedStyle(element)) === null || _window === void 0 ? void 0 : _window.display) === 'contents';
23
+ }
24
+ return ((_window2 = window) === null || _window2 === void 0 || (_window2 = _window2.getComputedStyle(element)) === null || _window2 === void 0 ? void 0 : _window2.display) === 'contents';
25
+ }
13
26
  var MAX_NESTED_LEVELS_OF_DISPLAY_CONTENT_ELEMENTS_HANDLED = 3;
14
27
  function getMutatedElements(element) {
15
- var _window;
16
28
  var depthLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
17
29
  if ((0, _platformFeatureFlags.fg)('platform_ufo_disable_vcnext_observations')) {
18
30
  return [{
@@ -20,16 +32,15 @@ function getMutatedElements(element) {
20
32
  isDisplayContentsElementChildren: false
21
33
  }];
22
34
  }
23
- if (((_window = window) === null || _window === void 0 || (_window = _window.getComputedStyle(element)) === null || _window === void 0 ? void 0 : _window.display) === 'contents') {
35
+ if (isElementStyledWithDisplayContents(element)) {
24
36
  var mutatedElements = [];
25
37
  var nestedDisplayContentsElementChildren = [];
26
38
  var _iterator = _createForOfIteratorHelper(element.children),
27
39
  _step;
28
40
  try {
29
41
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
30
- var _window2;
31
42
  var child = _step.value;
32
- if (((_window2 = window) === null || _window2 === void 0 || (_window2 = _window2.getComputedStyle(child)) === null || _window2 === void 0 ? void 0 : _window2.display) === 'contents') {
43
+ if (isElementStyledWithDisplayContents(child)) {
33
44
  nestedDisplayContentsElementChildren.push(child);
34
45
  }
35
46
  mutatedElements.push({
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isZeroDimensionRectangle = isZeroDimensionRectangle;
7
+ function isZeroDimensionRectangle(rect) {
8
+ return rect.bottom === 0 && rect.top === 0 && rect.left === 0 && rect.right === 0 && rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0;
9
+ }
@@ -1,5 +1,5 @@
1
1
  import{getDocument}from'@atlaskit/browser-apis';import{fg}from'@atlaskit/platform-feature-flags';// Import common utilities
2
- import{getLighthouseMetrics}from'../additional-payload';import{CHRReporter}from'../assets';import*as bundleEvalTiming from'../bundle-eval-timing';import coinflip from'../coinflip';import{getConfig,getExperimentalInteractionRate,getUfoNameOverrides}from'../config';import{getExperimentalVCMetrics}from'../create-experimental-interaction-metrics-payload';import{getBm3Timings}from'../custom-timings';import{getGlobalErrorCount}from'../global-error-handler';import{getPageVisibilityState}from'../hidden-timing';import*as initialPageLoadExtraTiming from'../initial-page-load-extra-timing';import{interactionSpans as atlaskitInteractionSpans}from'../interaction-metrics';import{createMemoryStateReport,createPressureStateReport}from'../machine-utilisation';import*as resourceTiming from'../resource-timing';import{filterResourceTimings}from'../resource-timing/common/utils/resource-timing-buffer';import{roundEpsilon}from'../round-number';import*as ssr from'../ssr';import{buildSegmentTree,getOldSegmentsLabelStack,labelStackStartWith,optimizeLabelStack,sanitizeUfoName,stringifyLabelStackFully}from'./common/utils';import{createCriticalMetricsPayloads}from'./critical-metrics-payload';import{addPerformanceMeasures}from'./utils/add-performance-measures';import{getBatteryInfoToLegacyFormat}from'./utils/get-battery-info';import{getBrowserMetadataToLegacyFormat}from'./utils/get-browser-metadata';import getInteractionStatus from'./utils/get-interaction-status';import{getMoreAccuratePageVisibilityUpToTTAI}from'./utils/get-more-accurate-page-visibility-up-to-ttai';import{getNavigationMetricsToLegacyFormat}from'./utils/get-navigation-metrics';import getPageVisibilityUpToTTAI from'./utils/get-page-visibility-up-to-ttai';import{getPaintMetricsToLegacyFormat}from'./utils/get-paint-metrics';import getPayloadSize from'./utils/get-payload-size';import{getReactUFOPayloadVersion}from'./utils/get-react-ufo-payload-version';import getSSRDoneTimeValue from'./utils/get-ssr-done-time-value';import getSSRSuccessUtil from'./utils/get-ssr-success';import getTTAI from'./utils/get-ttai';import getVCMetrics from'./utils/get-vc-metrics';import{getVisibilityStateFromPerformance}from'./utils/get-visibility-state-from-performance';import{optimizeApdex}from'./utils/optimize-apdex';import{optimizeCustomTimings}from'./utils/optimize-custom-timings';import{optimizeHoldInfo}from'./utils/optimize-hold-info';import{optimizeMarks}from'./utils/optimize-marks';import{optimizeReactProfilerTimings}from'./utils/optimize-react-profiler-timings';import{optimizeRequestInfo}from'./utils/optimize-request-info';import{optimizeSpans}from'./utils/optimize-spans';const MAX_PAYLOAD_SIZE=250;function getUfoNameOverride(interaction){const{ufoName,apdex}=interaction;try{const ufoNameOverrides=getUfoNameOverrides();if(ufoNameOverrides!=null){const metricKey=apdex.length>0?apdex[0].key:'';if(ufoNameOverrides[ufoName][metricKey]){return ufoNameOverrides[ufoName][metricKey];}}return ufoName;}catch(e){return ufoName;}}function getEarliestLegacyStopTime(interaction,labelStack){let earliestLegacyStopTime=null;interaction.apdex.forEach(a=>{var _a$labelStack,_earliestLegacyStopTi;if(!(a!==null&&a!==void 0&&a.stopTime)){return;}if(!labelStackStartWith((_a$labelStack=a.labelStack)!==null&&_a$labelStack!==void 0?_a$labelStack:[],labelStack)){return;}if(a.stopTime>interaction.start&&((_earliestLegacyStopTi=earliestLegacyStopTime)!==null&&_earliestLegacyStopTi!==void 0?_earliestLegacyStopTi:a.stopTime)>=a.stopTime){earliestLegacyStopTime=a.stopTime;}});return earliestLegacyStopTime;}function getBm3EndTimeOrFallbackValue(interaction,labelStack=[],fallbackValue=interaction.end){var _getEarliestLegacySto;if(interaction.type==='press'){return fallbackValue;}return(_getEarliestLegacySto=getEarliestLegacyStopTime(interaction,labelStack))!==null&&_getEarliestLegacySto!==void 0?_getEarliestLegacySto:fallbackValue;}function getPageVisibilityUpToTTI(interaction){const{start}=interaction;const bm3EndTimeOrInteractionEndTime=getBm3EndTimeOrFallbackValue(interaction);return getPageVisibilityState(start,bm3EndTimeOrInteractionEndTime);}function getMoreAccuratePageVisibilityUpToTTI(interaction){const old=getPageVisibilityUpToTTI(interaction);const tti=getEarliestLegacyStopTime(interaction,[]);if(!tti){return old;}const buffered=getVisibilityStateFromPerformance(tti);if(!buffered){return old;}if(buffered!==old){return'mixed';}return old;}function getResourceTimings(start,end){var _resourceTiming$getRe;return(_resourceTiming$getRe=resourceTiming.getResourceTimings(start,end))!==null&&_resourceTiming$getRe!==void 0?_resourceTiming$getRe:undefined;}function getBundleEvalTimings(start){return bundleEvalTiming.getBundleEvalTimings(start);}function getSSRPhaseSuccess(type){return type==='page_load'?ssr.getSSRPhaseSuccess():undefined;}function getSSRFeatureFlags(type){return type==='page_load'?ssr.getSSRFeatureFlags():undefined;}function getPPSMetrics(interaction){var _interaction$apdex,_interaction$apdex$;const{start,end}=interaction;const config=getConfig();const interactionStatus=getInteractionStatus(interaction);const pageVisibilityUpToTTAI=getPageVisibilityUpToTTAI(interaction);const 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;const ttai=interactionStatus.originalInteractionStatus==='SUCCEEDED'&&pageVisibilityUpToTTAI==='visible'?Math.round(end-start):undefined;const PPSMetricsAtTTI=tti!==undefined?getLighthouseMetrics({start,stop:tti}):null;const PPSMetricsAtTTAI=ttai!==undefined?getLighthouseMetrics({start,stop:interaction.end}):null;if(fg('platform_ufo_remove_deprecated_config_fields')){if(PPSMetricsAtTTAI!==null){return PPSMetricsAtTTAI;}}else{if(config!==null&&config!==void 0&&config.shouldCalculateLighthouseMetricsFromTTAI&&PPSMetricsAtTTAI!==null){return PPSMetricsAtTTAI;}if(PPSMetricsAtTTI!==null){return{...PPSMetricsAtTTI,'metrics@ttai':PPSMetricsAtTTAI};}}return{};}function getSSRProperties(type){const ssrPhases=getSSRPhaseSuccess(type);return{'ssr:success':(ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.done)!=null?ssrPhases.done:getSSRSuccessUtil(type),'ssr:featureFlags':getSSRFeatureFlags(type),...((ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.earlyFlush)!=null?{'ssr:earlyflush:success':ssrPhases.earlyFlush}:null),...((ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.prefetch)!=null?{'ssr:prefetch:success':ssrPhases.prefetch}:null)};}function getAssetsMetrics(interaction,SSRDoneTime){try{const config=getConfig();const{type}=interaction;const allowedTypes=['page_load'];const assetsConfig=config===null||config===void 0?void 0:config.assetsConfig;if(!allowedTypes.includes(type)||!assetsConfig){// Skip if: type not allowed or assetsClassification isn't configured
2
+ import{getLighthouseMetrics}from'../additional-payload';import{CHRReporter}from'../assets';import*as bundleEvalTiming from'../bundle-eval-timing';import coinflip from'../coinflip';import{getConfig,getExperimentalInteractionRate,getUfoNameOverrides}from'../config';import{getExperimentalVCMetrics}from'../create-experimental-interaction-metrics-payload';import{getBm3Timings}from'../custom-timings';import{getGlobalErrorCount}from'../global-error-handler';import{getPageVisibilityState}from'../hidden-timing';import*as initialPageLoadExtraTiming from'../initial-page-load-extra-timing';import{interactionSpans as atlaskitInteractionSpans}from'../interaction-metrics';import{createMemoryStateReport,createPressureStateReport}from'../machine-utilisation';import*as resourceTiming from'../resource-timing';import{filterResourceTimings}from'../resource-timing/common/utils/resource-timing-buffer';import{roundEpsilon}from'../round-number';import*as ssr from'../ssr';import{buildSegmentTree,getOldSegmentsLabelStack,labelStackStartWith,optimizeLabelStack,sanitizeUfoName,stringifyLabelStackFully}from'./common/utils';import{createCriticalMetricsPayloads}from'./critical-metrics-payload';import{addPerformanceMeasures}from'./utils/add-performance-measures';import{getBatteryInfoToLegacyFormat}from'./utils/get-battery-info';import{getBrowserMetadataToLegacyFormat}from'./utils/get-browser-metadata';import getInteractionStatus from'./utils/get-interaction-status';import{getMoreAccuratePageVisibilityUpToTTAI}from'./utils/get-more-accurate-page-visibility-up-to-ttai';import{getNavigationMetricsToLegacyFormat}from'./utils/get-navigation-metrics';import getPageVisibilityUpToTTAI from'./utils/get-page-visibility-up-to-ttai';import{getPaintMetricsToLegacyFormat}from'./utils/get-paint-metrics';import getPayloadSize from'./utils/get-payload-size';import{getReactUFOPayloadVersion}from'./utils/get-react-ufo-payload-version';import getSSRDoneTimeValue from'./utils/get-ssr-done-time-value';import getSSRSuccessUtil from'./utils/get-ssr-success';import getTTAI from'./utils/get-ttai';import getVCMetrics from'./utils/get-vc-metrics';import{getVisibilityStateFromPerformance}from'./utils/get-visibility-state-from-performance';import{optimizeApdex}from'./utils/optimize-apdex';import{optimizeCustomTimings}from'./utils/optimize-custom-timings';import{optimizeHoldInfo}from'./utils/optimize-hold-info';import{optimizeMarks}from'./utils/optimize-marks';import{optimizeReactProfilerTimings}from'./utils/optimize-react-profiler-timings';import{optimizeRequestInfo}from'./utils/optimize-request-info';import{optimizeSpans}from'./utils/optimize-spans';const MAX_PAYLOAD_SIZE=230;function getUfoNameOverride(interaction){const{ufoName,apdex}=interaction;try{const ufoNameOverrides=getUfoNameOverrides();if(ufoNameOverrides!=null){const metricKey=apdex.length>0?apdex[0].key:'';if(ufoNameOverrides[ufoName][metricKey]){return ufoNameOverrides[ufoName][metricKey];}}return ufoName;}catch(e){return ufoName;}}function getEarliestLegacyStopTime(interaction,labelStack){let earliestLegacyStopTime=null;interaction.apdex.forEach(a=>{var _a$labelStack,_earliestLegacyStopTi;if(!(a!==null&&a!==void 0&&a.stopTime)){return;}if(!labelStackStartWith((_a$labelStack=a.labelStack)!==null&&_a$labelStack!==void 0?_a$labelStack:[],labelStack)){return;}if(a.stopTime>interaction.start&&((_earliestLegacyStopTi=earliestLegacyStopTime)!==null&&_earliestLegacyStopTi!==void 0?_earliestLegacyStopTi:a.stopTime)>=a.stopTime){earliestLegacyStopTime=a.stopTime;}});return earliestLegacyStopTime;}function getBm3EndTimeOrFallbackValue(interaction,labelStack=[],fallbackValue=interaction.end){var _getEarliestLegacySto;if(interaction.type==='press'){return fallbackValue;}return(_getEarliestLegacySto=getEarliestLegacyStopTime(interaction,labelStack))!==null&&_getEarliestLegacySto!==void 0?_getEarliestLegacySto:fallbackValue;}function getPageVisibilityUpToTTI(interaction){const{start}=interaction;const bm3EndTimeOrInteractionEndTime=getBm3EndTimeOrFallbackValue(interaction);return getPageVisibilityState(start,bm3EndTimeOrInteractionEndTime);}function getMoreAccuratePageVisibilityUpToTTI(interaction){const old=getPageVisibilityUpToTTI(interaction);const tti=getEarliestLegacyStopTime(interaction,[]);if(!tti){return old;}const buffered=getVisibilityStateFromPerformance(tti);if(!buffered){return old;}if(buffered!==old){return'mixed';}return old;}function getResourceTimings(start,end){var _resourceTiming$getRe;return(_resourceTiming$getRe=resourceTiming.getResourceTimings(start,end))!==null&&_resourceTiming$getRe!==void 0?_resourceTiming$getRe:undefined;}function getBundleEvalTimings(start){return bundleEvalTiming.getBundleEvalTimings(start);}function getSSRPhaseSuccess(type){return type==='page_load'?ssr.getSSRPhaseSuccess():undefined;}function getSSRFeatureFlags(type){return type==='page_load'?ssr.getSSRFeatureFlags():undefined;}function getPPSMetrics(interaction){var _interaction$apdex,_interaction$apdex$;const{start,end}=interaction;const config=getConfig();const interactionStatus=getInteractionStatus(interaction);const pageVisibilityUpToTTAI=getPageVisibilityUpToTTAI(interaction);const 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;const ttai=interactionStatus.originalInteractionStatus==='SUCCEEDED'&&pageVisibilityUpToTTAI==='visible'?Math.round(end-start):undefined;const PPSMetricsAtTTI=tti!==undefined?getLighthouseMetrics({start,stop:tti}):null;const PPSMetricsAtTTAI=ttai!==undefined?getLighthouseMetrics({start,stop:interaction.end}):null;if(fg('platform_ufo_remove_deprecated_config_fields')){if(PPSMetricsAtTTAI!==null){return PPSMetricsAtTTAI;}}else{if(config!==null&&config!==void 0&&config.shouldCalculateLighthouseMetricsFromTTAI&&PPSMetricsAtTTAI!==null){return PPSMetricsAtTTAI;}if(PPSMetricsAtTTI!==null){return{...PPSMetricsAtTTI,'metrics@ttai':PPSMetricsAtTTAI};}}return{};}function getSSRProperties(type){const ssrPhases=getSSRPhaseSuccess(type);return{'ssr:success':(ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.done)!=null?ssrPhases.done:getSSRSuccessUtil(type),'ssr:featureFlags':getSSRFeatureFlags(type),...((ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.earlyFlush)!=null?{'ssr:earlyflush:success':ssrPhases.earlyFlush}:null),...((ssrPhases===null||ssrPhases===void 0?void 0:ssrPhases.prefetch)!=null?{'ssr:prefetch:success':ssrPhases.prefetch}:null)};}function getAssetsMetrics(interaction,SSRDoneTime){try{const config=getConfig();const{type}=interaction;const allowedTypes=['page_load'];const assetsConfig=config===null||config===void 0?void 0:config.assetsConfig;if(!allowedTypes.includes(type)||!assetsConfig){// Skip if: type not allowed or assetsClassification isn't configured
3
3
  return{};}const reporter=new CHRReporter();const resourceTimings=filterResourceTimings(interaction.start,interaction.end);const assets=reporter.get(resourceTimings,assetsConfig,SSRDoneTime);if(assets){// Only add assets in case it exists
4
4
  return{'event:assets':assets};}return{};}catch(error){// Skip CHR in case of error
5
5
  return{};}}function getTracingContextData(interaction){const{trace,start}=interaction;let tracingContextData={};if(trace){tracingContextData={'ufo:tracingContext':{'X-B3-TraceId':trace.traceId,'X-B3-SpanId':trace.spanId,// eslint-disable-next-line compat/compat
@@ -13,7 +13,9 @@ const getPageLoadDetailedInteractionMetrics=()=>{var _config$ssr3;if(!isPageLoad
13
13
  'event:cpu:usage':createPressureStateReport(interaction.start,interaction.end),'event:memory:usage':createMemoryStateReport(interaction.start,interaction.end),...(criticalPayloadCount!==undefined?{'ufo:multipayload':true,'ufo:criticalPayloadCount':criticalPayloadCount}:{}),// root
14
14
  ...getBrowserMetadataToLegacyFormat(),...batteryInfo,...getSSRProperties(type),...getAssetsMetrics(interaction,pageLoadInteractionMetrics===null||pageLoadInteractionMetrics===void 0?void 0:pageLoadInteractionMetrics.SSRDoneTime),...getPPSMetrics(interaction),...paintMetrics,...getNavigationMetricsToLegacyFormat(type),...finalVCMetrics,...experimentalMetrics,...((_config$additionalPay=config.additionalPayloadData)===null||_config$additionalPay===void 0?void 0:_config$additionalPay.call(config,interaction)),...getTracingContextData(interaction),...getStylesheetMetrics(),...getErrorCounts(interaction),...getReactHydrationStats(),interactionMetrics:{namePrefix:config.namePrefix||'',segmentPrefix:config.segmentPrefix||'',interactionId,pageVisibilityAtTTI,pageVisibilityAtTTAI,experimental__pageVisibilityAtTTI:moreAccuratePageVisibilityAtTTI,experimental__pageVisibilityAtTTAI:moreAccuratePageVisibilityAtTTAI,// raw interaction metrics
15
15
  rate,routeName,type,abortReason,featureFlags,previousInteractionName,isPreviousInteractionAborted,abortedByInteractionName,// performance
16
- apdex:optimizeApdex(interaction.apdex,getReactUFOPayloadVersion(interaction.type)),end:Math.round(end),start:Math.round(start),segments:getReactUFOPayloadVersion(interaction.type)==='2.0.0'?segmentTree:getOldSegmentsLabelStack(segments,interaction.type),marks:optimizeMarks(interaction.marks,getReactUFOPayloadVersion(interaction.type)),customData:optimizeCustomData(interaction),reactProfilerTimings:optimizeReactProfilerTimings(interaction.reactProfilerTimings,start,getReactUFOPayloadVersion(interaction.type)),minorInteractions:interaction.minorInteractions,...(responsiveness?{responsiveness}:{}),...labelStack,...pageLoadInteractionMetrics,...getDetailedInteractionMetrics(resourceTimings),...getPageLoadDetailedInteractionMetrics(),...getBm3TrackerTimings(interaction),'metric:ttai':experimental?regularTTAI||expTTAI:undefined,'metric:experimental:ttai':expTTAI,...(unknownElementName?{unknownElementName}:{}),...(unknownElementHierarchy?{unknownElementHierarchy}:{})},'ufo:payloadTime':roundEpsilon(performance.now()-interactionPayloadStart)}}};if(experimental){regularTTAI=undefined;expTTAI=undefined;}if(fg('platform_ufo_enable_vc_raw_data')){const size=getPayloadSize(payload.attributes.properties);const vcRev=payload.attributes.properties['ufo:vc:rev'];const rawData=vcRev.find(item=>item.revision==='raw-handler');if(rawData){const rawDataSize=getPayloadSize(rawData);payload.attributes.properties['ufo:vc:raw:size']=rawDataSize;if(size>MAX_PAYLOAD_SIZE&&Array.isArray(vcRev)&&vcRev.length>0){payload.attributes.properties['ufo:vc:rev']=vcRev.filter(item=>item.revision!=='raw-handler');payload.attributes.properties['ufo:vc:raw:removed']=true;}}payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}else{payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}return payload;}export async function createPayloads(interactionId,interaction){const ufoNameOverride=getUfoNameOverride(interaction);const modifiedInteraction={...interaction,ufoName:ufoNameOverride};const payloads=[];const isCriticalMetricsEnabled=fg('platform_ufo_critical_metrics_payload');// Calculate VC metrics once to avoid duplicate expensive calculations
16
+ apdex:optimizeApdex(interaction.apdex,getReactUFOPayloadVersion(interaction.type)),end:Math.round(end),start:Math.round(start),segments:getReactUFOPayloadVersion(interaction.type)==='2.0.0'?segmentTree:getOldSegmentsLabelStack(segments,interaction.type),marks:optimizeMarks(interaction.marks,getReactUFOPayloadVersion(interaction.type)),customData:optimizeCustomData(interaction),reactProfilerTimings:optimizeReactProfilerTimings(interaction.reactProfilerTimings,start,getReactUFOPayloadVersion(interaction.type)),minorInteractions:interaction.minorInteractions,...(responsiveness?{responsiveness}:{}),...labelStack,...pageLoadInteractionMetrics,...getDetailedInteractionMetrics(resourceTimings),...getPageLoadDetailedInteractionMetrics(),...getBm3TrackerTimings(interaction),'metric:ttai':experimental?regularTTAI||expTTAI:undefined,'metric:experimental:ttai':expTTAI,...(unknownElementName?{unknownElementName}:{}),...(unknownElementHierarchy?{unknownElementHierarchy}:{})},'ufo:payloadTime':roundEpsilon(performance.now()-interactionPayloadStart)}}};if(experimental){regularTTAI=undefined;expTTAI=undefined;}if(fg('platform_ufo_enable_vc_raw_data')){const size=getPayloadSize(payload.attributes.properties);const vcRev=payload.attributes.properties['ufo:vc:rev'];const rawData=vcRev.find(item=>item.revision==='raw-handler');if(rawData){const rawDataSize=getPayloadSize(rawData);payload.attributes.properties['ufo:vc:raw:size']=rawDataSize;if(size>MAX_PAYLOAD_SIZE&&Array.isArray(vcRev)&&vcRev.length>0){payload.attributes.properties['ufo:vc:rev']=vcRev.filter(item=>item.revision!=='raw-handler');payload.attributes.properties['ufo:vc:raw:removed']=true;}}payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}else{payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}if(fg('platform_ufo_enable_trimmed_payload')){// in order of importance, first one being least important
17
+ // we can add more fields as necessary
18
+ const interactionMetricsFieldsToTrim=['requestInfo','featureFlags','resourceTimings'];const properties=payload.attributes.properties;const interactionMetrics=properties.interactionMetrics;if(interactionMetrics){for(const field of interactionMetricsFieldsToTrim){if(getPayloadSize(properties)<=MAX_PAYLOAD_SIZE){continue;}interactionMetrics[field]=undefined;properties['event:isTrimmed']=true;let trimmedFields=properties['event:trimmedFields'];if(!Array.isArray(trimmedFields)){trimmedFields=[];}trimmedFields.push(`interactionMetrics.${field}`);properties['event:trimmedFields']=trimmedFields;}}}return payload;}export async function createPayloads(interactionId,interaction){const ufoNameOverride=getUfoNameOverride(interaction);const modifiedInteraction={...interaction,ufoName:ufoNameOverride};const payloads=[];const isCriticalMetricsEnabled=fg('platform_ufo_critical_metrics_payload');// Calculate VC metrics once to avoid duplicate expensive calculations
17
19
  const vcMetrics=await getVCMetrics(interaction);// typeof Promise<CriticalMetricsPayload[]>
18
20
  const criticalMetricsPayloads=isCriticalMetricsEnabled?await createCriticalMetricsPayloads(interactionId,interaction,vcMetrics):[];payloads.push(...criticalMetricsPayloads);const criticalPayloadCount=isCriticalMetricsEnabled?criticalMetricsPayloads.length:undefined;const interactionMetricsPayload=await createInteractionMetricsPayload(modifiedInteraction,interactionId,undefined,criticalPayloadCount,vcMetrics);payloads.push(interactionMetricsPayload);return payloads.filter(Boolean);}export async function createExperimentalMetricsPayload(interactionId,interaction){const config=getConfig();if(!config){throw Error('UFO Configuration not provided');}const ufoName=sanitizeUfoName(interaction.ufoName);const rate=getExperimentalInteractionRate(ufoName,interaction.type);if(!coinflip(rate)){return null;}const pageVisibilityState=getPageVisibilityState(interaction.start,interaction.end);if(pageVisibilityState!=='visible'){return null;}const result=await createInteractionMetricsPayload(interaction,interactionId,true);return result;}export async function createExtraSearchPageInteractionPayload(interactionId,interaction){var _newEnd;const SAIN_HOLD_NAMES=['search-ai-dialog-visible-text-loading','search-ai-dialog-all-text-loading'];const NAME_OVERRIDE='search-page-ignoring-smart-answers';const SEARCH_PAGE_SMART_ANSWERS_SEGMENT_LABEL='search-page-smart-answers';const newInteractionId=`${interactionId}-ignoring-smart-answers`;// Calculate a new end time which excludes SAIN holds
19
21
  let newEnd;const{holdInfo,reactProfilerTimings}=interaction;const lastHold=holdInfo.at(-1);const isLastHoldSAIN=Boolean(lastHold&&SAIN_HOLD_NAMES.includes(lastHold.name));// A new end time is only calculated if the last hold is a SAIN hold
@@ -233,6 +233,11 @@ export class SSRPlaceholderHandlers {
233
233
  }
234
234
  });
235
235
  }
236
+ validateReactComponentMatchToPlaceholderV4(el) {
237
+ el = this.findNearestPlaceholderContainerIfIgnored(el);
238
+ const id = this.getPlaceholderReplacementId(el);
239
+ return this.staticPlaceholders.has(id);
240
+ }
236
241
  hasSameSizePosition(rect, boundingClientRect) {
237
242
  if (!rect) {
238
243
  return false;
@@ -8,7 +8,10 @@ const getConsideredEntryTypes = () => {
8
8
  if (fg('platform_ufo_remove_ssr_placeholder_in_ttvc_v4')) {
9
9
  consideredEntryTypes.push('mutation:ssr-placeholder');
10
10
  }
11
- return ['mutation:display-contents-children-element'];
11
+ if (fg('platform_ufo_detect_zero_dimension_rectangles')) {
12
+ consideredEntryTypes.push('mutation:display-contents-children-attribute');
13
+ }
14
+ return consideredEntryTypes;
12
15
  };
13
16
  const getExcludedEntryTypes = () => {
14
17
  const excludedEntryTypes = ['layout-shift:same-rect'];
@@ -31,6 +31,67 @@ const createElementMutationsWatcher = removedNodeRects => ({
31
31
  }
32
32
  return 'mutation:element';
33
33
  };
34
+ const createElementMutationsWatcherV4 = (removedNodeRects, isWithinThirdPartySegment, hasSameDeletedNode, timestamp, isTargetReactRoot, getSSRState, getSSRPlaceholderHandler) => ({
35
+ target,
36
+ rect
37
+ }) => {
38
+ if (getSSRState) {
39
+ const ssrState = getSSRState();
40
+ const SSRStateEnum = {
41
+ normal: 1,
42
+ waitingForFirstRender: 2,
43
+ ignoring: 3
44
+ };
45
+ if (ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && isTargetReactRoot) {
46
+ ssrState.state = SSRStateEnum.ignoring;
47
+ if (ssrState.renderStop === -1) {
48
+ // arbitrary 500ms DOM update window
49
+ ssrState.renderStop = timestamp + 500;
50
+ }
51
+ return 'ssr-hydration';
52
+ }
53
+ if (ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && isTargetReactRoot) {
54
+ if (timestamp <= ssrState.renderStop) {
55
+ return 'ssr-hydration';
56
+ } else {
57
+ ssrState.state = SSRStateEnum.normal;
58
+ }
59
+ }
60
+ }
61
+ if (getSSRPlaceholderHandler) {
62
+ const ssrPlaceholderHandler = getSSRPlaceholderHandler();
63
+ if (ssrPlaceholderHandler) {
64
+ if ((ssrPlaceholderHandler.isPlaceholder(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.checkIfExistedAndSizeMatchingV3(target)) {
65
+ return 'mutation:ssr-placeholder';
66
+ }
67
+ if ((ssrPlaceholderHandler.isPlaceholderReplacement(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.validateReactComponentMatchToPlaceholderV4(target)) {
68
+ return 'mutation:ssr-placeholder';
69
+ }
70
+ }
71
+ }
72
+ if (hasSameDeletedNode && isInVCIgnoreIfNoLayoutShiftMarker(target)) {
73
+ return 'mutation:remount';
74
+ }
75
+ if (isContainedWithinMediaWrapper(target)) {
76
+ return 'mutation:media';
77
+ }
78
+ if (isWithinThirdPartySegment) {
79
+ return 'mutation:third-party-element';
80
+ }
81
+ const isInIgnoreLsMarker = isInVCIgnoreIfNoLayoutShiftMarker(target);
82
+ if (!isInIgnoreLsMarker) {
83
+ return 'mutation:element';
84
+ }
85
+ const isRLLPlaceholder = RLLPlaceholderHandlers.getInstance().isRLLPlaceholderHydration(rect);
86
+ if (isRLLPlaceholder && isInIgnoreLsMarker) {
87
+ return 'mutation:rll-placeholder';
88
+ }
89
+ const wasDeleted = removedNodeRects.some(nr => isSameRectDimensions(nr, rect));
90
+ if (wasDeleted && isInIgnoreLsMarker) {
91
+ return 'mutation:element-replacement';
92
+ }
93
+ return 'mutation:element';
94
+ };
34
95
  export default class ViewportObserver {
35
96
  // SSR context functions
36
97
 
@@ -81,96 +142,112 @@ export default class ViewportObserver {
81
142
  if (!addedNode) {
82
143
  continue;
83
144
  }
84
- for (const {
85
- isDisplayContentsElementChildren,
86
- element
87
- } of getMutatedElements(addedNode)) {
88
- // SSR hydration logic
89
- if (this.getSSRState) {
90
- const ssrState = this.getSSRState();
91
- const SSRStateEnum = {
92
- normal: 1,
93
- waitingForFirstRender: 2,
94
- ignoring: 3
95
- };
96
- if (ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement) {
97
- var _this$intersectionObs;
98
- ssrState.state = SSRStateEnum.ignoring;
99
- if (ssrState.renderStop === -1) {
100
- // arbitrary 500ms DOM update window
101
- ssrState.renderStop = timestamp + 500;
102
- }
103
- (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(element, 'ssr-hydration');
104
- continue;
145
+ if (fg('platform_ufo_detect_zero_dimension_rectangles')) {
146
+ var _this$getSSRState, _this$getSSRState$cal, _this$intersectionObs;
147
+ const hasSameDeletedNode = removedNodes.find(ref => {
148
+ const n = ref.deref();
149
+ if (!n || !addedNode) {
150
+ return false;
105
151
  }
106
- if (ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement) {
107
- if (timestamp <= ssrState.renderStop) {
152
+ return n.isEqualNode(addedNode);
153
+ });
154
+ const {
155
+ isWithin: isWithinThirdPartySegment
156
+ } = checkWithinComponent(addedNode, 'UFOThirdPartySegment', this.mapIs3pResult);
157
+ const isTargetReactRoot = targetNode === ((_this$getSSRState = this.getSSRState) === null || _this$getSSRState === void 0 ? void 0 : (_this$getSSRState$cal = _this$getSSRState.call(this)) === null || _this$getSSRState$cal === void 0 ? void 0 : _this$getSSRState$cal.reactRootElement);
158
+ (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(addedNode, createElementMutationsWatcherV4(removedNodeRects, isWithinThirdPartySegment, !!hasSameDeletedNode, timestamp, isTargetReactRoot, this.getSSRState, this.getSSRPlaceholderHandler));
159
+ } else {
160
+ for (const {
161
+ isDisplayContentsElementChildren,
162
+ element
163
+ } of getMutatedElements(addedNode)) {
164
+ // SSR hydration logic
165
+ if (this.getSSRState) {
166
+ const ssrState = this.getSSRState();
167
+ const SSRStateEnum = {
168
+ normal: 1,
169
+ waitingForFirstRender: 2,
170
+ ignoring: 3
171
+ };
172
+ if (ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement) {
108
173
  var _this$intersectionObs2;
174
+ ssrState.state = SSRStateEnum.ignoring;
175
+ if (ssrState.renderStop === -1) {
176
+ // arbitrary 500ms DOM update window
177
+ ssrState.renderStop = timestamp + 500;
178
+ }
109
179
  (_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.watchAndTag(element, 'ssr-hydration');
110
180
  continue;
111
- } else {
112
- ssrState.state = SSRStateEnum.normal;
113
181
  }
114
- }
115
- }
116
-
117
- // SSR placeholder logic - check and handle with await
118
- if (this.getSSRPlaceholderHandler) {
119
- const ssrPlaceholderHandler = this.getSSRPlaceholderHandler();
120
- if (ssrPlaceholderHandler) {
121
- if (ssrPlaceholderHandler.isPlaceholder(element) || ssrPlaceholderHandler.isPlaceholderIgnored(element)) {
122
- if (ssrPlaceholderHandler.checkIfExistedAndSizeMatchingV3(element)) {
182
+ if (ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement) {
183
+ if (timestamp <= ssrState.renderStop) {
123
184
  var _this$intersectionObs3;
124
- (_this$intersectionObs3 = this.intersectionObserver) === null || _this$intersectionObs3 === void 0 ? void 0 : _this$intersectionObs3.watchAndTag(element, 'mutation:ssr-placeholder');
185
+ (_this$intersectionObs3 = this.intersectionObserver) === null || _this$intersectionObs3 === void 0 ? void 0 : _this$intersectionObs3.watchAndTag(element, 'ssr-hydration');
125
186
  continue;
187
+ } else {
188
+ ssrState.state = SSRStateEnum.normal;
126
189
  }
127
- // If result is false, continue to normal mutation logic below
128
190
  }
129
- if (ssrPlaceholderHandler.isPlaceholderReplacement(element) || ssrPlaceholderHandler.isPlaceholderIgnored(element)) {
130
- const result = await ssrPlaceholderHandler.validateReactComponentMatchToPlaceholder(element);
131
- if (result !== false) {
132
- var _this$intersectionObs4;
133
- (_this$intersectionObs4 = this.intersectionObserver) === null || _this$intersectionObs4 === void 0 ? void 0 : _this$intersectionObs4.watchAndTag(element, 'mutation:ssr-placeholder');
134
- continue;
191
+ }
192
+
193
+ // SSR placeholder logic - check and handle with await
194
+ if (this.getSSRPlaceholderHandler) {
195
+ const ssrPlaceholderHandler = this.getSSRPlaceholderHandler();
196
+ if (ssrPlaceholderHandler) {
197
+ if (ssrPlaceholderHandler.isPlaceholder(element) || ssrPlaceholderHandler.isPlaceholderIgnored(element)) {
198
+ if (ssrPlaceholderHandler.checkIfExistedAndSizeMatchingV3(element)) {
199
+ var _this$intersectionObs4;
200
+ (_this$intersectionObs4 = this.intersectionObserver) === null || _this$intersectionObs4 === void 0 ? void 0 : _this$intersectionObs4.watchAndTag(element, 'mutation:ssr-placeholder');
201
+ continue;
202
+ }
203
+ // If result is false, continue to normal mutation logic below
204
+ }
205
+ if (ssrPlaceholderHandler.isPlaceholderReplacement(element) || ssrPlaceholderHandler.isPlaceholderIgnored(element)) {
206
+ const result = await ssrPlaceholderHandler.validateReactComponentMatchToPlaceholder(element);
207
+ if (result !== false) {
208
+ var _this$intersectionObs5;
209
+ (_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 ? void 0 : _this$intersectionObs5.watchAndTag(element, 'mutation:ssr-placeholder');
210
+ continue;
211
+ }
212
+ // If result is false, continue to normal mutation logic below
135
213
  }
136
- // If result is false, continue to normal mutation logic below
137
214
  }
138
215
  }
139
- }
140
- const sameDeletedNode = removedNodes.find(ref => {
141
- const n = ref.deref();
142
- if (!n || !element) {
143
- return false;
216
+ const sameDeletedNode = removedNodes.find(ref => {
217
+ const n = ref.deref();
218
+ if (!n || !element) {
219
+ return false;
220
+ }
221
+ return n.isEqualNode(element);
222
+ });
223
+ const isInIgnoreLsMarker = element instanceof HTMLElement ? isInVCIgnoreIfNoLayoutShiftMarker(element) : false;
224
+ if (sameDeletedNode && isInIgnoreLsMarker) {
225
+ var _this$intersectionObs6;
226
+ (_this$intersectionObs6 = this.intersectionObserver) === null || _this$intersectionObs6 === void 0 ? void 0 : _this$intersectionObs6.watchAndTag(element, 'mutation:remount');
227
+ continue;
228
+ }
229
+ if (isContainedWithinMediaWrapper(element)) {
230
+ var _this$intersectionObs7;
231
+ (_this$intersectionObs7 = this.intersectionObserver) === null || _this$intersectionObs7 === void 0 ? void 0 : _this$intersectionObs7.watchAndTag(element, 'mutation:media');
232
+ continue;
233
+ }
234
+ const {
235
+ isWithin: isWithinThirdPartySegment
236
+ } = element instanceof HTMLElement ? checkWithinComponent(element, 'UFOThirdPartySegment', this.mapIs3pResult) : {
237
+ isWithin: false
238
+ };
239
+ if (isWithinThirdPartySegment) {
240
+ var _this$intersectionObs8;
241
+ (_this$intersectionObs8 = this.intersectionObserver) === null || _this$intersectionObs8 === void 0 ? void 0 : _this$intersectionObs8.watchAndTag(element, 'mutation:third-party-element');
242
+ continue;
243
+ }
244
+ if (isDisplayContentsElementChildren) {
245
+ var _this$intersectionObs9;
246
+ (_this$intersectionObs9 = this.intersectionObserver) === null || _this$intersectionObs9 === void 0 ? void 0 : _this$intersectionObs9.watchAndTag(element, 'mutation:display-contents-children-element');
247
+ } else {
248
+ var _this$intersectionObs0;
249
+ (_this$intersectionObs0 = this.intersectionObserver) === null || _this$intersectionObs0 === void 0 ? void 0 : _this$intersectionObs0.watchAndTag(element, createElementMutationsWatcher(removedNodeRects));
144
250
  }
145
- return n.isEqualNode(element);
146
- });
147
- const isInIgnoreLsMarker = element instanceof HTMLElement ? isInVCIgnoreIfNoLayoutShiftMarker(element) : false;
148
- if (sameDeletedNode && isInIgnoreLsMarker) {
149
- var _this$intersectionObs5;
150
- (_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 ? void 0 : _this$intersectionObs5.watchAndTag(element, 'mutation:remount');
151
- continue;
152
- }
153
- if (isContainedWithinMediaWrapper(element)) {
154
- var _this$intersectionObs6;
155
- (_this$intersectionObs6 = this.intersectionObserver) === null || _this$intersectionObs6 === void 0 ? void 0 : _this$intersectionObs6.watchAndTag(element, 'mutation:media');
156
- continue;
157
- }
158
- const {
159
- isWithin: isWithinThirdPartySegment
160
- } = element instanceof HTMLElement ? checkWithinComponent(element, 'UFOThirdPartySegment', this.mapIs3pResult) : {
161
- isWithin: false
162
- };
163
- if (isWithinThirdPartySegment) {
164
- var _this$intersectionObs7;
165
- (_this$intersectionObs7 = this.intersectionObserver) === null || _this$intersectionObs7 === void 0 ? void 0 : _this$intersectionObs7.watchAndTag(element, 'mutation:third-party-element');
166
- continue;
167
- }
168
- if (isDisplayContentsElementChildren) {
169
- var _this$intersectionObs8;
170
- (_this$intersectionObs8 = this.intersectionObserver) === null || _this$intersectionObs8 === void 0 ? void 0 : _this$intersectionObs8.watchAndTag(element, 'mutation:display-contents-children-element');
171
- } else {
172
- var _this$intersectionObs9;
173
- (_this$intersectionObs9 = this.intersectionObserver) === null || _this$intersectionObs9 === void 0 ? void 0 : _this$intersectionObs9.watchAndTag(element, createElementMutationsWatcher(removedNodeRects));
174
251
  }
175
252
  }
176
253
  }
@@ -181,8 +258,8 @@ export default class ViewportObserver {
181
258
  oldValue,
182
259
  newValue
183
260
  }) => {
184
- var _this$intersectionObs0;
185
- (_this$intersectionObs0 = this.intersectionObserver) === null || _this$intersectionObs0 === void 0 ? void 0 : _this$intersectionObs0.watchAndTag(target, ({
261
+ var _this$intersectionObs1;
262
+ (_this$intersectionObs1 = this.intersectionObserver) === null || _this$intersectionObs1 === void 0 ? void 0 : _this$intersectionObs1.watchAndTag(target, ({
186
263
  target,
187
264
  rect
188
265
  }) => {
@@ -339,12 +416,12 @@ export default class ViewportObserver {
339
416
  this.isStarted = true;
340
417
  }
341
418
  stop() {
342
- var _this$mutationObserve2, _this$intersectionObs1, _this$performanceObse2;
419
+ var _this$mutationObserve2, _this$intersectionObs10, _this$performanceObse2;
343
420
  if (!this.isStarted) {
344
421
  return;
345
422
  }
346
423
  (_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 ? void 0 : _this$mutationObserve2.disconnect();
347
- (_this$intersectionObs1 = this.intersectionObserver) === null || _this$intersectionObs1 === void 0 ? void 0 : _this$intersectionObs1.disconnect();
424
+ (_this$intersectionObs10 = this.intersectionObserver) === null || _this$intersectionObs10 === void 0 ? void 0 : _this$intersectionObs10.disconnect();
348
425
  (_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 ? void 0 : _this$performanceObse2.disconnect();
349
426
  this.isStarted = false;
350
427
  // Clean up caches when stopping
@@ -1,3 +1,5 @@
1
+ import { fg } from '@atlaskit/platform-feature-flags';
2
+ import { isZeroDimensionRectangle } from '../utils/is-zero-dimension-rectangle';
1
3
  function isValidEntry(entry) {
2
4
  return entry.isIntersecting && entry.intersectionRect.width > 0 && entry.intersectionRect.height > 0;
3
5
  }
@@ -14,12 +16,41 @@ export function createIntersectionObserver({
14
16
  const startTime = performance.now();
15
17
  entries.forEach(entry => {
16
18
  var _mutationTag;
17
- if (!(entry.target instanceof HTMLElement) || !isValidEntry(entry)) {
19
+ if (!(entry.target instanceof HTMLElement)) {
20
+ return;
21
+ }
22
+ const tagOrCallback = callbacksPerElement.get(entry.target);
23
+ if (fg('platform_ufo_detect_zero_dimension_rectangles')) {
24
+ if (isZeroDimensionRectangle(entry.intersectionRect)) {
25
+ const zeroDimensionRectangleTagCallback = props => {
26
+ const tagOrCallbackResult = typeof tagOrCallback === 'function' ? tagOrCallback(props) : tagOrCallback;
27
+
28
+ // override as display-contents mutation
29
+ if (tagOrCallbackResult === 'mutation:element') {
30
+ return 'mutation:display-contents-children-element';
31
+ }
32
+
33
+ // override as display-contents mutation
34
+ if (tagOrCallbackResult && typeof tagOrCallbackResult !== 'string' && tagOrCallbackResult.type === 'mutation:attribute') {
35
+ return {
36
+ type: 'mutation:display-contents-children-attribute',
37
+ mutationData: tagOrCallbackResult.mutationData
38
+ };
39
+ }
40
+ return tagOrCallbackResult;
41
+ };
42
+ for (const child of entry.target.children) {
43
+ observer.observe(child);
44
+ callbacksPerElement.set(child, zeroDimensionRectangleTagCallback);
45
+ }
46
+ return;
47
+ }
48
+ }
49
+ if (!isValidEntry(entry)) {
18
50
  return;
19
51
  }
20
52
  let mutationTag = null;
21
53
  let mutationData = null;
22
- const tagOrCallback = callbacksPerElement.get(entry.target);
23
54
  if (typeof tagOrCallback === 'function') {
24
55
  const tagOrCallbackResult = tagOrCallback({
25
56
  target: entry.target,
@@ -1,19 +1,30 @@
1
1
  import { fg } from '@atlaskit/platform-feature-flags';
2
+ function isElementStyledWithDisplayContents(element) {
3
+ var _window2, _window2$getComputedS;
4
+ // To minimise calling `getComputedStyle`, we are making an assumption that if an element is from the Entrypoints framework, then it will have `display: contents` styling
5
+ // as per https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/e4ccf437262ef4c0fd3c651ffb7ad4770b15aed4/jira/src/packages/platform/entry-points/entry-point-placeholder/src/index.tsx#lines-136
6
+ if (fg('platform_ufo_detect_entrypoint_parent')) {
7
+ var _window, _window$getComputedSt;
8
+ if (element.hasAttribute('data-ep-placeholder-id')) {
9
+ return true;
10
+ }
11
+ return ((_window = window) === null || _window === void 0 ? void 0 : (_window$getComputedSt = _window.getComputedStyle(element)) === null || _window$getComputedSt === void 0 ? void 0 : _window$getComputedSt.display) === 'contents';
12
+ }
13
+ return ((_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$getComputedS = _window2.getComputedStyle(element)) === null || _window2$getComputedS === void 0 ? void 0 : _window2$getComputedS.display) === 'contents';
14
+ }
2
15
  const MAX_NESTED_LEVELS_OF_DISPLAY_CONTENT_ELEMENTS_HANDLED = 3;
3
16
  export function getMutatedElements(element, depthLevel = 0) {
4
- var _window, _window$getComputedSt;
5
17
  if (fg('platform_ufo_disable_vcnext_observations')) {
6
18
  return [{
7
19
  element,
8
20
  isDisplayContentsElementChildren: false
9
21
  }];
10
22
  }
11
- if (((_window = window) === null || _window === void 0 ? void 0 : (_window$getComputedSt = _window.getComputedStyle(element)) === null || _window$getComputedSt === void 0 ? void 0 : _window$getComputedSt.display) === 'contents') {
23
+ if (isElementStyledWithDisplayContents(element)) {
12
24
  const mutatedElements = [];
13
25
  const nestedDisplayContentsElementChildren = [];
14
26
  for (const child of element.children) {
15
- var _window2, _window2$getComputedS;
16
- if (((_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$getComputedS = _window2.getComputedStyle(child)) === null || _window2$getComputedS === void 0 ? void 0 : _window2$getComputedS.display) === 'contents') {
27
+ if (isElementStyledWithDisplayContents(child)) {
17
28
  nestedDisplayContentsElementChildren.push(child);
18
29
  }
19
30
  mutatedElements.push({
@@ -0,0 +1,3 @@
1
+ export function isZeroDimensionRectangle(rect) {
2
+ return rect.bottom === 0 && rect.top === 0 && rect.left === 0 && rect.right === 0 && rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0;
3
+ }