Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ module.exports = {
'@sentry-internal/sdk/no-nullish-coalescing': 'off',
'@sentry-internal/sdk/no-unsupported-es6-methods': 'off',
'@sentry-internal/sdk/no-class-field-initializers': 'off',
'deprecation/deprecation': 'off',
},
};
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ This release contains upgrade of `sentry-android` dependency to major version 7.
- Bump Android SDK from v6.34.0 to v7.3.0 ([#3434](https://github.com/getsentry/sentry-react-native/pull/3434))
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#730)
- [diff](https://github.com/getsentry/sentry-java/compare/6.34.0...7.3.0)
- Bump JavaScript SDK from v7.81.1 to v7.99.0 ([#3426](https://github.com/getsentry/sentry-react-native/pull/3426))
- [changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md#7990)
- [diff](https://github.com/getsentry/sentry-javascript/compare/7.81.1...7.99.0)

## 5.18.0

Expand Down
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,22 @@
"react-native": ">=0.65.0"
},
"dependencies": {
"@sentry/browser": "7.81.1",
"@sentry/browser": "7.99.0",
"@sentry/cli": "2.25.2",
"@sentry/core": "7.81.1",
"@sentry/hub": "7.81.1",
"@sentry/integrations": "7.81.1",
"@sentry/react": "7.81.1",
"@sentry/types": "7.81.1",
"@sentry/utils": "7.81.1"
"@sentry/core": "7.99.0",
"@sentry/hub": "7.99.0",
"@sentry/integrations": "7.99.0",
"@sentry/react": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"devDependencies": {
"@babel/core": "^7.23.5",
"@expo/metro-config": "0.16.0",
"@mswjs/interceptors": "^0.25.15",
"@sentry-internal/eslint-config-sdk": "7.81.1",
"@sentry-internal/eslint-plugin-sdk": "7.81.1",
"@sentry-internal/typescript": "7.80.0",
"@sentry-internal/eslint-config-sdk": "7.99.0",
"@sentry-internal/eslint-plugin-sdk": "7.99.0",
"@sentry-internal/typescript": "7.99.0",
"@sentry/wizard": "3.16.3",
"@types/jest": "^29.5.3",
"@types/node": "^20.9.3",
Expand Down
29 changes: 16 additions & 13 deletions src/js/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
super(options);

this._outcomesBuffer = [];
void this._initNativeSdk();
this._initNativeSdk();
}

/**
Expand Down Expand Up @@ -159,20 +159,23 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
/**
* Starts native client with dsn and options
*/
private async _initNativeSdk(): Promise<void> {
let didCallNativeInit = false;

try {
didCallNativeInit = await NATIVE.initNativeSdk(this._options);
} catch (_) {
this._showCannotConnectDialog();
} finally {
try {
private _initNativeSdk(): void {
NATIVE.initNativeSdk(this._options)
.then(
(result: boolean) => {
return result;
},
() => {
this._showCannotConnectDialog();
return false;
},
)
.then((didCallNativeInit: boolean) => {
this._options.onReady?.({ didCallNativeInit });
} catch (error) {
})
.then(undefined, error => {
logger.error('The OnReady callback threw an error: ', error);
}
}
});
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/js/integrations/debugsymbolicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ReactNativeLibraries } from '../utils/rnlibraries';
import { createStealthXhr, XHR_READYSTATE_DONE } from '../utils/xhr';
import type * as ReactNative from '../vendor/react-native';

// eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor
const INTERNAL_CALLSITES_REGEX = new RegExp(['ReactNativeRenderer-dev\\.js$', 'MessageQueue\\.js$'].join('|'));

/**
Expand Down
14 changes: 11 additions & 3 deletions src/js/integrations/reactnativeerrorhandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,17 @@ export class ReactNativeErrorHandlers implements Integration {
currentHub.captureEvent(event, hint);

if (!__DEV__) {
void client.flush(options.shutdownTimeout || 2000).then(() => {
defaultHandler(error, isFatal);
});
void client.flush(options.shutdownTimeout || 2000).then(
() => {
defaultHandler(error, isFatal);
},
(reason: unknown) => {
logger.error(
'[ReactNativeErrorHandlers] Error while flushing the event cache after uncaught error.',
reason,
);
},
);
} else {
// If in dev, we call the default handler anyway and hope the error will be sent
// Just for a better dev experience
Expand Down
4 changes: 2 additions & 2 deletions src/js/integrations/rewriteframes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RewriteFrames } from '@sentry/integrations';
import type { StackFrame } from '@sentry/types';
import type { Integration, StackFrame } from '@sentry/types';
import { Platform } from 'react-native';

import { isExpo, isHermesEnabled } from '../utils/environment';
Expand All @@ -13,7 +13,7 @@ export const IOS_DEFAULT_BUNDLE_NAME = 'app:///main.jsbundle';
* and removes file://, 'address at' prefixes, CodePush postfix,
* and Expo bundle postfix.
*/
export function createReactNativeRewriteFrames(): RewriteFrames {
export function createReactNativeRewriteFrames(): Integration {
return new RewriteFrames({
iteratee: (frame: StackFrame) => {
if (frame.platform === 'java' || frame.platform === 'cocoa') {
Expand Down
9 changes: 5 additions & 4 deletions src/js/sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,16 @@ export function captureUserFeedback(feedback: UserFeedback): void {
*
* @param callback that will be enclosed into push/popScope.
*/
export function withScope(callback: (scope: Scope) => void): ReturnType<Hub['withScope']> {
const safeCallback = (scope: Scope): void => {
export function withScope<T>(callback: (scope: Scope) => T): T | undefined {
const safeCallback = (scope: Scope): T | undefined => {
try {
callback(scope);
return callback(scope);
} catch (e) {
logger.error('Error while running withScope callback', e);
return undefined;
}
};
getCurrentHub().withScope(safeCallback);
return getCurrentHub().withScope(safeCallback);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/js/tools/sentryMetroSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 +192,6 @@ function calculateDebugId(bundle: Bundle): string {
}

function injectDebugId(code: string, debugId: string): string {
// eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor
return code.replace(new RegExp(DEBUG_ID_PLACE_HOLDER, 'g'), debugId);
}
4 changes: 2 additions & 2 deletions src/js/tracing/addTracingExtensions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Hub, Transaction } from '@sentry/core';
import type { Hub, Span, Transaction } from '@sentry/core';
import { addTracingExtensions, getCurrentHub, getMainCarrier } from '@sentry/core';
import type { CustomSamplingContext, Span, SpanContext, TransactionContext } from '@sentry/types';
import type { CustomSamplingContext, SpanContext, TransactionContext } from '@sentry/types';

import { DEFAULT } from '../tracing/ops';
import { ReactNativeTracing } from '../tracing/reactnativetracing';
Expand Down
4 changes: 3 additions & 1 deletion src/js/tracing/nativeframes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export class NativeFramesInstrumentation {
* To be called when a transaction is finished
*/
public onTransactionFinish(transaction: Transaction): void {
void this._fetchFramesForTransaction(transaction);
this._fetchFramesForTransaction(transaction).then(undefined, (reason: unknown) => {
logger.error(`[ReactNativeTracing] Error while fetching native frames:`, reason);
});
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/js/tracing/reactnativetracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ export class ReactNativeTracing implements Integration {
}

if (enableAppStartTracking) {
void this._instrumentAppStart();
this._instrumentAppStart().then(undefined, (reason: unknown) => {
logger.error(`[ReactNativeTracing] Error while instrumenting app start:`, reason);
});
}

if (enableNativeFramesTracking) {
Expand Down
13 changes: 13 additions & 0 deletions test/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ describe('Tests ReactNativeClient', () => {
);
});

test('catches errors from onReady callback', () => {
new ReactNativeClient(
mockedOptions({
dsn: EXAMPLE_DSN,
enableNative: true,
onReady: () => {
throw new Error('This error should be caught by the SDK');
},
transport: () => new NativeTransport(),
}),
);
});

test('calls onReady callback with false if Native SDK was not initialized', done => {
new ReactNativeClient(
mockedOptions({
Expand Down
10 changes: 5 additions & 5 deletions test/e2e/test/utils/fetchEvent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Event } from '@sentry/types';
import fetch from 'node-fetch';
import fetch, { Request } from 'node-fetch';

const domain = 'sentry.io';
const eventEndpoint = '/api/0/projects/sentry-sdks/sentry-react-native/events/';
Expand All @@ -18,9 +18,9 @@ const fetchEvent = async (eventId: string): Promise<ApiEvent> => {
const url = `https://${domain}${eventEndpoint}${eventId}/`;

expect(process.env.SENTRY_AUTH_TOKEN).toBeDefined();
expect(process.env.SENTRY_AUTH_TOKEN.length).toBeGreaterThan(0);
expect(process.env.SENTRY_AUTH_TOKEN?.length).toBeGreaterThan(0);

const request = new fetch.Request(url, {
const request = new Request(url, {
headers: {
Authorization: `Bearer ${process.env.SENTRY_AUTH_TOKEN}`,
'Content-Type': 'application/json',
Expand Down Expand Up @@ -51,10 +51,10 @@ const fetchEvent = async (eventId: string): Promise<ApiEvent> => {
}
});

const json: ApiEvent = await fetch(request)
const json: ApiEvent = (await fetch(request)
// tslint:disable-next-line: no-unsafe-any
.then(res => res.json())
.then(retryer);
.then(retryer)) as ApiEvent;

return json;
};
Expand Down
12 changes: 8 additions & 4 deletions test/integrations/rewriteframes.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Exception } from '@sentry/browser';
import { defaultStackParser, eventFromException } from '@sentry/browser';
import type { Event } from '@sentry/types';
import type { Client, Event, EventHint } from '@sentry/types';
import { Platform } from 'react-native';

import { createReactNativeRewriteFrames } from '../../src/js/integrations/rewriteframes';
Expand All @@ -22,11 +22,15 @@ describe('RewriteFrames', () => {
const error = new Error(options.message);
error.stack = options.stack;
const event = await eventFromException(defaultStackParser, error, HINT, ATTACH_STACKTRACE);
createReactNativeRewriteFrames().process(event);
createReactNativeRewriteFrames().processEvent?.(event, {} as EventHint, {} as Client);
const exception = event.exception?.values?.[0];
return exception;
};

const processEvent = (event: Event): Event | undefined | null | PromiseLike<Event | null> => {
return createReactNativeRewriteFrames().processEvent?.(event, {} as EventHint, {} as Client);
};

beforeEach(() => {
mockFunction(isExpo).mockReturnValue(false);
mockFunction(isHermesEnabled).mockReturnValue(false);
Expand Down Expand Up @@ -67,7 +71,7 @@ describe('RewriteFrames', () => {
},
};

const event = createReactNativeRewriteFrames().process(SENTRY_COCOA_EXCEPTION_EVENT);
const event = processEvent(SENTRY_COCOA_EXCEPTION_EVENT) as Event;
expect(event.exception?.values?.[0]).toEqual(EXPECTED_SENTRY_COCOA_EXCEPTION);
});

Expand Down Expand Up @@ -101,7 +105,7 @@ describe('RewriteFrames', () => {
},
};

const event = createReactNativeRewriteFrames().process(SENTRY_JVM_EXCEPTION_EVENT);
const event = processEvent(SENTRY_JVM_EXCEPTION_EVENT) as Event;
expect(event.exception?.values?.[0]).toEqual(EXPECTED_SENTRY_JVM_EXCEPTION);
});

Expand Down
3 changes: 3 additions & 0 deletions test/tracing/gesturetracing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ const getMockScope = () => {
// Placeholder
},
getUser: () => scopeUser,
captureEvent(_event: unknown) {
// Placeholder
},
};
};

Expand Down
Loading