diff --git a/packages/core/src/js/sdk.tsx b/packages/core/src/js/sdk.tsx index 8d26f0268e..98febeecfd 100644 --- a/packages/core/src/js/sdk.tsx +++ b/packages/core/src/js/sdk.tsx @@ -140,9 +140,11 @@ export function init(passedOptions: ReactNativeOptions): void { initialScope: safeFactory(userOptions.initialScope, { loggerMessage: 'The initialScope threw an error' }), }; - if (!('autoInitializeNativeSdk' in userOptions) && RN_GLOBAL_OBJ.__SENTRY_OPTIONS__) { - // Options file is present, native SDK is expected to be initialized + if (!('autoInitializeNativeSdk' in userOptions) && RN_GLOBAL_OBJ.__SENTRY_OPTIONS__ && !__DEV__) { + // Options file is present in a release build, native SDK is expected to be initialized // before JS from the native app entry point (e.g. AppDelegate, MainApplication). + // In dev builds, we always re-initialize from JS to set up the native log bridge + // and provide runtime values (devServerUrl, defaultSidecarUrl, etc.). // eslint-disable-next-line no-console console.info('[Sentry] Using options file. Native SDK is expected to be initialized before JS, skipping automatic native initialization from JS.'); options.autoInitializeNativeSdk = false; diff --git a/packages/core/test/sdk.test.ts b/packages/core/test/sdk.test.ts index 66cf4a927b..6b56df4cb4 100644 --- a/packages/core/test/sdk.test.ts +++ b/packages/core/test/sdk.test.ts @@ -135,10 +135,34 @@ describe('Tests the SDK functionality', () => { expect(usedOptions()?.dsn).toBe('https://key@example.io/code'); }); - it('initializing with __SENTRY_OPTIONS__ disabled native auto initialization', () => { - RN_GLOBAL_OBJ.__SENTRY_OPTIONS__ = {}; - init({}); - expect(usedOptions()?.autoInitializeNativeSdk).toBe(false); + it('does not disable native auto initialization in dev builds even with __SENTRY_OPTIONS__', () => { + // @ts-expect-error __DEV__ is a global + const originalDev = globalThis.__DEV__; + // @ts-expect-error __DEV__ is a global + globalThis.__DEV__ = true; + try { + RN_GLOBAL_OBJ.__SENTRY_OPTIONS__ = {}; + init({}); + expect(usedOptions()?.autoInitializeNativeSdk).toBe(true); + } finally { + // @ts-expect-error __DEV__ is a global + globalThis.__DEV__ = originalDev; + } + }); + + it('disables native auto initialization in release builds with __SENTRY_OPTIONS__', () => { + // @ts-expect-error __DEV__ is a global + const originalDev = globalThis.__DEV__; + // @ts-expect-error __DEV__ is a global + globalThis.__DEV__ = false; + try { + RN_GLOBAL_OBJ.__SENTRY_OPTIONS__ = {}; + init({}); + expect(usedOptions()?.autoInitializeNativeSdk).toBe(false); + } finally { + // @ts-expect-error __DEV__ is a global + globalThis.__DEV__ = originalDev; + } }); it('initializing without __SENTRY_OPTIONS__ enables native auto initialization', () => { @@ -155,7 +179,7 @@ describe('Tests the SDK functionality', () => { expect(usedOptions()?.autoInitializeNativeSdk).toBe(true); }); - it('initializing with __SENTRY_OPTIONS__ keeps native auto initialization false if set', () => { + it('respects explicit autoInitializeNativeSdk false even with __SENTRY_OPTIONS__', () => { RN_GLOBAL_OBJ.__SENTRY_OPTIONS__ = {}; init({ autoInitializeNativeSdk: false,