diff --git a/packages/tracing-internal/src/browser/backgroundtab.ts b/packages/tracing-internal/src/browser/backgroundtab.ts index 95f33c0c9fd3..67d114d1ee00 100644 --- a/packages/tracing-internal/src/browser/backgroundtab.ts +++ b/packages/tracing-internal/src/browser/backgroundtab.ts @@ -10,11 +10,11 @@ import { WINDOW } from './types'; * document is hidden. */ export function registerBackgroundTabDetection(): void { - if (WINDOW && WINDOW.document) { + if (WINDOW.document) { WINDOW.document.addEventListener('visibilitychange', () => { // eslint-disable-next-line deprecation/deprecation const activeTransaction = getActiveTransaction() as IdleTransaction; - if (WINDOW.document.hidden && activeTransaction) { + if (WINDOW.document!.hidden && activeTransaction) { const statusType: SpanStatusType = 'cancelled'; const { op, status } = spanToJSON(activeTransaction); diff --git a/packages/tracing-internal/src/browser/browserTracingIntegration.ts b/packages/tracing-internal/src/browser/browserTracingIntegration.ts index d17ceebe7a9a..9ac2e7a8fd42 100644 --- a/packages/tracing-internal/src/browser/browserTracingIntegration.ts +++ b/packages/tracing-internal/src/browser/browserTracingIntegration.ts @@ -292,7 +292,7 @@ export const browserTracingIntegration = ((_options: Partial { - if (['interactive', 'complete'].includes(WINDOW.document.readyState)) { + if (['interactive', 'complete'].includes(WINDOW.document!.readyState)) { idleTransaction.sendAutoFinishSignal(); } }); @@ -538,7 +538,9 @@ function registerInteractionListener( }; ['click'].forEach(type => { - addEventListener(type, registerInteractionTransaction, { once: false, capture: true }); + if (WINDOW.document) { + addEventListener(type, registerInteractionTransaction, { once: false, capture: true }); + } }); } diff --git a/packages/tracing-internal/src/browser/browsertracing.ts b/packages/tracing-internal/src/browser/browsertracing.ts index 28e1e35aba2f..afbd9265894e 100644 --- a/packages/tracing-internal/src/browser/browsertracing.ts +++ b/packages/tracing-internal/src/browser/browsertracing.ts @@ -418,14 +418,16 @@ export class BrowserTracing implements Integration { ); if (isPageloadTransaction) { - WINDOW.document.addEventListener('readystatechange', () => { + if (WINDOW.document) { + WINDOW.document.addEventListener('readystatechange', () => { + if (['interactive', 'complete'].includes(WINDOW.document!.readyState)) { + idleTransaction.sendAutoFinishSignal(); + } + }); + if (['interactive', 'complete'].includes(WINDOW.document.readyState)) { idleTransaction.sendAutoFinishSignal(); } - }); - - if (['interactive', 'complete'].includes(WINDOW.document.readyState)) { - idleTransaction.sendAutoFinishSignal(); } } @@ -496,7 +498,9 @@ export class BrowserTracing implements Integration { }; ['click'].forEach(type => { - addEventListener(type, registerInteractionTransaction, { once: false, capture: true }); + if (WINDOW.document) { + addEventListener(type, registerInteractionTransaction, { once: false, capture: true }); + } }); } diff --git a/packages/tracing-internal/src/browser/types.ts b/packages/tracing-internal/src/browser/types.ts index 068e4e058d32..c32d08c7f8e2 100644 --- a/packages/tracing-internal/src/browser/types.ts +++ b/packages/tracing-internal/src/browser/types.ts @@ -1,3 +1,6 @@ import { GLOBAL_OBJ } from '@sentry/utils'; -export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; +export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & + // document is not available in all browser environments (webworkers). We make it optional so you have to explicitly check for it + Omit & + Partial>; diff --git a/packages/tracing-internal/src/browser/web-vitals/getLCP.ts b/packages/tracing-internal/src/browser/web-vitals/getLCP.ts index 37e37c01eebd..b80d96832d96 100644 --- a/packages/tracing-internal/src/browser/web-vitals/getLCP.ts +++ b/packages/tracing-internal/src/browser/web-vitals/getLCP.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { WINDOW } from '../types'; import { bindReporter } from './lib/bindReporter'; import { getActivationStart } from './lib/getActivationStart'; import { getVisibilityWatcher } from './lib/getVisibilityWatcher'; @@ -71,7 +72,9 @@ export const onLCP = (onReport: ReportCallback): StopListening | undefined => { // stop LCP observation, it's unreliable since it can be programmatically // generated. See: https://github.com/GoogleChrome/web-vitals/issues/75 ['keydown', 'click'].forEach(type => { - addEventListener(type, stopListening, { once: true, capture: true }); + if (WINDOW.document) { + addEventListener(type, stopListening, { once: true, capture: true }); + } }); onHidden(stopListening, true); diff --git a/packages/tracing-internal/src/browser/web-vitals/lib/getVisibilityWatcher.ts b/packages/tracing-internal/src/browser/web-vitals/lib/getVisibilityWatcher.ts index f47ab0d82cf3..d7aa6dcf082d 100644 --- a/packages/tracing-internal/src/browser/web-vitals/lib/getVisibilityWatcher.ts +++ b/packages/tracing-internal/src/browser/web-vitals/lib/getVisibilityWatcher.ts @@ -19,10 +19,12 @@ import { onHidden } from './onHidden'; let firstHiddenTime = -1; -const initHiddenTime = (): number => { +const initHiddenTime = (): void => { // If the document is hidden and not prerendering, assume it was always // hidden and the page was loaded in the background. - return WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity; + if (WINDOW.document && WINDOW.document.visibilityState) { + firstHiddenTime = WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity; + } }; const trackChanges = (): void => { @@ -40,7 +42,7 @@ export const getVisibilityWatcher = (): { // since navigation start. This isn't a perfect heuristic, but it's the // best we can do until an API is available to support querying past // visibilityState. - firstHiddenTime = initHiddenTime(); + initHiddenTime(); trackChanges(); } return { diff --git a/packages/tracing-internal/src/browser/web-vitals/lib/initMetric.ts b/packages/tracing-internal/src/browser/web-vitals/lib/initMetric.ts index 2fa5854fd6db..c1d36304825a 100644 --- a/packages/tracing-internal/src/browser/web-vitals/lib/initMetric.ts +++ b/packages/tracing-internal/src/browser/web-vitals/lib/initMetric.ts @@ -25,7 +25,7 @@ export const initMetric = (name: Metric['name'], value?: number): Metric => { let navigationType: Metric['navigationType'] = 'navigate'; if (navEntry) { - if (WINDOW.document.prerendering || getActivationStart() > 0) { + if ((WINDOW.document && WINDOW.document.prerendering) || getActivationStart() > 0) { navigationType = 'prerender'; } else { navigationType = navEntry.type.replace(/_/g, '-') as Metric['navigationType']; diff --git a/packages/tracing-internal/src/browser/web-vitals/lib/onHidden.ts b/packages/tracing-internal/src/browser/web-vitals/lib/onHidden.ts index 70152cadd16d..fb7ff6264f76 100644 --- a/packages/tracing-internal/src/browser/web-vitals/lib/onHidden.ts +++ b/packages/tracing-internal/src/browser/web-vitals/lib/onHidden.ts @@ -22,7 +22,7 @@ export interface OnHiddenCallback { export const onHidden = (cb: OnHiddenCallback, once?: boolean): void => { const onHiddenOrPageHide = (event: Event): void => { - if (event.type === 'pagehide' || WINDOW.document.visibilityState === 'hidden') { + if (event.type === 'pagehide' || WINDOW.document!.visibilityState === 'hidden') { cb(event); if (once) { removeEventListener('visibilitychange', onHiddenOrPageHide, true); @@ -30,8 +30,11 @@ export const onHidden = (cb: OnHiddenCallback, once?: boolean): void => { } } }; - addEventListener('visibilitychange', onHiddenOrPageHide, true); - // Some browsers have buggy implementations of visibilitychange, - // so we use pagehide in addition, just to be safe. - addEventListener('pagehide', onHiddenOrPageHide, true); + + if (WINDOW.document) { + addEventListener('visibilitychange', onHiddenOrPageHide, true); + // Some browsers have buggy implementations of visibilitychange, + // so we use pagehide in addition, just to be safe. + addEventListener('pagehide', onHiddenOrPageHide, true); + } };