File tree Expand file tree Collapse file tree 5 files changed +72
-7
lines changed
Expand file tree Collapse file tree 5 files changed +72
-7
lines changed Original file line number Diff line number Diff line change 1818### Major Changes
1919
2020- ` Sentry.captureUserFeedback ` removed, use ` Sentry.captureFeedback ` instead ([ #4855 ] ( https://github.com/getsentry/sentry-react-native/pull/4855 ) )
21+ - Use global ` TextEncoder ` (available with Hermes in React Native 0.74 or higher) to greatly improve envelope encoding performance. ([ #4874 ] ( https://github.com/getsentry/sentry-react-native/pull/4874 ) )
2122
2223### Changes
2324
Original file line number Diff line number Diff line change 1- import { getMainCarrier , SDK_VERSION } from '@sentry/core' ;
1+ import { getSentryCarrier } from '../utils/carrier' ;
2+ import { RN_GLOBAL_OBJ } from '../utils/worldwide' ;
23import { utf8ToBytes } from '../vendor' ;
34
45export const useEncodePolyfill = ( ) : void => {
5- // Based on https://github.com/getsentry/sentry-javascript/blob/f0fc41f6166857cd97a695f5cc9a18caf6a0bf43/packages/core/src/carrier.ts#L49
6- const carrier = getMainCarrier ( ) ;
7- const __SENTRY__ = ( carrier . __SENTRY__ = carrier . __SENTRY__ || { } ) ;
8- ( __SENTRY__ [ SDK_VERSION ] = __SENTRY__ [ SDK_VERSION ] || { } ) . encodePolyfill = encodePolyfill ;
6+ const carrier = getSentryCarrier ( ) ;
7+
8+ if ( RN_GLOBAL_OBJ . TextEncoder ) {
9+ // Hermes for RN 0.74 and later includes native TextEncoder
10+ // https://github.com/facebook/hermes/commit/8fb0496d426a8e50d00385148d5fb498a6daa312
11+ carrier . encodePolyfill = globalEncodeFactory ( RN_GLOBAL_OBJ . TextEncoder ) ;
12+ } else {
13+ carrier . encodePolyfill = encodePolyfill ;
14+ }
915} ;
1016
17+ /*
18+ * The default encode polyfill is available in Hermes for RN 0.74 and later.
19+ * https://github.com/facebook/hermes/commit/8fb0496d426a8e50d00385148d5fb498a6daa312
20+ */
21+ export const globalEncodeFactory = ( Encoder : EncoderClass ) => ( text : string ) => new Encoder ( ) . encode ( text ) ;
22+
23+ type EncoderClass = Required < typeof RN_GLOBAL_OBJ > [ 'TextEncoder' ] ;
24+
25+ /*
26+ * Encode polyfill runs in JS and might cause performance issues when processing large payloads. (~2+ MB)
27+ */
1128export const encodePolyfill = ( text : string ) : Uint8Array => {
1229 const bytes = new Uint8Array ( utf8ToBytes ( text ) ) ;
1330 return bytes ;
Original file line number Diff line number Diff line change 1+ import { getMainCarrier , SDK_VERSION as CORE_SDK_VERSION } from '@sentry/core' ;
2+
3+ /*
4+ * Will either get the existing sentry carrier, or create a new one.
5+ * Based on https://github.com/getsentry/sentry-javascript/blob/f0fc41f6166857cd97a695f5cc9a18caf6a0bf43/packages/core/src/carrier.ts#L49
6+ */
7+ export const getSentryCarrier = ( ) : SentryCarrier => {
8+ const carrier = getMainCarrier ( ) ;
9+ const __SENTRY__ = ( carrier . __SENTRY__ = carrier . __SENTRY__ || { } ) ;
10+ return ( __SENTRY__ [ CORE_SDK_VERSION ] = __SENTRY__ [ CORE_SDK_VERSION ] || { } ) ;
11+ } ;
12+
13+ type SentryCarrier = Required < ReturnType < typeof getMainCarrier > > [ '__SENTRY__' ] [ string ] ;
Original file line number Diff line number Diff line change @@ -36,8 +36,9 @@ export interface ReactNativeInternalGlobal extends InternalGlobal {
3636}
3737
3838type TextEncoder = {
39- new ( ) : TextEncoder ;
40- encode ( input ?: string ) : Uint8Array ;
39+ new ( ) : {
40+ encode ( input ?: string ) : Uint8Array ;
41+ } ;
4142} ;
4243
4344/** Get's the global object for the current JavaScript runtime */
Original file line number Diff line number Diff line change 1+ import { SDK_VERSION } from '@sentry/core' ;
2+ import { encodePolyfill , useEncodePolyfill } from '../../src/js/transports/encodePolyfill' ;
3+ import { RN_GLOBAL_OBJ } from '../../src/js/utils/worldwide' ;
4+
5+ const OriginalTextEncoder = RN_GLOBAL_OBJ . TextEncoder ;
6+
7+ const restoreTextEncoder = ( ) : void => {
8+ RN_GLOBAL_OBJ . TextEncoder = OriginalTextEncoder ;
9+ } ;
10+
11+ describe ( 'useEncodePolyfill' , ( ) => {
12+ afterEach ( ( ) => {
13+ restoreTextEncoder ( ) ;
14+ } ) ;
15+
16+ test ( 'should use global encode factory if TextEncoder is available' , ( ) => {
17+ RN_GLOBAL_OBJ . TextEncoder = MockedTextEncoder ;
18+ useEncodePolyfill ( ) ;
19+ expect ( RN_GLOBAL_OBJ . __SENTRY__ ?. [ SDK_VERSION ] ?. encodePolyfill ?.( '' ) ) . toEqual ( new Uint8Array ( [ 1 , 2 , 3 ] ) ) ;
20+ } ) ;
21+
22+ test ( 'should use encode polyfill if TextEncoder is not available' , ( ) => {
23+ RN_GLOBAL_OBJ . TextEncoder = undefined ;
24+ useEncodePolyfill ( ) ;
25+ expect ( RN_GLOBAL_OBJ . __SENTRY__ ?. [ SDK_VERSION ] ?. encodePolyfill ) . toBe ( encodePolyfill ) ;
26+ } ) ;
27+ } ) ;
28+
29+ class MockedTextEncoder {
30+ public encode ( _text : string ) : Uint8Array {
31+ return new Uint8Array ( [ 1 , 2 , 3 ] ) ;
32+ }
33+ }
You can’t perform that action at this time.
0 commit comments