@@ -80,9 +80,25 @@ export function registerRenderer(renderer: ReactRenderer): void {
80
80
}
81
81
}
82
82
83
+ const consoleSettingsRef = {
84
+ appendComponentStack : false ,
85
+ breakOnConsoleErrors : false ,
86
+ } ;
87
+
83
88
// Patches whitelisted console methods to append component stack for the current fiber.
84
89
// Call unpatch() to remove the injected behavior.
85
- export function patch ( ) : void {
90
+ export function patch ( {
91
+ appendComponentStack,
92
+ breakOnConsoleErrors,
93
+ } : {
94
+ appendComponentStack : boolean ,
95
+ breakOnConsoleErrors : boolean ,
96
+ } ) : void {
97
+ // Settings may change after we've patched the console.
98
+ // Using a shared ref allows the patch function to read the latest values.
99
+ consoleSettingsRef . appendComponentStack = appendComponentStack ;
100
+ consoleSettingsRef . breakOnConsoleErrors = breakOnConsoleErrors ;
101
+
86
102
if ( unpatchFn !== null ) {
87
103
// Don't patch twice.
88
104
return ;
@@ -105,40 +121,56 @@ export function patch(): void {
105
121
targetConsole [ method ] ) ;
106
122
107
123
const overrideMethod = ( ...args ) => {
108
- try {
109
- // If we are ever called with a string that already has a component stack, e.g. a React error/warning,
110
- // don't append a second stack.
111
- const lastArg = args . length > 0 ? args [ args . length - 1 ] : null ;
112
- const alreadyHasComponentStack =
113
- lastArg !== null &&
114
- ( PREFIX_REGEX . test ( lastArg ) ||
115
- ROW_COLUMN_NUMBER_REGEX . test ( lastArg ) ) ;
116
-
117
- if ( ! alreadyHasComponentStack ) {
118
- // If there's a component stack for at least one of the injected renderers, append it.
119
- // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?)
120
- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
121
- for ( const {
122
- currentDispatcherRef,
123
- getCurrentFiber,
124
- workTagMap,
125
- } of injectedRenderers . values ( ) ) {
126
- const current : ?Fiber = getCurrentFiber ( ) ;
127
- if ( current != null ) {
128
- const componentStack = getStackByFiberInDevAndProd (
129
- workTagMap ,
130
- current ,
131
- currentDispatcherRef ,
132
- ) ;
133
- if ( componentStack !== '' ) {
134
- args . push ( componentStack ) ;
124
+ const latestAppendComponentStack =
125
+ consoleSettingsRef . appendComponentStack ;
126
+ const latestBreakOnConsoleErrors =
127
+ consoleSettingsRef . breakOnConsoleErrors ;
128
+
129
+ if ( latestAppendComponentStack ) {
130
+ try {
131
+ // If we are ever called with a string that already has a component stack, e.g. a React error/warning,
132
+ // don't append a second stack.
133
+ const lastArg = args . length > 0 ? args [ args . length - 1 ] : null ;
134
+ const alreadyHasComponentStack =
135
+ lastArg !== null &&
136
+ ( PREFIX_REGEX . test ( lastArg ) ||
137
+ ROW_COLUMN_NUMBER_REGEX . test ( lastArg ) ) ;
138
+
139
+ if ( ! alreadyHasComponentStack ) {
140
+ // If there's a component stack for at least one of the injected renderers, append it.
141
+ // We don't handle the edge case of stacks for more than one (e.g. interleaved renderers?)
142
+ // eslint-disable-next-line no-for-of-loops/no-for-of-loops
143
+ for ( const {
144
+ currentDispatcherRef,
145
+ getCurrentFiber,
146
+ workTagMap,
147
+ } of injectedRenderers . values ( ) ) {
148
+ const current : ?Fiber = getCurrentFiber ( ) ;
149
+ if ( current != null ) {
150
+ const componentStack = getStackByFiberInDevAndProd (
151
+ workTagMap ,
152
+ current ,
153
+ currentDispatcherRef ,
154
+ ) ;
155
+ if ( componentStack !== '' ) {
156
+ args . push ( componentStack ) ;
157
+ }
158
+ break ;
135
159
}
136
- break ;
137
160
}
138
161
}
162
+ } catch ( error ) {
163
+ // Don't let a DevTools or React internal error interfere with logging.
139
164
}
140
- } catch ( error ) {
141
- // Don't let a DevTools or React internal error interfere with logging.
165
+ }
166
+
167
+ if ( latestBreakOnConsoleErrors ) {
168
+ // --- Welcome to debugging with React DevTools ---
169
+ // This debugger statement means that you've enabled the "break on warnings" feature.
170
+ // Use the browser's Call Stack panel to step out of this override function-
171
+ // to where the original warning or error was logged.
172
+ // eslint-disable-next-line no-debugger
173
+ debugger ;
142
174
}
143
175
144
176
originalMethod ( ...args ) ;
0 commit comments