diff --git a/packages/hub/src/hub.ts b/packages/hub/src/hub.ts index 5aee3969afed..67761953abfa 100644 --- a/packages/hub/src/hub.ts +++ b/packages/hub/src/hub.ts @@ -20,7 +20,15 @@ import { TransactionContext, User, } from '@sentry/types'; -import { consoleSandbox, dateTimestampInSeconds, getGlobalObject, isNodeEnv, logger, uuid4 } from '@sentry/utils'; +import { + consoleSandbox, + dateTimestampInSeconds, + getGlobalObject, + getGlobalSingleton, + isNodeEnv, + logger, + uuid4, +} from '@sentry/utils'; import { IS_DEBUG_BUILD } from './flags'; import { Scope } from './scope'; @@ -617,10 +625,7 @@ function hasHubOnCarrier(carrier: Carrier): boolean { * @hidden */ export function getHubFromCarrier(carrier: Carrier): Hub { - if (carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub) return carrier.__SENTRY__.hub; - carrier.__SENTRY__ = carrier.__SENTRY__ || {}; - carrier.__SENTRY__.hub = new Hub(); - return carrier.__SENTRY__.hub; + return getGlobalSingleton('hub', () => new Hub(), carrier); } /** @@ -631,7 +636,7 @@ export function getHubFromCarrier(carrier: Carrier): Hub { */ export function setHubOnCarrier(carrier: Carrier, hub: Hub): boolean { if (!carrier) return false; - carrier.__SENTRY__ = carrier.__SENTRY__ || {}; - carrier.__SENTRY__.hub = hub; + const __SENTRY__ = (carrier.__SENTRY__ = carrier.__SENTRY__ || {}); + __SENTRY__.hub = hub; return true; } diff --git a/packages/hub/src/scope.ts b/packages/hub/src/scope.ts index 17ce4eef8458..9243cd409b66 100644 --- a/packages/hub/src/scope.ts +++ b/packages/hub/src/scope.ts @@ -18,7 +18,7 @@ import { Transaction, User, } from '@sentry/types'; -import { dateTimestampInSeconds, getGlobalObject, isPlainObject, isThenable, SyncPromise } from '@sentry/utils'; +import { dateTimestampInSeconds, getGlobalSingleton, isPlainObject, isThenable, SyncPromise } from '@sentry/utils'; import { Session } from './session'; @@ -522,12 +522,7 @@ export class Scope implements ScopeInterface { * Returns the global event processors. */ function getGlobalEventProcessors(): EventProcessor[] { - /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ - const global = getGlobalObject(); - global.__SENTRY__ = global.__SENTRY__ || {}; - global.__SENTRY__.globalEventProcessors = global.__SENTRY__.globalEventProcessors || []; - return global.__SENTRY__.globalEventProcessors; - /* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ + return getGlobalSingleton('globalEventProcessors', () => []); } /** diff --git a/packages/utils/src/global.ts b/packages/utils/src/global.ts index 7ede3f8fe58e..a8b4b7ce0b0e 100644 --- a/packages/utils/src/global.ts +++ b/packages/utils/src/global.ts @@ -44,3 +44,21 @@ export function getGlobalObject(): T & SentryGlobal { : fallbackGlobalObject ) as T & SentryGlobal; } + +/** + * Returns a global singleton contained in the global `__SENTRY__` object. + * + * If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory + * function and added to the `__SENTRY__` object. + * + * @param name name of the global singleton on __SENTRY__ + * @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__` + * @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `getGlobalObject`'s return value + * @returns the singleton + */ +export function getGlobalSingleton(name: keyof SentryGlobal['__SENTRY__'], creator: () => T, obj?: unknown): T { + const global = (obj || getGlobalObject()) as SentryGlobal; + const __SENTRY__ = (global.__SENTRY__ = global.__SENTRY__ || {}); + const singleton = __SENTRY__[name] || (__SENTRY__[name] = creator()); + return singleton; +}