Skip to content

Commit c35c86b

Browse files
fix(modules): Modules loaders integration handles native error and event modules are prioritised over native (#2730)
1 parent 4b32ab4 commit c35c86b

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixes
66

77
- Missing `originalException` in `beforeSend` for events from react native error handler ([#2706](https://github.com/getsentry/sentry-react-native/pull/2706))
8+
- ModulesLoader integration returns original event if native is not available and event modules overwrite native modules ([#2730](https://github.com/getsentry/sentry-react-native/pull/2730))
89

910
### Dependencies
1011

src/js/integrations/modulesloader.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Event,EventProcessor, Integration } from '@sentry/types';
2+
import { logger } from '@sentry/utils';
23

34
import { NATIVE } from '../wrapper';
45

@@ -23,13 +24,17 @@ export class ModulesLoader implements Integration {
2324

2425
addGlobalEventProcessor(async (event: Event) => {
2526
if (!isSetup) {
26-
modules = await NATIVE.fetchModules();
27+
try {
28+
modules = await NATIVE.fetchModules();
29+
} catch (e) {
30+
logger.log(`Failed to get modules from native: ${e}`);
31+
}
2732
isSetup = true;
2833
}
2934
if (modules) {
3035
event.modules = {
31-
...event.modules,
3236
...modules,
37+
...event.modules,
3338
};
3439
}
3540
return event;

src/js/wrapper.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ interface SentryNativeWrapper {
8484
*/
8585
export const NATIVE: SentryNativeWrapper = {
8686
async fetchModules(): Promise<Record<string, string> | null> {
87+
if (!this.enableNative) {
88+
throw this._DisabledNativeError;
89+
}
8790
if (!this._isModuleLoaded(RNSentry)) {
8891
throw this._NativeClientError;
8992
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Event, EventHint } from '@sentry/types';
2+
3+
import { ModulesLoader } from '../../src/js/integrations';
4+
import { NATIVE } from '../../src/js/wrapper';
5+
6+
jest.mock('../../src/js/wrapper');
7+
8+
describe('Modules Loader', () => {
9+
let integration: ModulesLoader;
10+
11+
beforeEach(() => {
12+
integration = new ModulesLoader();
13+
});
14+
15+
it('integration event processor does not throw on native error', async () => {
16+
(NATIVE.fetchModules as jest.Mock).mockImplementation(() => { throw new Error('Test Error') });
17+
const mockEvent: Event = {
18+
modules: {
19+
eventModule: 'eventModuleVersion',
20+
},
21+
};
22+
const processedEvent = await executeIntegrationFor(mockEvent);
23+
24+
expect(processedEvent).toEqual(mockEvent);
25+
});
26+
27+
it('merges event modules with native modules', async () => {
28+
(NATIVE.fetchModules as jest.Mock).mockImplementation(() => ({
29+
nativeModules: 'nativeModuleVersion',
30+
duplicateModule: 'duplicateNativeModuleVersion',
31+
}));
32+
const mockEvent: Event = {
33+
modules: {
34+
eventModule: 'eventModuleVersion',
35+
duplicateModule: 'duplicateEventModuleVersion',
36+
}
37+
};
38+
const processedEvent = await executeIntegrationFor(mockEvent);
39+
40+
expect(processedEvent?.modules).toEqual({
41+
eventModule: 'eventModuleVersion',
42+
nativeModules: 'nativeModuleVersion',
43+
duplicateModule: 'duplicateEventModuleVersion',
44+
});
45+
});
46+
47+
function executeIntegrationFor(mockedEvent: Event, mockedHint: EventHint = {}): Promise<Event | null> {
48+
return new Promise((resolve, reject) => {
49+
integration.setupOnce(async (eventProcessor) => {
50+
try {
51+
const processedEvent = await eventProcessor(mockedEvent, mockedHint);
52+
resolve(processedEvent);
53+
} catch (e) {
54+
reject(e);
55+
}
56+
});
57+
});
58+
}
59+
});

0 commit comments

Comments
 (0)