{"version":3,"file":"time.js","sources":["../../../src/utils/time.ts"],"sourcesContent":["import { safeDateNow, withRandomSafeContext } from './randomSafeContext';\nimport { GLOBAL_OBJ } from './worldwide';\n\nconst ONE_SECOND_IN_MS = 1000;\n\n/**\n * A partial definition of the [Performance Web API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Performance}\n * for accessing a high-resolution monotonic clock.\n */\ninterface Performance {\n /**\n * The millisecond timestamp at which measurement began, measured in Unix time.\n */\n timeOrigin: number;\n /**\n * Returns the current millisecond timestamp, where 0 represents the start of measurement.\n */\n now(): number;\n}\n\n/**\n * Returns a timestamp in seconds since the UNIX epoch using the Date API.\n */\nexport function dateTimestampInSeconds(): number {\n return safeDateNow() / ONE_SECOND_IN_MS;\n}\n\n/**\n * Returns a wrapper around the native Performance API browser implementation, or undefined for browsers that do not\n * support the API.\n *\n * Wrapping the native API works around differences in behavior from different browsers.\n */\nfunction createUnixTimestampInSecondsFunc(): () => number {\n const { performance } = GLOBAL_OBJ as typeof GLOBAL_OBJ & { performance?: Performance };\n // Some browser and environments don't have a performance or timeOrigin, so we fallback to\n // using Date.now() to compute the starting time.\n if (!performance?.now || !performance.timeOrigin) {\n return dateTimestampInSeconds;\n }\n\n const timeOrigin = performance.timeOrigin;\n\n // performance.now() is a monotonic clock, which means it starts at 0 when the process begins. To get the current\n // wall clock time (actual UNIX timestamp), we need to add the starting time origin and the current time elapsed.\n //\n // TODO: This does not account for the case where the monotonic clock that powers performance.now() drifts from the\n // wall clock time, which causes the returned timestamp to be inaccurate. We should investigate how to detect and\n // correct for this.\n // See: https://github.com/getsentry/sentry-javascript/issues/2590\n // See: https://github.com/mdn/content/issues/4713\n // See: https://dev.to/noamr/when-a-millisecond-is-not-a-millisecond-3h6\n return () => {\n return (timeOrigin + withRandomSafeContext(() => performance.now())) / ONE_SECOND_IN_MS;\n };\n}\n\nlet _cachedTimestampInSeconds: (() => number) | undefined;\n\n/**\n * Returns a timestamp in seconds since the UNIX epoch using either the Performance or Date APIs, depending on the\n * availability of the Performance API.\n *\n * BUG: Note that because of how browsers implement the Performance API, the clock might stop when the computer is\n * asleep. This creates a skew between `dateTimestampInSeconds` and `timestampInSeconds`. The\n * skew can grow to arbitrary amounts like days, weeks or months.\n * See https://github.com/getsentry/sentry-javascript/issues/2590.\n */\nexport function timestampInSeconds(): number {\n // We store this in a closure so that we don't have to create a new function every time this is called.\n const func = _cachedTimestampInSeconds ?? (_cachedTimestampInSeconds = createUnixTimestampInSecondsFunc());\n return func();\n}\n\n/**\n * Cached result of getBrowserTimeOrigin.\n */\nlet cachedTimeOrigin: number | null | undefined = null;\n\n/**\n * Gets the time origin and the mode used to determine it.\n *\n * Unfortunately browsers may report an inaccurate time origin data, through either performance.timeOrigin or\n * performance.timing.navigationStart, which results in poor results in performance data. We only treat time origin\n * data as reliable if they are within a reasonable threshold of the current time.\n *\n * TODO: move to `@sentry/browser-utils` package.\n */\nfunction getBrowserTimeOrigin(): number | undefined {\n const { performance } = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n if (!performance?.now) {\n return undefined;\n }\n\n const threshold = 300_000; // 5 minutes in milliseconds\n const performanceNow = withRandomSafeContext(() => performance.now());\n const dateNow = safeDateNow();\n\n const timeOrigin = performance.timeOrigin;\n if (typeof timeOrigin === 'number') {\n const timeOriginDelta = Math.abs(timeOrigin + performanceNow - dateNow);\n if (timeOriginDelta < threshold) {\n return timeOrigin;\n }\n }\n\n // TODO: Remove all code related to `performance.timing.navigationStart` once we drop support for Safari 14.\n // `performance.timeSince` is available in Safari 15.\n // see: https://caniuse.com/mdn-api_performance_timeorigin\n\n // While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin\n // is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.\n // Also as of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always\n // a valid fallback. In the absence of an initial time provided by the browser, fallback to the current time from the\n // Date API.\n // eslint-disable-next-line deprecation/deprecation\n const navigationStart = performance.timing?.navigationStart;\n if (typeof navigationStart === 'number') {\n const navigationStartDelta = Math.abs(navigationStart + performanceNow - dateNow);\n if (navigationStartDelta < threshold) {\n return navigationStart;\n }\n }\n\n // Either both timeOrigin and navigationStart are skewed or neither is available, fallback to subtracting\n // `performance.now()` from `Date.now()`.\n return dateNow - performanceNow;\n}\n\n/**\n * The number of milliseconds since the UNIX epoch. This value is only usable in a browser, and only when the\n * performance API is available.\n */\nexport function browserPerformanceTimeOrigin(): number | undefined {\n if (cachedTimeOrigin === null) {\n cachedTimeOrigin = getBrowserTimeOrigin();\n }\n\n return cachedTimeOrigin;\n}\n"],"names":[],"mappings":";;;AAGA,MAAM,gBAAA,GAAmB,IAAI;;AAE7B;AACA;AACA;AACA;;AAYA;AACA;AACA;AACO,SAAS,sBAAsB,GAAW;AACjD,EAAE,OAAO,WAAW,EAAC,GAAI,gBAAgB;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gCAAgC,GAAiB;AAC1D,EAAE,MAAM,EAAE,WAAA,EAAY,GAAI,UAAA;AAC1B;AACA;AACA,EAAE,IAAI,CAAC,WAAW,EAAE,GAAA,IAAO,CAAC,WAAW,CAAC,UAAU,EAAE;AACpD,IAAI,OAAO,sBAAsB;AACjC,EAAE;;AAEF,EAAE,MAAM,UAAA,GAAa,WAAW,CAAC,UAAU;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,OAAO,MAAM;AACf,IAAI,OAAO,CAAC,UAAA,GAAa,qBAAqB,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,gBAAgB;AAC3F,EAAE,CAAC;AACH;;AAEA,IAAI,yBAAyB;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,GAAW;AAC7C;AACA,EAAE,MAAM,IAAA,GAAO,yBAAA,KAA8B,yBAAA,GAA4B,gCAAgC,EAAE,CAAC;AAC5G,EAAE,OAAO,IAAI,EAAE;AACf;;AAEA;AACA;AACA;AACA,IAAI,gBAAgB,GAA8B,IAAI;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,GAAuB;AACpD,EAAE,MAAM,EAAE,WAAA,EAAY,GAAI,UAAA;AAC1B,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;AACzB,IAAI,OAAO,SAAS;AACpB,EAAE;;AAEF,EAAE,MAAM,SAAA,GAAY,MAAO,CAAA;AAC3B,EAAE,MAAM,cAAA,GAAiB,qBAAqB,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;AACvE,EAAE,MAAM,OAAA,GAAU,WAAW,EAAE;;AAE/B,EAAE,MAAM,UAAA,GAAa,WAAW,CAAC,UAAU;AAC3C,EAAE,IAAI,OAAO,UAAA,KAAe,QAAQ,EAAE;AACtC,IAAI,MAAM,eAAA,GAAkB,IAAI,CAAC,GAAG,CAAC,UAAA,GAAa,cAAA,GAAiB,OAAO,CAAC;AAC3E,IAAI,IAAI,eAAA,GAAkB,SAAS,EAAE;AACrC,MAAM,OAAO,UAAU;AACvB,IAAI;AACJ,EAAE;;AAEF;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,MAAM,eAAA,GAAkB,WAAW,CAAC,MAAM,EAAE,eAAe;AAC7D,EAAE,IAAI,OAAO,eAAA,KAAoB,QAAQ,EAAE;AAC3C,IAAI,MAAM,oBAAA,GAAuB,IAAI,CAAC,GAAG,CAAC,eAAA,GAAkB,cAAA,GAAiB,OAAO,CAAC;AACrF,IAAI,IAAI,oBAAA,GAAuB,SAAS,EAAE;AAC1C,MAAM,OAAO,eAAe;AAC5B,IAAI;AACJ,EAAE;;AAEF;AACA;AACA,EAAE,OAAO,OAAA,GAAU,cAAc;AACjC;;AAEA;AACA;AACA;AACA;AACO,SAAS,4BAA4B,GAAuB;AACnE,EAAE,IAAI,gBAAA,KAAqB,IAAI,EAAE;AACjC,IAAI,gBAAA,GAAmB,oBAAoB,EAAE;AAC7C,EAAE;;AAEF,EAAE,OAAO,gBAAgB;AACzB;;;;"}