@@ -13,7 +13,6 @@ import type {ExtendedExceptionData} from './Data/parseLogBoxLog';
13
13
14
14
import Platform from '../Utilities/Platform' ;
15
15
import RCTLog from '../Utilities/RCTLog' ;
16
- import { hasComponentStack } from './Data/parseLogBoxLog' ;
17
16
import * as React from 'react' ;
18
17
19
18
export type { LogData , ExtendedExceptionData , IgnorePattern } ;
@@ -28,6 +27,7 @@ interface ILogBox {
28
27
ignoreAllLogs ( ?boolean ) : void ;
29
28
clearAllLogs ( ) : void ;
30
29
addLog ( log : LogData ) : void ;
30
+ addConsoleLog ( level : 'warn' | 'error' , ...args : Array < mixed > ) : void ;
31
31
addException ( error : ExtendedExceptionData ) : void ;
32
32
}
33
33
@@ -36,11 +36,12 @@ interface ILogBox {
36
36
*/
37
37
if ( __DEV__ ) {
38
38
const LogBoxData = require ( './Data/LogBoxData' ) ;
39
- const { parseLogBoxLog, parseInterpolation} = require ( './Data/parseLogBoxLog' ) ;
39
+ const {
40
+ parseLogBoxLog,
41
+ parseComponentStack,
42
+ } = require ( './Data/parseLogBoxLog' ) ;
40
43
41
- let originalConsoleError ;
42
44
let originalConsoleWarn ;
43
- let consoleErrorImpl ;
44
45
let consoleWarnImpl : ( ...args : Array < mixed > ) => void ;
45
46
46
47
let isLogBoxInstalled : boolean = false ;
@@ -70,22 +71,20 @@ if (__DEV__) {
70
71
// IMPORTANT: we only overwrite `console.error` and `console.warn` once.
71
72
// When we uninstall we keep the same reference and only change its
72
73
// internal implementation
73
- const isFirstInstall = originalConsoleError == null ;
74
+ const isFirstInstall = originalConsoleWarn == null ;
74
75
if ( isFirstInstall ) {
75
- originalConsoleError = console . error . bind ( console ) ;
76
+ // We only patch warning for legacy reasons.
77
+ // This will be removed in the future, once warnings
78
+ // are fully moved to fusebox. Error handling is done
79
+ // via the ExceptionManager.
76
80
originalConsoleWarn = console . warn . bind ( console ) ;
77
81
78
- // $FlowExpectedError[cannot-write]
79
- console . error = ( ...args ) => {
80
- consoleErrorImpl ( ...args ) ;
81
- } ;
82
82
// $FlowExpectedError[cannot-write]
83
83
console . warn = ( ...args ) => {
84
84
consoleWarnImpl ( ...args ) ;
85
85
} ;
86
86
}
87
87
88
- consoleErrorImpl = registerError ;
89
88
consoleWarnImpl = registerWarning ;
90
89
91
90
if ( Platform . isTesting ) {
@@ -108,7 +107,6 @@ if (__DEV__) {
108
107
// decorated again after installing LogBox. E.g.:
109
108
// Before uninstalling: original > LogBox > OtherErrorHandler
110
109
// After uninstalling: original > LogBox (noop) > OtherErrorHandler
111
- consoleErrorImpl = originalConsoleError ;
112
110
consoleWarnImpl = originalConsoleWarn ;
113
111
} ,
114
112
@@ -134,6 +132,56 @@ if (__DEV__) {
134
132
}
135
133
} ,
136
134
135
+ addConsoleLog ( level : 'warn' | 'error' , ...args : Array < mixed > ) {
136
+ let filteredLevel : 'warn' | 'error' | 'fatal' = level ;
137
+ try {
138
+ let format = args [ 0 ] ;
139
+ if ( typeof format === 'string' ) {
140
+ const filterResult =
141
+ require ( '../LogBox/Data/LogBoxData' ) . checkWarningFilter ( format ) ;
142
+ if ( filterResult . monitorEvent !== 'warning_unhandled' ) {
143
+ if ( filterResult . suppressCompletely ) {
144
+ return ;
145
+ }
146
+
147
+ if ( filterResult . suppressDialog_LEGACY === true ) {
148
+ filteredLevel = 'warn' ;
149
+ } else if ( filterResult . forceDialogImmediately === true ) {
150
+ filteredLevel = 'fatal' ; // Do not downgrade. These are real bugs with same severity as throws.
151
+ }
152
+ }
153
+ }
154
+
155
+ const result = parseLogBoxLog ( args ) ;
156
+ const category = result . category ;
157
+ const message = result . message ;
158
+ let componentStackType = result . componentStackType ;
159
+ let componentStack = result . componentStack ;
160
+ if (
161
+ ( ! componentStack || componentStack . length === 0 ) &&
162
+ // $FlowExpectedError[prop-missing]
163
+ React . captureOwnerStack
164
+ ) {
165
+ const ownerStack = React . captureOwnerStack ( ) ;
166
+ const parsedComponentStack = parseComponentStack ( ownerStack ) ;
167
+ componentStack = parsedComponentStack . stack ;
168
+ componentStackType = parsedComponentStack . type ;
169
+ }
170
+
171
+ if ( ! LogBoxData . isMessageIgnored ( message . content ) ) {
172
+ LogBoxData . addLog ( {
173
+ level : filteredLevel ,
174
+ category,
175
+ message,
176
+ componentStack,
177
+ componentStackType,
178
+ } ) ;
179
+ }
180
+ } catch ( err ) {
181
+ LogBoxData . reportLogBoxError ( err ) ;
182
+ }
183
+ } ,
184
+
137
185
addException ,
138
186
} ;
139
187
@@ -149,14 +197,9 @@ if (__DEV__) {
149
197
return typeof args [ 0 ] = == 'string' && args [ 0 ] . startsWith ( '(ADVICE)' ) ;
150
198
} ;
151
199
152
- const isWarningModuleWarning = ( ...args : Array < mixed > ) => {
153
- return typeof args [ 0 ] === 'string' && args [ 0 ] . startsWith ( 'Warning: ' ) ;
154
- } ;
155
-
156
200
const registerWarning = ( ...args : Array < mixed > ) : void => {
157
201
// Let warnings within LogBox itself fall through.
158
202
if ( LogBoxData . isLogBoxErrorMessage ( String ( args [ 0 ] ) ) ) {
159
- originalConsoleError ( ...args ) ;
160
203
return ;
161
204
} else {
162
205
// Be sure to pass LogBox warnings through.
@@ -182,89 +225,6 @@ if (__DEV__) {
182
225
LogBoxData . reportLogBoxError ( err ) ;
183
226
}
184
227
} ;
185
-
186
- /* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
187
- * LTI update could not be added via codemod */
188
- const registerError = ( ...args ) : void => {
189
- // Let errors within LogBox itself fall through.
190
- if ( LogBoxData . isLogBoxErrorMessage ( args [ 0 ] ) ) {
191
- originalConsoleError ( ...args ) ;
192
- return ;
193
- }
194
-
195
- try {
196
- let stack ;
197
- // $FlowFixMe[prop-missing] Not added to flow types yet.
198
- if ( ! hasComponentStack ( args ) && React . captureOwnerStack != null ) {
199
- stack = React . captureOwnerStack ( ) ;
200
- if ( ! hasComponentStack ( args ) ) {
201
- console . log ( 'hit' ) ;
202
- if ( stack !== '' ) {
203
- args [ 0 ] = args [ 0 ] += '%s' ;
204
- args . push ( stack ) ;
205
- }
206
- }
207
- }
208
- if ( ! isWarningModuleWarning ( ...args ) && ! hasComponentStack ( args ) ) {
209
- // Only show LogBox for the 'warning' module, or React errors with
210
- // component stacks, otherwise pass the error through.
211
- //
212
- // By passing through, this will get picked up by the React console override,
213
- // potentially adding the component stack. React then passes it back to the
214
- // React Native ExceptionsManager, which reports it to LogBox as an error.
215
- //
216
- // Ideally, we refactor all RN error handling so that LogBox patching
217
- // errors is not necessary, and they are reported the same as a framework.
218
- // The blocker to this is that the ExceptionManager console.error override
219
- // strigifys all of the args before passing it through to LogBox, which
220
- // would lose all of the interpolation information.
221
- //
222
- // The 'warning' module needs to be handled here because React internally calls
223
- // `console.error('Warning: ')` with the component stack already included.
224
- originalConsoleError ( ...args ) ;
225
- return ;
226
- }
227
-
228
- let format = args [ 0 ] . replace ( 'Warning: ' , '' ) ;
229
- const filterResult = LogBoxData . checkWarningFilter ( format ) ;
230
- let level = 'error' ;
231
- if ( filterResult . monitorEvent !== 'warning_unhandled' ) {
232
- if ( filterResult . suppressCompletely ) {
233
- return ;
234
- }
235
-
236
- if ( filterResult . suppressDialog_LEGACY === true ) {
237
- level = 'warn' ;
238
- } else if ( filterResult . forceDialogImmediately === true ) {
239
- level = 'fatal' ; // Do not downgrade. These are real bugs with same severity as throws.
240
- }
241
- }
242
-
243
- // Unfortunately, we need to add the Warning: prefix back for downstream dependencies.
244
- // Downstream, we check for this prefix to know that LogBox already handled it, so
245
- // it doesn't get reported back to LogBox. It's an absolute mess.
246
- args [ 0 ] = `Warning: ${ filterResult . finalFormat } ` ;
247
- const { category, message, componentStack, componentStackType} =
248
- parseLogBoxLog ( args ) ;
249
-
250
- // Interpolate the message so they are formatted for adb and other CLIs.
251
- // This is different than the message.content above because it includes component stacks.
252
- const interpolated = parseInterpolation ( args ) ;
253
- originalConsoleError ( interpolated . message . content ) ;
254
-
255
- if ( ! LogBoxData . isMessageIgnored ( message . content ) ) {
256
- LogBoxData . addLog ( {
257
- level,
258
- category,
259
- message,
260
- componentStack,
261
- componentStackType,
262
- } ) ;
263
- }
264
- } catch ( err ) {
265
- LogBoxData . reportLogBoxError ( err ) ;
266
- }
267
- } ;
268
228
} else {
269
229
LogBox = {
270
230
install ( ) : void {
@@ -295,6 +255,10 @@ if (__DEV__) {
295
255
// Do nothing.
296
256
} ,
297
257
258
+ addConsoleLog ( level : 'warn' | 'error' , ...args : Array < mixed > ) : void {
259
+ // Do nothing.
260
+ } ,
261
+
298
262
addException ( error : ExtendedExceptionData ) : void {
299
263
// Do nothing.
300
264
} ,
0 commit comments