From ef5199384783ed2833c23f4f1a59479c599d9008 Mon Sep 17 00:00:00 2001 From: SorsOps <80043879+SorsOps@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:34:35 +0200 Subject: [PATCH] fix(browser): Check for existence of instrumentation targets (#8939) There are cases when global objects such as the window object are shimmed that they define properties such as `document`, but the actual value is undefined. This exact situation has been occurring and is causing the instrumentDOM function to throw an error as `'document' in WINDOW` is technically true though the value is falsey. We should rather attempt an actual check of the value being truthy rather than if the property is defined Co-authored-by: Luca Forstner --- packages/utils/src/instrument.ts | 9 +++++---- packages/utils/test/instrument.test.ts | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index 157fe8a50c0b..f3364ba92b9c 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -247,8 +247,9 @@ export function parseFetchArgs(fetchArgs: unknown[]): { method: string; url: str } /** JSDoc */ -function instrumentXHR(): void { - if (!('XMLHttpRequest' in WINDOW)) { +export function instrumentXHR(): void { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (!(WINDOW as any).XMLHttpRequest) { return; } @@ -539,8 +540,8 @@ type InstrumentedElement = Element & { }; /** JSDoc */ -function instrumentDOM(): void { - if (!('document' in WINDOW)) { +export function instrumentDOM(): void { + if (!WINDOW.document) { return; } diff --git a/packages/utils/test/instrument.test.ts b/packages/utils/test/instrument.test.ts index f9088ca1257a..f1ec46b93fb1 100644 --- a/packages/utils/test/instrument.test.ts +++ b/packages/utils/test/instrument.test.ts @@ -1,6 +1,22 @@ -import { parseFetchArgs } from '../src/instrument'; +import { instrumentDOM, instrumentXHR, parseFetchArgs } from '../src/instrument'; + +jest.mock('../src/worldwide', () => ({ + // Return an empty object with undefined properties + getGlobalObject: () => ({ + document: undefined, + XMLHttpRequest: undefined, + }), +})); describe('instrument', () => { + it('instrumentXHR() does not throw if XMLHttpRequest is a key on window but not defined', () => { + expect(instrumentXHR).not.toThrow(); + }); + + it('instrumentDOM() does not throw if XMLHttpRequest is a key on window but not defined', () => { + expect(instrumentDOM).not.toThrow(); + }); + describe('parseFetchArgs', () => { it.each([ ['string URL only', ['http://example.com'], { method: 'GET', url: 'http://example.com' }],