|
@@ -1,5 +1,7 @@
|
|
1
|
+/* global __DEV__ */
|
|
2
|
+
|
1
|
3
|
import React from 'react';
|
2
|
|
-import { Linking, Navigator } from 'react-native';
|
|
4
|
+import { Linking, Navigator, Platform } from 'react-native';
|
3
|
5
|
import { Provider } from 'react-redux';
|
4
|
6
|
|
5
|
7
|
import { _getRouteToRender } from '../functions';
|
|
@@ -30,6 +32,12 @@ export class App extends AbstractApp {
|
30
|
32
|
// Bind event handlers so they are only bound once for every instance.
|
31
|
33
|
this._navigatorRenderScene = this._navigatorRenderScene.bind(this);
|
32
|
34
|
this._onLinkingURL = this._onLinkingURL.bind(this);
|
|
35
|
+
|
|
36
|
+ // In the Release configuration, React Native will (intentionally) throw
|
|
37
|
+ // an unhandled JavascriptException for an unhandled JavaScript error.
|
|
38
|
+ // This will effectively kill the application. In accord with the Web,
|
|
39
|
+ // do not kill the application.
|
|
40
|
+ this._maybeDisableExceptionsManager();
|
33
|
41
|
}
|
34
|
42
|
|
35
|
43
|
/**
|
|
@@ -101,6 +109,44 @@ export class App extends AbstractApp {
|
101
|
109
|
navigator && navigator.replace({ ...route });
|
102
|
110
|
}
|
103
|
111
|
|
|
112
|
+ /**
|
|
113
|
+ * Attempts to disable the use of React Native
|
|
114
|
+ * {@link ExceptionsManager#handleException} on platforms and in
|
|
115
|
+ * configurations on/in which the use of the method in questions has been
|
|
116
|
+ * determined to be undesirable. For example, React Native will
|
|
117
|
+ * (intentionally) throw an unhandled JavascriptException for an
|
|
118
|
+ * unhandled JavaScript error in the Release configuration. This will
|
|
119
|
+ * effectively kill the application. In accord with the Web, do not kill the
|
|
120
|
+ * application.
|
|
121
|
+ *
|
|
122
|
+ * @private
|
|
123
|
+ * @returns {void}
|
|
124
|
+ */
|
|
125
|
+ _maybeDisableExceptionsManager() {
|
|
126
|
+ if (__DEV__) {
|
|
127
|
+ // As mentioned above, only the Release configuration was observed
|
|
128
|
+ // to suffer.
|
|
129
|
+ return;
|
|
130
|
+ }
|
|
131
|
+ if (Platform.OS !== 'android') {
|
|
132
|
+ // A solution based on RTCSetFatalHandler was implemented on iOS and
|
|
133
|
+ // it is preferred because it is at a later step of the
|
|
134
|
+ // error/exception handling and it is specific to fatal
|
|
135
|
+ // errors/exceptions which were observed to kill the application.
|
|
136
|
+ // The solution implemented bellow was tested on Android only so it
|
|
137
|
+ // is considered safest to use it there only.
|
|
138
|
+ return;
|
|
139
|
+ }
|
|
140
|
+
|
|
141
|
+ const oldHandler = global.ErrorUtils.getGlobalHandler();
|
|
142
|
+ const newHandler = _handleException;
|
|
143
|
+
|
|
144
|
+ if (!oldHandler || oldHandler !== newHandler) {
|
|
145
|
+ newHandler.next = oldHandler;
|
|
146
|
+ global.ErrorUtils.setGlobalHandler(newHandler);
|
|
147
|
+ }
|
|
148
|
+ }
|
|
149
|
+
|
104
|
150
|
/**
|
105
|
151
|
* Renders the scene identified by a specific route in the Navigator of this
|
106
|
152
|
* instance.
|
|
@@ -133,3 +179,29 @@ export class App extends AbstractApp {
|
133
|
179
|
this._openURL(event.url);
|
134
|
180
|
}
|
135
|
181
|
}
|
|
182
|
+
|
|
183
|
+/**
|
|
184
|
+ * Handles a (possibly unhandled) JavaScript error by preventing React Native
|
|
185
|
+ * from converting a fatal error into an unhandled native exception which will
|
|
186
|
+ * kill the application.
|
|
187
|
+ *
|
|
188
|
+ * @param {Error} error - The (possibly unhandled) JavaScript error to handle.
|
|
189
|
+ * @param {boolean} fatal - True if the specified error is fatal; otherwise,
|
|
190
|
+ * false.
|
|
191
|
+ * @private
|
|
192
|
+ * @returns {void}
|
|
193
|
+ */
|
|
194
|
+function _handleException(error, fatal) {
|
|
195
|
+ if (fatal) {
|
|
196
|
+ // In the Release configuration, React Native will (intentionally) throw
|
|
197
|
+ // an unhandled JavascriptException for an unhandled JavaScript error.
|
|
198
|
+ // This will effectively kill the application. In accord with the Web,
|
|
199
|
+ // do not kill the application.
|
|
200
|
+ console.error(error);
|
|
201
|
+ } else {
|
|
202
|
+ // Forward to the next globalHandler of ErrorUtils.
|
|
203
|
+ const next = _handleException.next;
|
|
204
|
+
|
|
205
|
+ typeof next === 'function' && next(error, fatal);
|
|
206
|
+ }
|
|
207
|
+}
|