From f2ae1329034e1e7d477f890d9b67e2b18b586f4d Mon Sep 17 00:00:00 2001 From: Said Atrahouch Date: Sun, 3 Nov 2024 11:29:49 +0100 Subject: [PATCH] fix(hasConfigurableGlobal): handle existing globals with undefined value (#669) Co-authored-by: Artem Zakharchenko --- src/utils/hasConfigurableGlobal.test.ts | 24 ++++++++++++++++++++++++ src/utils/hasConfigurableGlobal.ts | 14 ++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/utils/hasConfigurableGlobal.test.ts b/src/utils/hasConfigurableGlobal.test.ts index 0799246e..9bade249 100644 --- a/src/utils/hasConfigurableGlobal.test.ts +++ b/src/utils/hasConfigurableGlobal.test.ts @@ -26,6 +26,30 @@ it('returns false if the global property does not exist', () => { expect(hasConfigurableGlobal('_non-existing')).toBe(false) }) +it('returns false for existing global with undefined as a value', () => { + Object.defineProperty(global, '_existsAndUndefined', { + value: undefined, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsAndUndefined')).toBe(false) +}) + +it('returns false for existing global with null as a value', () => { + Object.defineProperty(global, '_existsAndNull', { + value: null, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsAndNull')).toBe(false) +}) + +it('returns false for existing global with a getter that returns undefined', () => { + Object.defineProperty(global, '_existsGetterUndefined', { + get: () => undefined, + configurable: true, + }) + expect(hasConfigurableGlobal('_existsGetterUndefined')).toBe(false) +}) + it('returns false and prints an error for implicitly non-configurable global property', () => { Object.defineProperty(global, '_implicitlyNonConfigurable', { value: 'something', diff --git a/src/utils/hasConfigurableGlobal.ts b/src/utils/hasConfigurableGlobal.ts index 134efd6c..c8304533 100644 --- a/src/utils/hasConfigurableGlobal.ts +++ b/src/utils/hasConfigurableGlobal.ts @@ -5,10 +5,24 @@ export function hasConfigurableGlobal(propertyName: string): boolean { const descriptor = Object.getOwnPropertyDescriptor(globalThis, propertyName) + // The property is not set at all. if (typeof descriptor === 'undefined') { return false } + // The property is set to a getter that returns undefined. + if ( + typeof descriptor.get === 'function' && + typeof descriptor.get() === 'undefined' + ) { + return false + } + + // The property is set to a value equal to undefined. + if (typeof descriptor.get === 'undefined' && descriptor.value == null) { + return false + } + if (typeof descriptor.set === 'undefined' && !descriptor.configurable) { console.error( `[MSW] Failed to apply interceptor: the global \`${propertyName}\` property is non-configurable. This is likely an issue with your environment. If you are using a framework, please open an issue about this in their repository.`