Skip to content

Commit ee4091e

Browse files
authored
fix(browser): Don't assume window.document is available (#11602)
1 parent 39c8290 commit ee4091e

File tree

8 files changed

+33
-26
lines changed

8 files changed

+33
-26
lines changed
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
import { GLOBAL_OBJ } from '@sentry/utils';
22

3-
export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;
3+
export const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ &
4+
// document is not available in all browser environments (webworkers). We make it optional so you have to explicitly check for it
5+
Omit<Window, 'document'> &
6+
Partial<Pick<Window, 'document'>>;

packages/browser-utils/src/metrics/web-vitals/getLCP.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { WINDOW } from '../types';
1718
import { bindReporter } from './lib/bindReporter';
1819
import { getActivationStart } from './lib/getActivationStart';
1920
import { getVisibilityWatcher } from './lib/getVisibilityWatcher';
@@ -82,10 +83,12 @@ export const onLCP = (onReport: LCPReportCallback, opts: ReportOpts = {}) => {
8283
// stops LCP observation, it's unreliable since it can be programmatically
8384
// generated. See: https://github.com/GoogleChrome/web-vitals/issues/75
8485
['keydown', 'click'].forEach(type => {
85-
// Wrap in a setTimeout so the callback is run in a separate task
86-
// to avoid extending the keyboard/click handler to reduce INP impact
87-
// https://github.com/GoogleChrome/web-vitals/issues/383
88-
addEventListener(type, () => setTimeout(stopListening, 0), true);
86+
if (WINDOW.document) {
87+
// Wrap in a setTimeout so the callback is run in a separate task
88+
// to avoid extending the keyboard/click handler to reduce INP impact
89+
// https://github.com/GoogleChrome/web-vitals/issues/383
90+
addEventListener(type, () => setTimeout(stopListening, 0), true);
91+
}
8992
});
9093

9194
onHidden(stopListening);

packages/browser-utils/src/metrics/web-vitals/lib/getVisibilityWatcher.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ const initHiddenTime = () => {
2424
// that visibility state is always 'hidden' during prerendering, so we have
2525
// to ignore that case until prerendering finishes (see: `prerenderingchange`
2626
// event logic below).
27-
return WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity;
27+
firstHiddenTime = WINDOW.document!.visibilityState === 'hidden' && !WINDOW.document!.prerendering ? 0 : Infinity;
2828
};
2929

3030
const onVisibilityUpdate = (event: Event) => {
3131
// If the document is 'hidden' and no previous hidden timestamp has been
3232
// set, update it based on the current event data.
33-
if (WINDOW.document.visibilityState === 'hidden' && firstHiddenTime > -1) {
33+
if (WINDOW.document!.visibilityState === 'hidden' && firstHiddenTime > -1) {
3434
// If the event is a 'visibilitychange' event, it means the page was
3535
// visible prior to this change, so the event timestamp is the first
3636
// hidden time.
@@ -41,7 +41,8 @@ const onVisibilityUpdate = (event: Event) => {
4141
firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;
4242

4343
// Remove all listeners now that a `firstHiddenTime` value has been set.
44-
removeChangeListeners();
44+
removeEventListener('visibilitychange', onVisibilityUpdate, true);
45+
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
4546
}
4647
};
4748

@@ -54,18 +55,13 @@ const addChangeListeners = () => {
5455
addEventListener('prerenderingchange', onVisibilityUpdate, true);
5556
};
5657

57-
const removeChangeListeners = () => {
58-
removeEventListener('visibilitychange', onVisibilityUpdate, true);
59-
removeEventListener('prerenderingchange', onVisibilityUpdate, true);
60-
};
61-
6258
export const getVisibilityWatcher = () => {
63-
if (firstHiddenTime < 0) {
59+
if (WINDOW.document && firstHiddenTime < 0) {
6460
// If the document is hidden when this code runs, assume it was hidden
6561
// since navigation start. This isn't a perfect heuristic, but it's the
6662
// best we can do until an API is available to support querying past
6763
// visibilityState.
68-
firstHiddenTime = initHiddenTime();
64+
initHiddenTime();
6965
addChangeListeners();
7066
}
7167
return {

packages/browser-utils/src/metrics/web-vitals/lib/initMetric.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export const initMetric = <MetricName extends MetricType['name']>(name: MetricNa
2525
let navigationType: MetricType['navigationType'] = 'navigate';
2626

2727
if (navEntry) {
28-
if (WINDOW.document.prerendering || getActivationStart() > 0) {
28+
if ((WINDOW.document && WINDOW.document.prerendering) || getActivationStart() > 0) {
2929
navigationType = 'prerender';
30-
} else if (WINDOW.document.wasDiscarded) {
30+
} else if (WINDOW.document && WINDOW.document.wasDiscarded) {
3131
navigationType = 'restore';
3232
} else if (navEntry.type) {
3333
navigationType = navEntry.type.replace(/_/g, '-') as MetricType['navigationType'];

packages/browser-utils/src/metrics/web-vitals/lib/onHidden.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ export interface OnHiddenCallback {
2222

2323
export const onHidden = (cb: OnHiddenCallback) => {
2424
const onHiddenOrPageHide = (event: Event) => {
25-
if (event.type === 'pagehide' || WINDOW.document.visibilityState === 'hidden') {
25+
if (event.type === 'pagehide' || (WINDOW.document && WINDOW.document.visibilityState === 'hidden')) {
2626
cb(event);
2727
}
2828
};
29-
addEventListener('visibilitychange', onHiddenOrPageHide, true);
30-
// Some browsers have buggy implementations of visibilitychange,
31-
// so we use pagehide in addition, just to be safe.
32-
addEventListener('pagehide', onHiddenOrPageHide, true);
29+
30+
if (WINDOW.document) {
31+
addEventListener('visibilitychange', onHiddenOrPageHide, true);
32+
// Some browsers have buggy implementations of visibilitychange,
33+
// so we use pagehide in addition, just to be safe.
34+
addEventListener('pagehide', onHiddenOrPageHide, true);
35+
}
3336
};

packages/browser-utils/src/metrics/web-vitals/lib/whenActivated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import { WINDOW } from '../../types';
1818

1919
export const whenActivated = (callback: () => void) => {
20-
if (WINDOW.document.prerendering) {
20+
if (WINDOW.document && WINDOW.document.prerendering) {
2121
addEventListener('prerenderingchange', () => callback(), true);
2222
} else {
2323
callback();

packages/browser-utils/src/metrics/web-vitals/onTTFB.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const TTFBThresholds: MetricRatingThresholds = [800, 1800];
3030
* @param callback
3131
*/
3232
const whenReady = (callback: () => void) => {
33-
if (WINDOW.document.prerendering) {
33+
if (WINDOW.document && WINDOW.document.prerendering) {
3434
whenActivated(() => whenReady(callback));
35-
} else if (WINDOW.document.readyState !== 'complete') {
35+
} else if (WINDOW.document && WINDOW.document.readyState !== 'complete') {
3636
addEventListener('load', () => whenReady(callback), true);
3737
} else {
3838
// Queue a task so the callback runs after `loadEventEnd`.

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ function registerInteractionListener(
448448
};
449449

450450
['click'].forEach(type => {
451-
addEventListener(type, registerInteractionTransaction, { once: false, capture: true });
451+
if (WINDOW.document) {
452+
addEventListener(type, registerInteractionTransaction, { once: false, capture: true });
453+
}
452454
});
453455
}

0 commit comments

Comments
 (0)