{"version":3,"file":"getVisibilityWatcher.js","sources":["../../../../../src/metrics/web-vitals/lib/getVisibilityWatcher.ts"],"sourcesContent":["/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types';\nimport { getActivationStart } from './getActivationStart';\nimport { addPageListener, removePageListener } from './globalListeners';\n\nlet firstHiddenTime = -1;\nconst onHiddenFunctions: Set<() => void> = new Set();\n\nconst initHiddenTime = () => {\n // If the document is hidden when this code runs, assume it was always\n // hidden and the page was loaded in the background, with the one exception\n // that visibility state is always 'hidden' during prerendering, so we have\n // to ignore that case until prerendering finishes (see: `prerenderingchange`\n // event logic below).\n return WINDOW.document?.visibilityState === 'hidden' && !WINDOW.document?.prerendering ? 0 : Infinity;\n};\n\nconst onVisibilityUpdate = (event: Event) => {\n // Handle changes to hidden state\n if (isPageHidden(event) && firstHiddenTime > -1) {\n // Sentry-specific change: Also call onHidden callbacks for pagehide events\n // to support older browsers (Safari <14.4) that don't properly fire visibilitychange\n if (event.type === 'visibilitychange' || event.type === 'pagehide') {\n for (const onHiddenFunction of onHiddenFunctions) {\n onHiddenFunction();\n }\n }\n\n // If the document is 'hidden' and no previous hidden timestamp has been\n // set (so is infinity), update it based on the current event data.\n if (!isFinite(firstHiddenTime)) {\n // If the event is a 'visibilitychange' event, it means the page was\n // visible prior to this change, so the event timestamp is the first\n // hidden time.\n // However, if the event is not a 'visibilitychange' event, then it must\n // be a 'prerenderingchange' or 'pagehide' event, and the fact that the document is\n // still 'hidden' from the above check means the tab was activated\n // in a background state and so has always been hidden.\n firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;\n\n // We no longer need the `prerenderingchange` event listener now we've\n // set an initial init time so remove that\n // (we'll keep the visibilitychange and pagehide ones for onHiddenFunction above)\n removePageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n }\n};\n\nexport const getVisibilityWatcher = () => {\n if (WINDOW.document && firstHiddenTime < 0) {\n // Check if we have a previous hidden `visibility-state` performance entry.\n const activationStart = getActivationStart();\n const firstVisibilityStateHiddenTime = !WINDOW.document.prerendering\n ? globalThis.performance\n .getEntriesByType('visibility-state')\n .filter(e => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime\n : undefined;\n\n // Prefer that, but if it's not available and the document is hidden when\n // this code runs, assume it was hidden since navigation start. This isn't\n // a perfect heuristic, but it's the best we can do until the\n // `visibility-state` performance entry becomes available in all browsers.\n firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();\n // Listen for visibility changes so we can handle things like bfcache\n // restores and/or prerender without having to examine individual\n // timestamps in detail and also for onHidden function calls.\n addPageListener('visibilitychange', onVisibilityUpdate, true);\n\n // Sentry-specific change: Some browsers have buggy implementations of visibilitychange,\n // so we use pagehide in addition, just to be safe. This is also required for older\n // Safari versions (<14.4) that we still support.\n addPageListener('pagehide', onVisibilityUpdate, true);\n\n // IMPORTANT: when a page is prerendering, its `visibilityState` is\n // 'hidden', so in order to account for cases where this module checks for\n // visibility during prerendering, an additional check after prerendering\n // completes is also required.\n addPageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n\n return {\n get firstHiddenTime() {\n return firstHiddenTime;\n },\n onHidden(cb: () => void) {\n onHiddenFunctions.add(cb);\n },\n };\n};\n\n/**\n * Check if the page is hidden, uses the `pagehide` event for older browsers support that we used to have in `onHidden` function.\n * Some browsers we still support (Safari <14.4) don't fully support `visibilitychange`\n * or have known bugs w.r.t the `visibilitychange` event.\n * // TODO (v11): If we decide to drop support for Safari 14.4, we can use the logic from web-vitals 4.2.4\n */\nfunction isPageHidden(event: Event) {\n return event.type === 'pagehide' || WINDOW.document?.visibilityState === 'hidden';\n}\n"],"names":[],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAMA,IAAI,eAAA,GAAkB,EAAE;AACxB,MAAM,iBAAiB,GAAoB,IAAI,GAAG,EAAE;;AAEpD,MAAM,cAAA,GAAiB,MAAM;AAC7B;AACA;AACA;AACA;AACA;AACA,EAAE,OAAO,MAAM,CAAC,QAAQ,EAAE,eAAA,KAAoB,QAAA,IAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAA,GAAI,QAAQ;AACvG,CAAC;;AAED,MAAM,kBAAA,GAAqB,CAAC,KAAK,KAAY;AAC7C;AACA,EAAE,IAAI,YAAY,CAAC,KAAK,CAAA,IAAK,eAAA,GAAkB,EAAE,EAAE;AACnD;AACA;AACA,IAAI,IAAI,KAAK,CAAC,IAAA,KAAS,kBAAA,IAAsB,KAAK,CAAC,IAAA,KAAS,UAAU,EAAE;AACxE,MAAM,KAAK,MAAM,gBAAA,IAAoB,iBAAiB,EAAE;AACxD,QAAQ,gBAAgB,EAAE;AAC1B,MAAM;AACN,IAAI;;AAEJ;AACA;AACA,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,eAAA,GAAkB,KAAK,CAAC,IAAA,KAAS,kBAAA,GAAqB,KAAK,CAAC,SAAA,GAAY,CAAC;;AAE/E;AACA;AACA;AACA,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,IAAI,CAAC;AACxE,IAAI;AACJ,EAAE;AACF,CAAC;;AAEM,MAAM,oBAAA,GAAuB,MAAM;AAC1C,EAAE,IAAI,MAAM,CAAC,YAAY,eAAA,GAAkB,CAAC,EAAE;AAC9C;AACA,IAAI,MAAM,eAAA,GAAkB,kBAAkB,EAAE;AAChD,IAAI,MAAM,8BAAA,GAAiC,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC5D,QAAQ,UAAU,CAAC;AACnB,WAAW,gBAAgB,CAAC,kBAAkB;AAC9C,WAAW,MAAM,CAAC,CAAA,IAAK,CAAC,CAAC,SAAS,QAAA,IAAY,CAAC,CAAC,YAAY,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE;AACjF,QAAQ,SAAS;;AAEjB;AACA;AACA;AACA;AACA,IAAI,kBAAkB,8BAAA,IAAkC,cAAc,EAAE;AACxE;AACA;AACA;AACA,IAAI,eAAe,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,IAAI,CAAC;;AAEjE;AACA;AACA;AACA,IAAI,eAAe,CAAC,UAAU,EAAE,kBAAkB,EAAE,IAAI,CAAC;;AAEzD;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,IAAI,CAAC;AACnE,EAAE;;AAEF,EAAE,OAAO;AACT,IAAI,IAAI,eAAe,GAAG;AAC1B,MAAM,OAAO,eAAe;AAC5B,IAAI,CAAC;AACL,IAAI,QAAQ,CAAC,EAAE,EAAc;AAC7B,MAAM,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/B,IAAI,CAAC;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,YAAY,CAAC,KAAK,EAAS;AACpC,EAAE,OAAO,KAAK,CAAC,IAAA,KAAS,UAAA,IAAc,MAAM,CAAC,QAAQ,EAAE,eAAA,KAAoB,QAAQ;AACnF;;;;"}