Skip to content

Commit bf323b1

Browse files
authored
ref(core)!: Remove backwards compatible SentryCarrier type (#14697)
I do not really think this is breaking or has any impact on any user code, but to be on the safe side, we can remove this in v9. The one actual breaking thing is to also move the `encodePolyfill` / `decodePolyfill` code to the versioned carrier - this was before still on the global, making this a bit harder than necessary. In v9, this will have to be set on the versioned carrier the same as other things - cc @krystofwoldrich
1 parent 4625569 commit bf323b1

File tree

11 files changed

+54
-85
lines changed

11 files changed

+54
-85
lines changed

packages/core/src/carrier.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { AsyncContextStack } from './asyncContext/stackStrategy';
22
import type { AsyncContextStrategy } from './asyncContext/types';
3-
import type { Client, Integration, MetricsAggregator, Scope } from './types-hoist';
3+
import type { Client, MetricsAggregator, Scope } from './types-hoist';
4+
import type { Logger } from './utils-hoist/logger';
45
import { SDK_VERSION } from './utils-hoist/version';
56
import { GLOBAL_OBJ } from './utils-hoist/worldwide';
67

@@ -16,21 +17,20 @@ type VersionedCarrier = {
1617
version?: string;
1718
} & Record<Exclude<string, 'version'>, SentryCarrier>;
1819

19-
interface SentryCarrier {
20+
export interface SentryCarrier {
2021
acs?: AsyncContextStrategy;
2122
stack?: AsyncContextStack;
2223

2324
globalScope?: Scope;
2425
defaultIsolationScope?: Scope;
2526
defaultCurrentScope?: Scope;
2627
globalMetricsAggregators?: WeakMap<Client, MetricsAggregator> | undefined;
28+
logger?: Logger;
2729

28-
// TODO(v9): Remove these properties - they are no longer used and were left over in v8
29-
integrations?: Integration[];
30-
extensions?: {
31-
// eslint-disable-next-line @typescript-eslint/ban-types
32-
[key: string]: Function;
33-
};
30+
/** Overwrites TextEncoder used in `@sentry/core`, need for `react-native@0.73` and older */
31+
encodePolyfill?: (input: string) => Uint8Array;
32+
/** Overwrites TextDecoder used in `@sentry/core`, need for `react-native@0.73` and older */
33+
decodePolyfill?: (input: Uint8Array) => string;
3434
}
3535

3636
/**
@@ -57,3 +57,25 @@ export function getSentryCarrier(carrier: Carrier): SentryCarrier {
5757
// rather than what's set in .version so that "this" SDK always gets its carrier
5858
return (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
5959
}
60+
61+
/**
62+
* Returns a global singleton contained in the global `__SENTRY__[]` object.
63+
*
64+
* If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
65+
* function and added to the `__SENTRY__` object.
66+
*
67+
* @param name name of the global singleton on __SENTRY__
68+
* @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
69+
* @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
70+
* @returns the singleton
71+
*/
72+
export function getGlobalSingleton<Prop extends keyof SentryCarrier>(
73+
name: Prop,
74+
creator: () => NonNullable<SentryCarrier[Prop]>,
75+
obj = GLOBAL_OBJ,
76+
): NonNullable<SentryCarrier[Prop]> {
77+
const __SENTRY__ = (obj.__SENTRY__ = obj.__SENTRY__ || {});
78+
const carrier = (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
79+
// Note: We do not want to set `carrier.version` here, as this may be called before any `init` is called, e.g. for the default scopes
80+
return carrier[name] || (carrier[name] = creator());
81+
}

packages/core/src/currentScopes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { getAsyncContextStrategy } from './asyncContext';
22
import { getMainCarrier } from './carrier';
3+
import { getGlobalSingleton } from './carrier';
34
import { Scope as ScopeClass } from './scope';
45
import type { Client, Scope, TraceContext } from './types-hoist';
56
import { dropUndefinedKeys } from './utils-hoist/object';
6-
import { getGlobalSingleton } from './utils-hoist/worldwide';
77

88
/**
99
* Get the currently active scope.

packages/core/src/defaultScopes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { getGlobalSingleton } from './carrier';
12
import { Scope as ScopeClass } from './scope';
23
import type { Scope } from './types-hoist';
3-
import { getGlobalSingleton } from './utils-hoist/worldwide';
44

55
/** Get the default current scope. */
66
export function getDefaultCurrentScope(): Scope {

packages/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export {
4545
getDefaultIsolationScope,
4646
} from './defaultScopes';
4747
export { setAsyncContextStrategy } from './asyncContext';
48-
export { getMainCarrier } from './carrier';
48+
export { getGlobalSingleton, getMainCarrier } from './carrier';
4949
export { makeSession, closeSession, updateSession } from './session';
5050
// eslint-disable-next-line deprecation/deprecation
5151
export { SessionFlusher } from './sessionflusher';

packages/core/src/metrics/exports.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
import { getGlobalSingleton } from '../carrier';
12
import { getClient } from '../currentScopes';
23
import { DEBUG_BUILD } from '../debug-build';
34
import { startSpanManual } from '../tracing';
45
import type { Client, DurationUnit, MetricData, MetricsAggregator as MetricsAggregatorInterface } from '../types-hoist';
56
import { logger } from '../utils-hoist/logger';
67
import { timestampInSeconds } from '../utils-hoist/time';
7-
import { getGlobalSingleton } from '../utils-hoist/worldwide';
88
import { handleCallbackErrors } from '../utils/handleCallbackErrors';
99
import { getActiveSpan, getRootSpan, spanToJSON } from '../utils/spanUtils';
1010
import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, GAUGE_METRIC_TYPE, SET_METRIC_TYPE } from './constants';
@@ -23,9 +23,9 @@ function getMetricsAggregatorForClient(
2323
client: Client,
2424
Aggregator: MetricsAggregatorConstructor,
2525
): MetricsAggregatorInterface {
26-
const globalMetricsAggregators = getGlobalSingleton<WeakMap<Client, MetricsAggregatorInterface>>(
26+
const globalMetricsAggregators = getGlobalSingleton(
2727
'globalMetricsAggregators',
28-
() => new WeakMap(),
28+
() => new WeakMap<Client, MetricsAggregatorInterface>(),
2929
);
3030

3131
const aggregator = globalMetricsAggregators.get(client);

packages/core/src/utils-hoist/envelope.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getSentryCarrier } from '../carrier';
12
import type {
23
Attachment,
34
AttachmentItem,
@@ -74,18 +75,16 @@ export function envelopeContainsItemType(envelope: Envelope, types: EnvelopeItem
7475
* Encode a string to UTF8 array.
7576
*/
7677
function encodeUTF8(input: string): Uint8Array {
77-
return GLOBAL_OBJ.__SENTRY__ && GLOBAL_OBJ.__SENTRY__.encodePolyfill
78-
? GLOBAL_OBJ.__SENTRY__.encodePolyfill(input)
79-
: new TextEncoder().encode(input);
78+
const carrier = getSentryCarrier(GLOBAL_OBJ);
79+
return carrier.encodePolyfill ? carrier.encodePolyfill(input) : new TextEncoder().encode(input);
8080
}
8181

8282
/**
8383
* Decode a UTF8 array to string.
8484
*/
8585
function decodeUTF8(input: Uint8Array): string {
86-
return GLOBAL_OBJ.__SENTRY__ && GLOBAL_OBJ.__SENTRY__.decodePolyfill
87-
? GLOBAL_OBJ.__SENTRY__.decodePolyfill(input)
88-
: new TextDecoder().decode(input);
86+
const carrier = getSentryCarrier(GLOBAL_OBJ);
87+
return carrier.decodePolyfill ? carrier.decodePolyfill(input) : new TextDecoder().decode(input);
8988
}
9089

9190
/**

packages/core/src/utils-hoist/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export { getBreadcrumbLogLevelFromHttpStatusCode } from './breadcrumb-log-level'
55
export { getComponentName, getDomElement, getLocationHref, htmlTreeAsString } from './browser';
66
export { dsnFromString, dsnToString, makeDsn } from './dsn';
77
export { SentryError } from './error';
8-
export { GLOBAL_OBJ, getGlobalSingleton } from './worldwide';
8+
export { GLOBAL_OBJ } from './worldwide';
99
export type { InternalGlobal } from './worldwide';
1010
export { addConsoleInstrumentationHandler } from './instrument/console';
1111
export { addFetchEndInstrumentationHandler, addFetchInstrumentationHandler } from './instrument/fetch';

packages/core/src/utils-hoist/logger.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { getGlobalSingleton } from '../carrier';
12
import type { ConsoleLevel } from '../types-hoist';
2-
33
import { DEBUG_BUILD } from './debug-build';
4-
import { GLOBAL_OBJ, getGlobalSingleton } from './worldwide';
4+
import { GLOBAL_OBJ } from './worldwide';
55

66
/** Prefix for logging strings */
77
const PREFIX = 'Sentry Logger ';
@@ -24,7 +24,7 @@ export const originalConsoleMethods: {
2424
[key in ConsoleLevel]?: (...args: unknown[]) => void;
2525
} = {};
2626

27-
/** JSDoc */
27+
/** A Sentry Logger instance. */
2828
export interface Logger extends LoggerConsoleMethods {
2929
disable(): void;
3030
enable(): void;

packages/core/src/utils-hoist/worldwide.ts

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,8 @@
1212

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

15-
import type { Client, MetricsAggregator, Scope } from '../types-hoist';
16-
15+
import type { Carrier } from '../carrier';
1716
import type { SdkSource } from './env';
18-
import type { logger } from './logger';
19-
import { SDK_VERSION } from './version';
20-
21-
interface SentryCarrier {
22-
acs?: any;
23-
stack?: any;
24-
25-
globalScope?: Scope;
26-
defaultIsolationScope?: Scope;
27-
defaultCurrentScope?: Scope;
28-
globalMetricsAggregators?: WeakMap<Client, MetricsAggregator> | undefined;
29-
logger?: typeof logger;
30-
31-
/** Overwrites TextEncoder used in `@sentry/core`, need for `react-native@0.73` and older */
32-
encodePolyfill?: (input: string) => Uint8Array;
33-
/** Overwrites TextDecoder used in `@sentry/core`, need for `react-native@0.73` and older */
34-
decodePolyfill?: (input: Uint8Array) => string;
35-
}
36-
37-
// TODO(v9): Clean up or remove this type
38-
type BackwardsCompatibleSentryCarrier = SentryCarrier & {
39-
// pre-v7 hub (replaced by .stack)
40-
hub: any;
41-
integrations?: any[];
42-
logger: any;
43-
extensions?: {
44-
/** Extension methods for the hub, which are bound to the current Hub instance */
45-
// eslint-disable-next-line @typescript-eslint/ban-types
46-
[key: string]: Function;
47-
};
48-
};
4917

5018
/** Internal global with common properties and Sentry extensions */
5119
export type InternalGlobal = {
@@ -73,35 +41,14 @@ export type InternalGlobal = {
7341
* file.
7442
*/
7543
_sentryDebugIds?: Record<string, string>;
76-
__SENTRY__: Record<Exclude<string, 'version'>, SentryCarrier> & {
77-
version?: string;
78-
} & BackwardsCompatibleSentryCarrier;
7944
/**
8045
* Raw module metadata that is injected by bundler plugins.
8146
*
8247
* Keys are `error.stack` strings, values are the metadata.
8348
*/
8449
_sentryModuleMetadata?: Record<string, any>;
8550
_sentryEsmLoaderHookRegistered?: boolean;
86-
};
51+
} & Carrier;
8752

8853
/** Get's the global object for the current JavaScript runtime */
8954
export const GLOBAL_OBJ = globalThis as unknown as InternalGlobal;
90-
91-
/**
92-
* Returns a global singleton contained in the global `__SENTRY__[]` object.
93-
*
94-
* If the singleton doesn't already exist in `__SENTRY__`, it will be created using the given factory
95-
* function and added to the `__SENTRY__` object.
96-
*
97-
* @param name name of the global singleton on __SENTRY__
98-
* @param creator creator Factory function to create the singleton if it doesn't already exist on `__SENTRY__`
99-
* @param obj (Optional) The global object on which to look for `__SENTRY__`, if not `GLOBAL_OBJ`'s return value
100-
* @returns the singleton
101-
*/
102-
export function getGlobalSingleton<T>(name: keyof SentryCarrier, creator: () => T, obj?: unknown): T {
103-
const gbl = (obj || GLOBAL_OBJ) as InternalGlobal;
104-
const __SENTRY__ = (gbl.__SENTRY__ = gbl.__SENTRY__ || {});
105-
const versionedCarrier = (__SENTRY__[SDK_VERSION] = __SENTRY__[SDK_VERSION] || {});
106-
return versionedCarrier[name] || (versionedCarrier[name] = creator());
107-
}

packages/core/test/lib/hint.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ describe('Hint', () => {
1414

1515
afterEach(() => {
1616
jest.clearAllMocks();
17-
// @ts-expect-error for testing
1817
delete GLOBAL_OBJ.__SENTRY__;
1918
});
2019

packages/core/test/utils-hoist/envelope.test.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
spanToJSON,
88
} from '@sentry/core';
99
import { SentrySpan } from '@sentry/core';
10+
import { getSentryCarrier } from '../../src/carrier';
1011
import {
1112
addItemToEnvelope,
1213
createEnvelope,
@@ -107,17 +108,18 @@ describe('envelope', () => {
107108
{
108109
name: 'with TextEncoder/Decoder polyfill',
109110
before: () => {
110-
GLOBAL_OBJ.__SENTRY__ = {} as InternalGlobal['__SENTRY__'];
111-
GLOBAL_OBJ.__SENTRY__.encodePolyfill = jest.fn<Uint8Array, [string]>((input: string) =>
111+
GLOBAL_OBJ.__SENTRY__ = {};
112+
113+
getSentryCarrier(GLOBAL_OBJ).encodePolyfill = jest.fn<Uint8Array, [string]>((input: string) =>
112114
new TextEncoder().encode(input),
113115
);
114-
GLOBAL_OBJ.__SENTRY__.decodePolyfill = jest.fn<string, [Uint8Array]>((input: Uint8Array) =>
116+
getSentryCarrier(GLOBAL_OBJ).decodePolyfill = jest.fn<string, [Uint8Array]>((input: Uint8Array) =>
115117
new TextDecoder().decode(input),
116118
);
117119
},
118120
after: () => {
119-
expect(GLOBAL_OBJ.__SENTRY__.encodePolyfill).toHaveBeenCalled();
120-
expect(GLOBAL_OBJ.__SENTRY__.decodePolyfill).toHaveBeenCalled();
121+
expect(getSentryCarrier(GLOBAL_OBJ).encodePolyfill).toHaveBeenCalled();
122+
expect(getSentryCarrier(GLOBAL_OBJ).decodePolyfill).toHaveBeenCalled();
121123
},
122124
},
123125
{

0 commit comments

Comments
 (0)