Skip to content

Commit 22dc2e4

Browse files
author
Brian Vaughn
authored
Add experimental DebugTracing logger for internal use (facebook#18531)
1 parent dbd2626 commit 22dc2e4

33 files changed

+1050
-19
lines changed

packages/react-dom/src/__tests__/ReactDOMServerIntegrationModes-test.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,56 @@ describe('ReactDOMServerIntegration', () => {
3939
resetModules();
4040
});
4141

42+
// Test pragmas don't support itRenders abstraction
43+
if (
44+
__EXPERIMENTAL__ &&
45+
require('shared/ReactFeatureFlags').enableDebugTracing
46+
) {
47+
describe('React.unstable_DebugTracingMode', () => {
48+
beforeEach(() => {
49+
spyOnDevAndProd(console, 'log');
50+
});
51+
52+
itRenders('with one child', async render => {
53+
const e = await render(
54+
<React.unstable_DebugTracingMode>
55+
<div>text1</div>
56+
</React.unstable_DebugTracingMode>,
57+
);
58+
const parent = e.parentNode;
59+
expect(parent.childNodes[0].tagName).toBe('DIV');
60+
});
61+
62+
itRenders('mode with several children', async render => {
63+
const Header = props => {
64+
return <p>header</p>;
65+
};
66+
const Footer = props => {
67+
return (
68+
<React.unstable_DebugTracingMode>
69+
<h2>footer</h2>
70+
<h3>about</h3>
71+
</React.unstable_DebugTracingMode>
72+
);
73+
};
74+
const e = await render(
75+
<React.unstable_DebugTracingMode>
76+
<div>text1</div>
77+
<span>text2</span>
78+
<Header />
79+
<Footer />
80+
</React.unstable_DebugTracingMode>,
81+
);
82+
const parent = e.parentNode;
83+
expect(parent.childNodes[0].tagName).toBe('DIV');
84+
expect(parent.childNodes[1].tagName).toBe('SPAN');
85+
expect(parent.childNodes[2].tagName).toBe('P');
86+
expect(parent.childNodes[3].tagName).toBe('H2');
87+
expect(parent.childNodes[4].tagName).toBe('H3');
88+
});
89+
});
90+
}
91+
4292
describe('React.StrictMode', () => {
4393
itRenders('a strict mode with one child', async render => {
4494
const e = await render(

packages/react-dom/src/server/ReactPartialRenderer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
} from 'shared/ReactFeatureFlags';
2929

3030
import {
31+
REACT_DEBUG_TRACING_MODE_TYPE,
3132
REACT_FORWARD_REF_TYPE,
3233
REACT_FRAGMENT_TYPE,
3334
REACT_STRICT_MODE_TYPE,
@@ -1002,6 +1003,7 @@ class ReactDOMServerRenderer {
10021003
}
10031004

10041005
switch (elementType) {
1006+
case REACT_DEBUG_TRACING_MODE_TYPE:
10051007
case REACT_STRICT_MODE_TYPE:
10061008
case REACT_PROFILER_TYPE:
10071009
case REACT_SUSPENSE_LIST_TYPE:
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
import type {Wakeable} from 'shared/ReactTypes';
11+
12+
import {enableDebugTracing} from 'shared/ReactFeatureFlags';
13+
14+
const nativeConsole: Object = console;
15+
let nativeConsoleLog: null | Function = null;
16+
17+
const pendingGroupArgs: Array<any> = [];
18+
let printedGroupIndex: number = -1;
19+
20+
function group(...groupArgs): void {
21+
pendingGroupArgs.push(groupArgs);
22+
23+
if (nativeConsoleLog === null) {
24+
nativeConsoleLog = nativeConsole.log;
25+
nativeConsole.log = log;
26+
}
27+
}
28+
29+
function groupEnd(): void {
30+
pendingGroupArgs.pop();
31+
while (printedGroupIndex >= pendingGroupArgs.length) {
32+
nativeConsole.groupEnd();
33+
printedGroupIndex--;
34+
}
35+
36+
if (pendingGroupArgs.length === 0) {
37+
nativeConsole.log = nativeConsoleLog;
38+
nativeConsoleLog = null;
39+
}
40+
}
41+
42+
function log(...logArgs): void {
43+
if (printedGroupIndex < pendingGroupArgs.length - 1) {
44+
for (let i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) {
45+
const groupArgs = pendingGroupArgs[i];
46+
nativeConsole.group(...groupArgs);
47+
}
48+
printedGroupIndex = pendingGroupArgs.length - 1;
49+
}
50+
if (typeof nativeConsoleLog === 'function') {
51+
nativeConsoleLog(...logArgs);
52+
} else {
53+
nativeConsole.log(...logArgs);
54+
}
55+
}
56+
57+
const REACT_LOGO_STYLE =
58+
'background-color: #20232a; color: #61dafb; padding: 0 2px;';
59+
60+
export function logCommitStarted(priorityLabel: string): void {
61+
if (__DEV__) {
62+
if (enableDebugTracing) {
63+
group(
64+
`%c⚛️%c commit%c (priority: ${priorityLabel})`,
65+
REACT_LOGO_STYLE,
66+
'',
67+
'font-weight: normal;',
68+
);
69+
}
70+
}
71+
}
72+
73+
export function logCommitStopped(): void {
74+
if (__DEV__) {
75+
if (enableDebugTracing) {
76+
groupEnd();
77+
}
78+
}
79+
}
80+
81+
const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
82+
// $FlowFixMe: Flow cannot handle polymorphic WeakMaps
83+
const wakeableIDs: WeakMap<Wakeable, number> = new PossiblyWeakMap();
84+
let wakeableID: number = 0;
85+
function getWakeableID(wakeable: Wakeable): number {
86+
if (!wakeableIDs.has(wakeable)) {
87+
wakeableIDs.set(wakeable, wakeableID++);
88+
}
89+
return ((wakeableIDs.get(wakeable): any): number);
90+
}
91+
92+
export function logComponentSuspended(
93+
componentName: string,
94+
wakeable: Wakeable,
95+
): void {
96+
if (__DEV__) {
97+
if (enableDebugTracing) {
98+
const id = getWakeableID(wakeable);
99+
const display = (wakeable: any).displayName || wakeable;
100+
log(
101+
`%c⚛️%c ${componentName} suspended`,
102+
REACT_LOGO_STYLE,
103+
'color: #80366d; font-weight: bold;',
104+
id,
105+
display,
106+
);
107+
wakeable.then(
108+
() => {
109+
log(
110+
`%c⚛️%c ${componentName} resolved`,
111+
REACT_LOGO_STYLE,
112+
'color: #80366d; font-weight: bold;',
113+
id,
114+
display,
115+
);
116+
},
117+
() => {
118+
log(
119+
`%c⚛️%c ${componentName} rejected`,
120+
REACT_LOGO_STYLE,
121+
'color: #80366d; font-weight: bold;',
122+
id,
123+
display,
124+
);
125+
},
126+
);
127+
}
128+
}
129+
}
130+
131+
export function logLayoutEffectsStarted(priorityLabel: string): void {
132+
if (__DEV__) {
133+
if (enableDebugTracing) {
134+
group(
135+
`%c⚛️%c layout effects%c (priority: ${priorityLabel})`,
136+
REACT_LOGO_STYLE,
137+
'',
138+
'font-weight: normal;',
139+
);
140+
}
141+
}
142+
}
143+
144+
export function logLayoutEffectsStopped(): void {
145+
if (__DEV__) {
146+
if (enableDebugTracing) {
147+
groupEnd();
148+
}
149+
}
150+
}
151+
152+
export function logPassiveEffectsStarted(priorityLabel: string): void {
153+
if (__DEV__) {
154+
if (enableDebugTracing) {
155+
group(
156+
`%c⚛️%c passive effects%c (priority: ${priorityLabel})`,
157+
REACT_LOGO_STYLE,
158+
'',
159+
'font-weight: normal;',
160+
);
161+
}
162+
}
163+
}
164+
165+
export function logPassiveEffectsStopped(): void {
166+
if (__DEV__) {
167+
if (enableDebugTracing) {
168+
groupEnd();
169+
}
170+
}
171+
}
172+
173+
export function logRenderStarted(priorityLabel: string): void {
174+
if (__DEV__) {
175+
if (enableDebugTracing) {
176+
group(
177+
`%c⚛️%c render%c (priority: ${priorityLabel})`,
178+
REACT_LOGO_STYLE,
179+
'',
180+
'font-weight: normal;',
181+
);
182+
}
183+
}
184+
}
185+
186+
export function logRenderStopped(): void {
187+
if (__DEV__) {
188+
if (enableDebugTracing) {
189+
groupEnd();
190+
}
191+
}
192+
}
193+
194+
export function logForceUpdateScheduled(
195+
componentName: string,
196+
priorityLabel: string,
197+
): void {
198+
if (__DEV__) {
199+
if (enableDebugTracing) {
200+
log(
201+
`%c⚛️%c ${componentName} forced update %c(priority: ${priorityLabel})`,
202+
REACT_LOGO_STYLE,
203+
'color: #db2e1f; font-weight: bold;',
204+
'',
205+
);
206+
}
207+
}
208+
}
209+
210+
export function logStateUpdateScheduled(
211+
componentName: string,
212+
priorityLabel: string,
213+
payloadOrAction: any,
214+
): void {
215+
if (__DEV__) {
216+
if (enableDebugTracing) {
217+
log(
218+
`%c⚛️%c ${componentName} updated state %c(priority: ${priorityLabel})`,
219+
REACT_LOGO_STYLE,
220+
'color: #01a252; font-weight: bold;',
221+
'',
222+
payloadOrAction,
223+
);
224+
}
225+
}
226+
}

packages/react-reconciler/src/ReactFiber.new.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ import {NoWork} from './ReactFiberExpirationTime.new';
6767
import {
6868
NoMode,
6969
ConcurrentMode,
70+
DebugTracingMode,
7071
ProfileMode,
7172
StrictMode,
7273
BlockingMode,
7374
} from './ReactTypeOfMode';
7475
import {
7576
REACT_FORWARD_REF_TYPE,
7677
REACT_FRAGMENT_TYPE,
78+
REACT_DEBUG_TRACING_MODE_TYPE,
7779
REACT_STRICT_MODE_TYPE,
7880
REACT_PROFILER_TYPE,
7981
REACT_PROVIDER_TYPE,
@@ -488,6 +490,10 @@ export function createFiberFromTypeAndProps(
488490
expirationTime,
489491
key,
490492
);
493+
case REACT_DEBUG_TRACING_MODE_TYPE:
494+
fiberTag = Mode;
495+
mode |= DebugTracingMode;
496+
break;
491497
case REACT_STRICT_MODE_TYPE:
492498
fiberTag = Mode;
493499
mode |= StrictMode;

packages/react-reconciler/src/ReactFiber.old.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ import {NoWork} from './ReactFiberExpirationTime.old';
6767
import {
6868
NoMode,
6969
ConcurrentMode,
70+
DebugTracingMode,
7071
ProfileMode,
7172
StrictMode,
7273
BlockingMode,
7374
} from './ReactTypeOfMode';
7475
import {
7576
REACT_FORWARD_REF_TYPE,
7677
REACT_FRAGMENT_TYPE,
78+
REACT_DEBUG_TRACING_MODE_TYPE,
7779
REACT_STRICT_MODE_TYPE,
7880
REACT_PROFILER_TYPE,
7981
REACT_PROVIDER_TYPE,
@@ -488,6 +490,10 @@ export function createFiberFromTypeAndProps(
488490
expirationTime,
489491
key,
490492
);
493+
case REACT_DEBUG_TRACING_MODE_TYPE:
494+
fiberTag = Mode;
495+
mode |= DebugTracingMode;
496+
break;
491497
case REACT_STRICT_MODE_TYPE:
492498
fiberTag = Mode;
493499
mode |= StrictMode;

0 commit comments

Comments
 (0)