Skip to content

Commit 762c921

Browse files
Merge branches 'dev' and 'native/android/11.14.0' of https://github.com/Instabug/Instabug-React-Native into native/android/11.14.0
2 parents d075afe + 71449bc commit 762c921

File tree

14 files changed

+328
-9
lines changed

14 files changed

+328
-9
lines changed

.circleci/config.yml

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ commands:
3838
key: v1-pods-{{ checksum "<< parameters.working_directory >>/Podfile.lock" }}
3939
paths:
4040
- << parameters.working_directory >>/Pods
41+
search_and_replace:
42+
parameters:
43+
file:
44+
type: string
45+
replace-pattern:
46+
type: string
47+
steps:
48+
- run:
49+
name: Search and Replace in << parameters.file >>
50+
command: sed -i '<< parameters.replace-pattern >>' << parameters.file >>
51+
4152
jobs:
4253
danger:
4354
executor:
@@ -224,6 +235,36 @@ jobs:
224235
working_directory: examples/default
225236
command: detox test -c android.emu.release
226237

238+
# Automate the enterprise NN sdk changes
239+
release_nn:
240+
working_directory: ~/project
241+
executor:
242+
name: node/default
243+
steps:
244+
- advanced-checkout/shallow-checkout
245+
- install_node_modules
246+
- run:
247+
name: Remove README.md file
248+
command: rm README.md
249+
- search_and_replace:
250+
file: package.json
251+
replace-pattern: 's/instabug-reactnative/@instabug\/react-native-nn/g'
252+
- search_and_replace:
253+
file: cli/UploadSourcemaps.ts
254+
replace-pattern: 's/api.instabug.com\/api\/sdk/st001009nn.instabug.com\/api\/sdk/g'
255+
- search_and_replace:
256+
file: android/native.gradle
257+
replace-pattern: 's/com\.instabug\.library:instabug:/com.instabug.library-nn:instabug:/g'
258+
- run:
259+
working_directory: project
260+
command: yarn build
261+
- run:
262+
name: Authorize with npm
263+
command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
264+
- run:
265+
name: Publish new enterprise version
266+
command: npm publish
267+
227268
publish:
228269
macos:
229270
xcode: 13.4.1
@@ -262,7 +303,22 @@ workflows:
262303
- test_ios
263304
- e2e_ios
264305
- e2e_android
265-
- hold:
306+
- hold_publish:
307+
requires:
308+
- danger
309+
- lint
310+
- test_module
311+
- test_android
312+
- validate_shell_files
313+
- sync_generated_files
314+
- test_ios
315+
- e2e_ios
316+
- e2e_android
317+
type: approval
318+
filters:
319+
branches:
320+
only: master
321+
- hold_release_nn:
266322
requires:
267323
- danger
268324
- lint
@@ -279,7 +335,13 @@ workflows:
279335
only: master
280336
- publish:
281337
requires:
282-
- hold
338+
- hold_publish
339+
filters:
340+
branches:
341+
only: master
342+
- release_nn:
343+
requires:
344+
- hold_release_nn
283345
filters:
284346
branches:
285347
only: master

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
### Added
66

7+
- Add support for automatic capturing of unhandled Promise rejection crashes ([#1014](https://github.com/Instabug/Instabug-React-Native/pull/1014)).
78
- Add new strings (`StringKey.discardAlertStay` and `StringKey.discardAlertDiscard`) for overriding the discard alert buttons for consistency between iOS and Android ([#1001](https://github.com/Instabug/Instabug-React-Native/pull/1001)).
89
- Add a new string (`StringKey.reproStepsListItemNumberingTitle`) for overriding the repro steps list item (screen) title for consistency between iOS and Android ([#1002](https://github.com/Instabug/Instabug-React-Native/pull/1002)).
910
- Add support for RN version 0.73 by updating the `build.gradle` file with the `namespace` ([#1004](https://github.com/Instabug/Instabug-React-Native/pull/1004))
1011
- Add native-side init API which can be used to catch and report startup crashes on android. ([#1012](https://github.com/Instabug/Instabug-React-Native/pull/1012))
1112

1213
### Changed
1314

15+
- Bump Instabug iOS SDK to v11.14.0 ([#1020](https://github.com/Instabug/Instabug-React-Native/pull/1020)). [See release notes](https://github.com/Instabug/Instabug-iOS/releases/tag/11.14.0).
1416
- Bump Instabug Android SDK to v11.14.0 ([#1019](https://github.com/Instabug/Instabug-React-Native/pull/1019)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v11.14.0).
1517

1618
### Deprecated

examples/default/ios/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ PODS:
7373
- hermes-engine (0.72.3):
7474
- hermes-engine/Pre-built (= 0.72.3)
7575
- hermes-engine/Pre-built (0.72.3)
76-
- Instabug (11.13.3)
76+
- Instabug (11.14.0)
7777
- libevent (2.1.12)
7878
- OCMock (3.9.1)
7979
- OpenSSL-Universal (1.1.1100)
@@ -490,7 +490,7 @@ PODS:
490490
- React-logger (= 0.72.3)
491491
- React-perflogger (= 0.72.3)
492492
- RNInstabug (11.13.0):
493-
- Instabug (= 11.13.3)
493+
- Instabug (= 11.14.0)
494494
- React-Core
495495
- RNScreens (3.24.0):
496496
- React-Core
@@ -702,7 +702,7 @@ SPEC CHECKSUMS:
702702
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
703703
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
704704
hermes-engine: 10fbd3f62405c41ea07e71973ea61e1878d07322
705-
Instabug: f7c3880823873cff9ee70307d373e8266c9ea0f8
705+
Instabug: b4976b1a96ed7462b772ff63f7c4e0166389c86a
706706
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
707707
OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8
708708
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
@@ -739,7 +739,7 @@ SPEC CHECKSUMS:
739739
React-runtimescheduler: 837c1bebd2f84572db17698cd702ceaf585b0d9a
740740
React-utils: bcb57da67eec2711f8b353f6e3d33bd8e4b2efa3
741741
ReactCommon: 3ccb8fb14e6b3277e38c73b0ff5e4a1b8db017a9
742-
RNInstabug: a72078ae892268b40d72ce812b213fd8f127c2e9
742+
RNInstabug: 229d6ece2c9e8d085758578bdc12566aa9bef6f2
743743
RNScreens: b21dc57dfa2b710c30ec600786a3fc223b1b92e7
744744
RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9
745745
RNVectorIcons: 8b5bb0fa61d54cd2020af4f24a51841ce365c7e9

examples/default/metro.config.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ const exclusionList = require('metro-config/src/defaults/exclusionList');
55
const root = path.resolve(__dirname, '../..');
66
const pkg = require(path.join(root, 'package.json'));
77
const peerDependencies = Object.keys(pkg.peerDependencies);
8-
const modules = [...peerDependencies, '@babel/runtime'];
8+
const modules = [
9+
...peerDependencies,
10+
'@babel/runtime',
11+
12+
// We need to exclude the `promise` package in the root node_modules directory
13+
// to be able to track unhandled Promise rejections on the correct example app
14+
// Promise object.
15+
'promise',
16+
];
917

1018
module.exports = {
1119
watchFolders: [root],

examples/default/src/screens/CrashReportingScreen.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ export const CrashReportingScreen: React.FC = () => {
2222
}
2323
}}
2424
/>
25+
<ListTile
26+
title="Reject an Unhandled Promise"
27+
onPress={() => {
28+
Promise.reject(new Error('Unhandled Promise Rejection from Instabug Test App'));
29+
Alert.alert('Crash report sent!');
30+
}}
31+
/>
2532
</Screen>
2633
);
2734
};

ios/native.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$instabug = { :version => '11.13.3' }
1+
$instabug = { :version => '11.14.0' }
22

33
def use_instabug! (spec = nil)
44
version = $instabug[:version]

src/modules/Instabug.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import InstabugUtils, {
3636
stringifyIfNotString,
3737
} from '../utils/InstabugUtils';
3838
import * as NetworkLogger from './NetworkLogger';
39+
import { captureUnhandledRejections } from '../utils/UnhandledRejectionTracking';
3940

4041
let _currentScreen: string | null = null;
4142
let _lastScreen: string | null = null;
@@ -87,6 +88,7 @@ export const start = (token: string, invocationEvents: invocationEvent[] | Invoc
8788
*/
8889
export const init = (config: InstabugConfig) => {
8990
InstabugUtils.captureJsErrors();
91+
captureUnhandledRejections();
9092
NetworkLogger.setEnabled(true);
9193

9294
NativeInstabug.init(

src/promise.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
declare module 'promise/setimmediate/rejection-tracking' {
2+
export interface RejectionTrackingOptions {
3+
allRejections?: boolean;
4+
whitelist?: Function[];
5+
onUnhandled?: (id: number, error: unknown) => void;
6+
onHandled?: (id: number, error: unknown) => void;
7+
}
8+
9+
export function enable(options?: RejectionTrackingOptions): void;
10+
export function disable(): void;
11+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import tracking, { RejectionTrackingOptions } from 'promise/setimmediate/rejection-tracking';
2+
import { sendCrashReport } from './InstabugUtils';
3+
import { NativeCrashReporting } from '../native/NativeCrashReporting';
4+
5+
export interface HermesInternalType {
6+
enablePromiseRejectionTracker?: (options?: RejectionTrackingOptions) => void;
7+
hasPromise?: () => boolean;
8+
}
9+
10+
/**
11+
* A typed version of the `HermesInternal` global object with the properties
12+
* we use.
13+
*/
14+
function _getHermes(): HermesInternalType | null {
15+
return (global as any).HermesInternal;
16+
}
17+
18+
/**
19+
* Checks whether the Promise object is provided by Hermes.
20+
*
21+
* @returns whether the `Promise` object is provided by Hermes.
22+
*/
23+
function _isHermesPromise() {
24+
const hermes = _getHermes();
25+
const hasPromise = hermes?.hasPromise?.() === true;
26+
const canTrack = hermes?.enablePromiseRejectionTracker != null;
27+
28+
return hasPromise && canTrack;
29+
}
30+
31+
/**
32+
* Enables unhandled Promise rejection tracking in Hermes.
33+
*
34+
* @param options Rejection tracking options.
35+
*/
36+
function _enableHermesRejectionTracking(options?: RejectionTrackingOptions) {
37+
const hermes = _getHermes();
38+
39+
hermes!.enablePromiseRejectionTracker!(options);
40+
}
41+
42+
/**
43+
* Enables unhandled Promise rejection tracking in the default `promise` polyfill.
44+
*
45+
* @param options Rejection tracking options.
46+
*/
47+
function _enableDefaultRejectionTracking(options?: RejectionTrackingOptions) {
48+
tracking.enable(options);
49+
}
50+
51+
/**
52+
* Tracks whether an unhandled Promise rejection happens and reports it.
53+
*/
54+
export function captureUnhandledRejections() {
55+
const options: RejectionTrackingOptions = {
56+
allRejections: true,
57+
onUnhandled: _onUnhandled,
58+
};
59+
60+
if (_isHermesPromise()) {
61+
_enableHermesRejectionTracking(options);
62+
} else {
63+
_enableDefaultRejectionTracking(options);
64+
}
65+
}
66+
67+
/**
68+
* The callback passed in the rejection tracking options to report unhandled
69+
* Promise rejection
70+
*/
71+
function _onUnhandled(id: number, rejection: unknown) {
72+
_originalOnUnhandled(id, rejection);
73+
74+
if (__DEV__) {
75+
return;
76+
}
77+
78+
if (rejection instanceof Error) {
79+
sendCrashReport(rejection, NativeCrashReporting.sendHandledJSCrash);
80+
}
81+
}
82+
83+
/* istanbul ignore next */
84+
/**
85+
* The default unhandled promise rejection handler set by React Native.
86+
*
87+
* In fact, this is copied from the React Native repo but modified to work well
88+
* with our static analysis setup.
89+
*
90+
* https://github.com/facebook/react-native/blob/f2447e6048a6b519c3333767d950dbf567149b75/packages/react-native/Libraries/promiseRejectionTrackingOptions.js#L15-L49
91+
*/
92+
function _originalOnUnhandled(id: number, rejection: unknown = {}) {
93+
let message: string;
94+
let stack: string | undefined;
95+
96+
const stringValue = Object.prototype.toString.call(rejection);
97+
if (stringValue === '[object Error]') {
98+
message = Error.prototype.toString.call(rejection);
99+
const error = rejection as Error;
100+
stack = error.stack;
101+
} else {
102+
try {
103+
message = require('pretty-format')(rejection);
104+
} catch {
105+
message = typeof rejection === 'string' ? rejection : JSON.stringify(rejection);
106+
}
107+
}
108+
109+
const warning =
110+
`Possible Unhandled Promise Rejection (id: ${id}):\n` +
111+
`${message ?? ''}\n` +
112+
(stack == null ? '' : stack);
113+
console.warn(warning);
114+
}

test/mocks/mockHermesInternal.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { HermesInternalType } from '../../src/utils/UnhandledRejectionTracking';
2+
3+
export function mockHermesInternal(hermes: HermesInternalType) {
4+
const original = (global as any).HermesInternal;
5+
6+
// Using Object.defineProperty to avoid TypeScript errors
7+
Object.defineProperty(global, 'HermesInternal', { value: hermes, writable: true });
8+
9+
return {
10+
mockRestore: () => {
11+
Object.defineProperty(global, 'HermesInternal', { value: original, writable: true });
12+
},
13+
};
14+
}

0 commit comments

Comments
 (0)