Skip to content

Commit da7cdec

Browse files
author
Brian Vaughn
committed
Patch console to append component stacks
1 parent 0f2fb5b commit da7cdec

3 files changed

Lines changed: 70 additions & 3 deletions

File tree

src/backend/console.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// @flow
2+
3+
import type { ReactRenderer } from './types';
4+
5+
let disabled: boolean = false;
6+
7+
export function disable(): void {
8+
disabled = true;
9+
}
10+
11+
export function enable(): void {
12+
disabled = false;
13+
}
14+
15+
export function patch({ debugCurrentFrame }: ReactRenderer): void {
16+
for (let method in console) {
17+
const originalMethod = console[method];
18+
const appendComponentStack =
19+
debugCurrentFrame != null &&
20+
(method === 'error' || method === 'warn' || method === 'trace');
21+
try {
22+
// $FlowFixMe property error|warn is not writable.
23+
console[method] = (...args) => {
24+
if (disabled) return;
25+
if (appendComponentStack) {
26+
const componentStack = debugCurrentFrame.getStackAddendum();
27+
if (componentStack) {
28+
args.push(componentStack);
29+
}
30+
}
31+
originalMethod(...args);
32+
};
33+
} catch (error) {}
34+
}
35+
}

src/backend/renderer.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ import {
3939
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
4040
} from '../constants';
4141
import { inspectHooksOfFiber } from './ReactDebugHooks';
42+
import {
43+
disable as disableConsole,
44+
enable as enableConsole,
45+
patch as patchConsole,
46+
} from './console';
4247

4348
import type {
4449
ChangeDescription,
@@ -267,6 +272,11 @@ export function attach(
267272
DEPRECATED_PLACEHOLDER_SYMBOL_STRING,
268273
} = ReactSymbols;
269274

275+
// Patching the console enables DevTools to do a few useful things:
276+
// * Append component stacks to warnings and error messages
277+
// * Disable logging during re-renders to inspect hooks (see inspectHooksOfFiber)
278+
patchConsole(renderer);
279+
270280
const {
271281
overrideHookState,
272282
overrideProps,
@@ -2109,6 +2119,20 @@ export function attach(
21092119
node = node.return;
21102120
}
21112121

2122+
let hooks = null;
2123+
if (usesHooks) {
2124+
// Suppress console logging while re-rendering
2125+
try {
2126+
disableConsole();
2127+
hooks = inspectHooksOfFiber(
2128+
fiber,
2129+
(renderer.currentDispatcherRef: any)
2130+
);
2131+
} finally {
2132+
enableConsole();
2133+
}
2134+
}
2135+
21122136
return {
21132137
id,
21142138

@@ -2136,9 +2160,7 @@ export function attach(
21362160
// TODO Review sanitization approach for the below inspectable values.
21372161
context,
21382162
events,
2139-
hooks: usesHooks
2140-
? inspectHooksOfFiber(fiber, (renderer.currentDispatcherRef: any))
2141-
: null,
2163+
hooks,
21422164
props: memoizedProps,
21432165
state: usesHooks ? null : memoizedState,
21442166

src/backend/types.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ export type GetFiberIDForNative = (
9191
) => number | null;
9292
export type FindNativeNodesForFiberID = (id: number) => ?Array<NativeType>;
9393

94+
type ReactDebugCurrentFrame = {|
95+
// Stack implementation injected by the current renderer.
96+
getCurrentStack: () => string,
97+
getStackAddendum: () => string,
98+
|};
99+
94100
export type ReactRenderer = {
95101
findFiberByHostInstance: (hostInstance: NativeType) => ?Fiber,
96102
version: string,
@@ -118,6 +124,10 @@ export type ReactRenderer = {
118124
// Only injected by React v16.8+ in order to support hooks inspection.
119125
currentDispatcherRef?: {| current: null | Dispatcher |},
120126

127+
// Only injected by React v16.9+ in DEV mode.
128+
// Enables DevTools to append component stack to error messages.
129+
debugCurrentFrame: ReactDebugCurrentFrame,
130+
121131
// <= 15
122132
Mount?: any,
123133
};

0 commit comments

Comments
 (0)