Skip to content

Commit 34d7e41

Browse files
authored
feat(core): Move globals to __SENTRY__ singleton (#11034)
This PR moves `globalScope` and `globalMetricsAggregators` to the `__SENTRY__` global singleton. This means that if the files that these globals are in get bundled or different versions of `@sentry/core` are used, we can be sure that they'll still access the same globals.
1 parent 81da58a commit 34d7e41

File tree

9 files changed

+28
-48
lines changed

9 files changed

+28
-48
lines changed

packages/core/src/currentScopes.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import type { Scope } from '@sentry/types';
22
import type { Client } from '@sentry/types';
3+
import { getGlobalSingleton } from '@sentry/utils';
34
import { getMainCarrier } from './asyncContext';
45
import { getAsyncContextStrategy } from './hub';
56
import { Scope as ScopeClass } from './scope';
67

7-
/**
8-
* The global scope is kept in this module.
9-
* When accessing it, we'll make sure to set one if none is currently present.
10-
*/
11-
let globalScope: Scope | undefined;
12-
138
/**
149
* Get the currently active scope.
1510
*/
@@ -34,20 +29,7 @@ export function getIsolationScope(): Scope {
3429
* This scope is applied to _all_ events.
3530
*/
3631
export function getGlobalScope(): Scope {
37-
if (!globalScope) {
38-
globalScope = new ScopeClass();
39-
}
40-
41-
return globalScope;
42-
}
43-
44-
/**
45-
* This is mainly needed for tests.
46-
* DO NOT USE this, as this is an internal API and subject to change.
47-
* @hidden
48-
*/
49-
export function setGlobalScope(scope: Scope | undefined): void {
50-
globalScope = scope;
32+
return getGlobalSingleton('globalScope', () => new ScopeClass());
5133
}
5234

5335
/**

packages/core/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export {
4343
getCurrentScope,
4444
getIsolationScope,
4545
getGlobalScope,
46-
setGlobalScope,
4746
withScope,
4847
withIsolationScope,
4948
getClient,

packages/core/src/metrics/exports.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
MetricsAggregator as MetricsAggregatorInterface,
55
Primitive,
66
} from '@sentry/types';
7-
import { logger } from '@sentry/utils';
7+
import { getGlobalSingleton, logger } from '@sentry/utils';
88
import { getCurrentScope } from '../currentScopes';
99
import { getClient } from '../currentScopes';
1010
import { DEBUG_BUILD } from '../debug-build';
@@ -23,11 +23,6 @@ type MetricsAggregatorConstructor = {
2323
new (client: Client): MetricsAggregatorInterface;
2424
};
2525

26-
/**
27-
* A metrics aggregator instance per Client.
28-
*/
29-
let globalMetricsAggregators: WeakMap<Client, MetricsAggregatorInterface> | undefined;
30-
3126
/**
3227
* Gets the metrics aggregator for a given client.
3328
* @param client The client for which to get the metrics aggregator.
@@ -37,9 +32,10 @@ function getMetricsAggregatorForClient(
3732
client: Client,
3833
Aggregator: MetricsAggregatorConstructor,
3934
): MetricsAggregatorInterface {
40-
if (!globalMetricsAggregators) {
41-
globalMetricsAggregators = new WeakMap();
42-
}
35+
const globalMetricsAggregators = getGlobalSingleton<WeakMap<Client, MetricsAggregatorInterface>>(
36+
'globalMetricsAggregators',
37+
() => new WeakMap(),
38+
);
4339

4440
const aggregator = globalMetricsAggregators.get(client);
4541
if (aggregator) {

packages/core/test/lib/base.test.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import type { Client, Envelope, Event } from '@sentry/types';
22
import { SentryError, SyncPromise, dsnToString, logger } from '@sentry/utils';
33

4-
import {
5-
Scope,
6-
addBreadcrumb,
7-
getCurrentScope,
8-
getIsolationScope,
9-
makeSession,
10-
setCurrentClient,
11-
setGlobalScope,
12-
} from '../../src';
4+
import { Scope, addBreadcrumb, getCurrentScope, getIsolationScope, makeSession, setCurrentClient } from '../../src';
135
import * as integrationModule from '../../src/integration';
146
import { TestClient, getDefaultTestClientOptions } from '../mocks/client';
157
import { AdHocIntegration, TestIntegration } from '../mocks/integration';
168
import { makeFakeTransport } from '../mocks/transport';
9+
import { clearGlobalScope } from './clear-global-scope';
1710

1811
const PUBLIC_DSN = 'https://username@domain/123';
1912
// eslint-disable-next-line no-var
@@ -62,7 +55,7 @@ describe('BaseClient', () => {
6255
beforeEach(() => {
6356
TestClient.sendEventCalled = undefined;
6457
TestClient.instance = undefined;
65-
setGlobalScope(undefined);
58+
clearGlobalScope();
6659
getCurrentScope().clear();
6760
getCurrentScope().setClient(undefined);
6861
getIsolationScope().clear();
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { GLOBAL_OBJ } from '@sentry/utils';
2+
3+
export function clearGlobalScope() {
4+
const __SENTRY__ = (GLOBAL_OBJ.__SENTRY__ = GLOBAL_OBJ.__SENTRY__ || {});
5+
__SENTRY__.globalScope = undefined;
6+
}

packages/core/test/lib/prepareEvent.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
ScopeContext,
1010
} from '@sentry/types';
1111
import { GLOBAL_OBJ, createStackParser } from '@sentry/utils';
12-
import { getGlobalScope, getIsolationScope, setGlobalScope } from '../../src';
12+
import { getGlobalScope, getIsolationScope } from '../../src';
1313

1414
import { Scope } from '../../src/scope';
1515
import {
@@ -18,6 +18,7 @@ import {
1818
parseEventHintOrCaptureContext,
1919
prepareEvent,
2020
} from '../../src/utils/prepareEvent';
21+
import { clearGlobalScope } from './clear-global-scope';
2122

2223
describe('applyDebugIds', () => {
2324
afterEach(() => {
@@ -191,7 +192,7 @@ describe('parseEventHintOrCaptureContext', () => {
191192

192193
describe('prepareEvent', () => {
193194
beforeEach(() => {
194-
setGlobalScope(undefined);
195+
clearGlobalScope();
195196
getIsolationScope().clear();
196197
});
197198

packages/core/test/lib/scope.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import {
44
getCurrentScope,
55
getGlobalScope,
66
getIsolationScope,
7-
setGlobalScope,
87
withIsolationScope,
98
} from '../../src';
109

1110
import { Scope } from '../../src/scope';
1211
import { TestClient, getDefaultTestClientOptions } from '../mocks/client';
12+
import { clearGlobalScope } from './clear-global-scope';
1313

1414
describe('Scope', () => {
1515
beforeEach(() => {
16-
setGlobalScope(undefined);
16+
clearGlobalScope();
1717
});
1818

1919
it('allows to create & update a scope', () => {
@@ -491,7 +491,7 @@ describe('Scope', () => {
491491

492492
describe('global scope', () => {
493493
beforeEach(() => {
494-
setGlobalScope(undefined);
494+
clearGlobalScope();
495495
});
496496

497497
it('works', () => {

packages/node-experimental/test/integration/scope.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { getCurrentScope, setGlobalScope } from '@sentry/core';
1+
import { getCurrentScope } from '@sentry/core';
22
import { getClient, getSpanScopes } from '@sentry/opentelemetry';
3+
import { clearGlobalScope } from '../../../core/test/lib/clear-global-scope';
34

45
import * as Sentry from '../../src/';
56
import type { NodeClient } from '../../src/sdk/client';
@@ -246,7 +247,7 @@ describe('Integration | Scope', () => {
246247

247248
describe('global scope', () => {
248249
beforeEach(() => {
249-
setGlobalScope(undefined);
250+
clearGlobalScope();
250251
});
251252

252253
it('works before calling init', () => {

packages/utils/src/worldwide.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
/* eslint-disable @typescript-eslint/no-explicit-any */
1414

15-
import type { Integration } from '@sentry/types';
15+
import type { Client, Integration, MetricsAggregator, Scope } from '@sentry/types';
1616

1717
import type { SdkSource } from './env';
1818

@@ -54,6 +54,8 @@ export interface InternalGlobal {
5454
// eslint-disable-next-line @typescript-eslint/ban-types
5555
[key: string]: Function;
5656
};
57+
globalScope: Scope | undefined;
58+
globalMetricsAggregators: WeakMap<Client, MetricsAggregator> | undefined;
5759
};
5860
/**
5961
* Raw module metadata that is injected by bundler plugins.

0 commit comments

Comments
 (0)