Disable console.logs in the second render pass of DEV mode double render (#18547)
* Disable console log during the second rerender * Use the disabled log to avoid double yielding values in scheduler mock * Reenable debugRenderPhaseSideEffectsForStrictMode in tests that can
Sebastian Markbåge committed
Apr 8, 2020 at 16:43 UTC
5474a83e258b497584bed9df95de1d554bc53f89
43 files changed
+221
-162
packages/create-subscription/src/__tests__/createSubscription-test.internal.js
+1
-3
@@ -11,7 +11,6 @@
11
12
let createSubscription;
13
let BehaviorSubject;
14
-let ReactFeatureFlags;
14
let React;
15
let ReactNoop;
16
let Scheduler;
@@ -21,8 +20,7 @@ describe('createSubscription', () => {
20
beforeEach(() => {
21
jest.resetModules();
22
createSubscription = require('create-subscription').createSubscription;
24
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
25
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
23
+
24
React = require('react');
25
ReactNoop = require('react-noop-renderer');
26
Scheduler = require('scheduler');
packages/react-art/src/__tests__/ReactART-test.js
+2
-4
@@ -391,7 +391,7 @@ describe('ReactART', () => {
391
</CurrentRendererContext.Provider>,
392
);
393
394
- expect(Scheduler).toFlushAndYieldThrough(__DEV__ ? ['A', 'A'] : ['A']);
394
+ expect(Scheduler).toFlushAndYieldThrough(['A']);
395
396
ReactDOM.render(
397
<Surface>
@@ -406,9 +406,7 @@ describe('ReactART', () => {
406
expect(ops).toEqual([null, 'ART']);
407
408
ops = [];
409
- expect(Scheduler).toFlushAndYield(
410
- __DEV__ ? ['B', 'B', 'C', 'C'] : ['B', 'C'],
411
- );
409
+ expect(Scheduler).toFlushAndYield(['B', 'C']);
410
411
expect(ops).toEqual(['Test']);
412
});
packages/react-cache/src/__tests__/ReactCache-test.internal.js
+1
-1
@@ -24,7 +24,7 @@ describe('ReactCache', () => {
24
jest.resetModules();
25
26
ReactFeatureFlags = require('shared/ReactFeatureFlags');
27
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
27
+
28
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
29
React = require('react');
30
Suspense = React.Suspense;
packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.internal.js
+2
-6
@@ -10,7 +10,6 @@
10
'use strict';
11
12
let React;
13
-let ReactFeatureFlags = require('shared/ReactFeatureFlags');
13
14
let ReactDOM;
15
let Scheduler;
@@ -149,8 +148,7 @@ describe('ReactDOMFiberAsync', () => {
148
describe('concurrent mode', () => {
149
beforeEach(() => {
150
jest.resetModules();
152
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
153
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
151
+
152
ReactDOM = require('react-dom');
153
Scheduler = require('scheduler');
154
});
@@ -639,9 +637,7 @@ describe('ReactDOMFiberAsync', () => {
637
expect(container.textContent).toEqual('');
638
639
// Everything should render immediately in the next event
642
- expect(Scheduler).toFlushExpired(
643
- __DEV__ ? ['A', 'A', 'B', 'B', 'C', 'C'] : ['A', 'B', 'C'],
644
- );
640
+ expect(Scheduler).toFlushExpired(['A', 'B', 'C']);
641
expect(container.textContent).toEqual('ABC');
642
});
643
});
packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js
+1
-1
@@ -40,7 +40,7 @@ function initModules() {
40
jest.resetModuleRegistry();
41
42
ReactFeatureFlags = require('shared/ReactFeatureFlags');
43
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
43
+
44
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
45
React = require('react');
46
ReactDOM = require('react-dom');
packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
-1
@@ -77,7 +77,6 @@ describe('ReactDOMServerPartialHydration', () => {
77
ReactFeatureFlags = require('shared/ReactFeatureFlags');
78
ReactFeatureFlags.enableSuspenseCallback = true;
79
ReactFeatureFlags.enableDeprecatedFlareAPI = true;
80
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
80
81
React = require('react');
82
ReactDOM = require('react-dom');
packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js
-1
@@ -97,7 +97,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
97
98
const ReactFeatureFlags = require('shared/ReactFeatureFlags');
99
ReactFeatureFlags.enableDeprecatedFlareAPI = true;
100
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
100
101
React = require('react');
102
ReactDOM = require('react-dom');
packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
-3
@@ -121,7 +121,6 @@ describe('ReactTestUtils.act()', () => {
121
);
122
}).toErrorDev([
123
'An update to App ran an effect, but was not wrapped in act(...)',
124
- 'An update to App ran an effect, but was not wrapped in act(...)',
124
]);
125
});
126
@@ -132,7 +131,6 @@ describe('ReactTestUtils.act()', () => {
131
Scheduler.unstable_flushAll();
132
}).toErrorDev([
133
'An update to App ran an effect, but was not wrapped in act(...)',
135
- 'An update to App ran an effect, but was not wrapped in act(...)',
134
]);
135
});
136
@@ -143,7 +141,6 @@ describe('ReactTestUtils.act()', () => {
141
Scheduler.unstable_flushAll();
142
}).toErrorDev([
143
'An update to App ran an effect, but was not wrapped in act(...)',
146
- 'An update to App ran an effect, but was not wrapped in act(...)',
144
]);
145
});
146
});
packages/react-dom/src/__tests__/ReactUpdates-test.js
+3
-25
@@ -1324,30 +1324,12 @@ describe('ReactUpdates', () => {
1324
let hiddenDiv;
1325
act(() => {
1326
root.render(<Foo />);
1327
- if (__DEV__) {
1328
- expect(Scheduler).toFlushAndYieldThrough([
1329
- 'Foo',
1330
- 'Foo',
1331
- 'Baz',
1332
- 'Baz',
1333
- 'Foo#effect',
1334
- ]);
1335
- } else {
1336
- expect(Scheduler).toFlushAndYieldThrough([
1337
- 'Foo',
1338
- 'Baz',
1339
- 'Foo#effect',
1340
- ]);
1341
- }
1327
+ expect(Scheduler).toFlushAndYieldThrough(['Foo', 'Baz', 'Foo#effect']);
1328
hiddenDiv = container.firstChild.firstChild;
1329
expect(hiddenDiv.hidden).toBe(true);
1330
expect(hiddenDiv.innerHTML).toBe('');
1331
// Run offscreen update
1346
- if (__DEV__) {
1347
- expect(Scheduler).toFlushAndYield(['Bar', 'Bar']);
1348
- } else {
1349
- expect(Scheduler).toFlushAndYield(['Bar']);
1350
- }
1332
+ expect(Scheduler).toFlushAndYield(['Bar']);
1333
expect(hiddenDiv.hidden).toBe(true);
1334
expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');
1335
});
@@ -1359,11 +1341,7 @@ describe('ReactUpdates', () => {
1341
expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');
1342
1343
// Run offscreen update
1362
- if (__DEV__) {
1363
- expect(Scheduler).toFlushAndYield(['Bar', 'Bar']);
1364
- } else {
1365
- expect(Scheduler).toFlushAndYield(['Bar']);
1366
- }
1344
+ expect(Scheduler).toFlushAndYield(['Bar']);
1345
expect(hiddenDiv.innerHTML).toBe('<p>bar 1</p>');
1346
},
1347
);
packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
+2
-12
@@ -1701,12 +1701,7 @@ describe('DOMModernPluginEventSystem', () => {
1701
const root = ReactDOM.createRoot(container);
1702
root.render(<Test counter={0} />);
1703
1704
- // Dev double-render
1705
- if (__DEV__) {
1706
- expect(Scheduler).toFlushAndYield(['Test', 'Test']);
1707
- } else {
1708
- expect(Scheduler).toFlushAndYield(['Test']);
1709
- }
1704
+ expect(Scheduler).toFlushAndYield(['Test']);
1705
1706
// Click the button
1707
dispatchClickEvent(ref.current);
@@ -1718,12 +1713,7 @@ describe('DOMModernPluginEventSystem', () => {
1713
// Increase counter
1714
root.render(<Test counter={1} />);
1715
// Yield before committing
1721
- // Dev double-render
1722
- if (__DEV__) {
1723
- expect(Scheduler).toFlushAndYieldThrough(['Test', 'Test']);
1724
- } else {
1725
- expect(Scheduler).toFlushAndYieldThrough(['Test']);
1726
- }
1716
+ expect(Scheduler).toFlushAndYieldThrough(['Test']);
1717
1718
// Click the button again
1719
dispatchClickEvent(ref.current);
packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js
+2
-4
@@ -811,7 +811,7 @@ describe('DOMEventResponderSystem', () => {
811
812
const root = ReactDOM.createRoot(container);
813
root.render(<Test counter={0} />);
814
- expect(Scheduler).toFlushAndYield(__DEV__ ? ['Test', 'Test'] : ['Test']);
814
+ expect(Scheduler).toFlushAndYield(['Test']);
815
816
// Click the button
817
dispatchClickEvent(ref.current);
@@ -823,9 +823,7 @@ describe('DOMEventResponderSystem', () => {
823
// Increase counter
824
root.render(<Test counter={1} />);
825
// Yield before committing
826
- expect(Scheduler).toFlushAndYieldThrough(
827
- __DEV__ ? ['Test', 'Test'] : ['Test'],
828
- );
826
+ expect(Scheduler).toFlushAndYieldThrough(['Test']);
827
828
// Click the button again
829
dispatchClickEvent(ref.current);
packages/react-reconciler/src/ReactFiberBeginWork.js
+60
-33
@@ -181,6 +181,8 @@ import {
181
getWorkInProgressRoot,
182
} from './ReactFiberWorkLoop';
183
184
+import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
185
+
186
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
187
188
let didReceiveUpdate: boolean = false;
@@ -320,14 +322,19 @@ function updateForwardRef(
322
debugRenderPhaseSideEffectsForStrictMode &&
323
workInProgress.mode & StrictMode
324
) {
323
- nextChildren = renderWithHooks(
324
- current,
325
- workInProgress,
326
- render,
327
- nextProps,
328
- ref,
329
- renderExpirationTime,
330
- );
325
+ disableLogs();
326
+ try {
327
+ nextChildren = renderWithHooks(
328
+ current,
329
+ workInProgress,
330
+ render,
331
+ nextProps,
332
+ ref,
333
+ renderExpirationTime,
334
+ );
335
+ } finally {
336
+ reenableLogs();
337
+ }
338
}
339
setIsRendering(false);
340
} else {
@@ -658,14 +665,19 @@ function updateFunctionComponent(
665
debugRenderPhaseSideEffectsForStrictMode &&
666
workInProgress.mode & StrictMode
667
) {
661
- nextChildren = renderWithHooks(
662
- current,
663
- workInProgress,
664
- Component,
665
- nextProps,
666
- context,
667
- renderExpirationTime,
668
- );
668
+ disableLogs();
669
+ try {
670
+ nextChildren = renderWithHooks(
671
+ current,
672
+ workInProgress,
673
+ Component,
674
+ nextProps,
675
+ context,
676
+ renderExpirationTime,
677
+ );
678
+ } finally {
679
+ reenableLogs();
680
+ }
681
}
682
setIsRendering(false);
683
} else {
@@ -731,14 +743,19 @@ function updateBlock<Props, Data>(
743
debugRenderPhaseSideEffectsForStrictMode &&
744
workInProgress.mode & StrictMode
745
) {
734
- nextChildren = renderWithHooks(
735
- current,
736
- workInProgress,
737
- render,
738
- nextProps,
739
- data,
740
- renderExpirationTime,
741
- );
746
+ disableLogs();
747
+ try {
748
+ nextChildren = renderWithHooks(
749
+ current,
750
+ workInProgress,
751
+ render,
752
+ nextProps,
753
+ data,
754
+ renderExpirationTime,
755
+ );
756
+ } finally {
757
+ reenableLogs();
758
+ }
759
}
760
setIsRendering(false);
761
} else {
@@ -923,7 +940,12 @@ function finishClassComponent(
940
debugRenderPhaseSideEffectsForStrictMode &&
941
workInProgress.mode & StrictMode
942
) {
926
- instance.render();
943
+ disableLogs();
944
+ try {
945
+ instance.render();
946
+ } finally {
947
+ reenableLogs();
948
+ }
949
}
950
setIsRendering(false);
951
} else {
@@ -1485,14 +1507,19 @@ function mountIndeterminateComponent(
1507
debugRenderPhaseSideEffectsForStrictMode &&
1508
workInProgress.mode & StrictMode
1509
) {
1488
- value = renderWithHooks(
1489
- null,
1490
- workInProgress,
1491
- Component,
1492
- props,
1493
- context,
1494
- renderExpirationTime,
1495
- );
1510
+ disableLogs();
1511
+ try {
1512
+ value = renderWithHooks(
1513
+ null,
1514
+ workInProgress,
1515
+ Component,
1516
+ props,
1517
+ context,
1518
+ renderExpirationTime,
1519
+ );
1520
+ } finally {
1521
+ reenableLogs();
1522
+ }
1523
}
1524
}
1525
reconcileChildren(null, workInProgress, value, renderExpirationTime);
packages/react-reconciler/src/ReactFiberClassComponent.js
+22
-5
@@ -56,6 +56,8 @@ import {
56
} from './ReactFiberWorkLoop';
57
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
58
59
+import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
60
+
61
const fakeInternalInstance = {};
62
const isArray = Array.isArray;
63
@@ -151,8 +153,13 @@ export function applyDerivedStateFromProps(
153
debugRenderPhaseSideEffectsForStrictMode &&
154
workInProgress.mode & StrictMode
155
) {
154
- // Invoke the function an extra time to help detect side-effects.
155
- getDerivedStateFromProps(nextProps, prevState);
156
+ disableLogs();
157
+ try {
158
+ // Invoke the function an extra time to help detect side-effects.
159
+ getDerivedStateFromProps(nextProps, prevState);
160
+ } finally {
161
+ reenableLogs();
162
+ }
163
}
164
}
165
@@ -266,8 +273,13 @@ function checkShouldComponentUpdate(
273
debugRenderPhaseSideEffectsForStrictMode &&
274
workInProgress.mode & StrictMode
275
) {
269
- // Invoke the function an extra time to help detect side-effects.
270
- instance.shouldComponentUpdate(newProps, newState, nextContext);
276
+ disableLogs();
277
+ try {
278
+ // Invoke the function an extra time to help detect side-effects.
279
+ instance.shouldComponentUpdate(newProps, newState, nextContext);
280
+ } finally {
281
+ reenableLogs();
282
+ }
283
}
284
}
285
const shouldUpdate = instance.shouldComponentUpdate(
@@ -598,7 +610,12 @@ function constructClassInstance(
610
debugRenderPhaseSideEffectsForStrictMode &&
611
workInProgress.mode & StrictMode
612
) {
601
- new ctor(props, context); // eslint-disable-line no-new
613
+ disableLogs();
614
+ try {
615
+ new ctor(props, context); // eslint-disable-line no-new
616
+ } finally {
617
+ reenableLogs();
618
+ }
619
}
620
}
621
packages/react-reconciler/src/ReactUpdateQueue.js
+14
-2
@@ -107,6 +107,8 @@ import {
107
import invariant from 'shared/invariant';
108
import {getCurrentPriorityLevel} from './SchedulerWithReactIntegration';
109
110
+import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
111
+
112
export type Update<State> = {|
113
expirationTime: ExpirationTime,
114
suspenseConfig: null | SuspenseConfig,
@@ -336,7 +338,12 @@ function getStateFromUpdate<State>(
338
debugRenderPhaseSideEffectsForStrictMode &&
339
workInProgress.mode & StrictMode
340
) {
339
- payload.call(instance, prevState, nextProps);
341
+ disableLogs();
342
+ try {
343
+ payload.call(instance, prevState, nextProps);
344
+ } finally {
345
+ reenableLogs();
346
+ }
347
}
348
}
349
const nextState = payload.call(instance, prevState, nextProps);
@@ -364,7 +371,12 @@ function getStateFromUpdate<State>(
371
debugRenderPhaseSideEffectsForStrictMode &&
372
workInProgress.mode & StrictMode
373
) {
367
- payload.call(instance, prevState, nextProps);
374
+ disableLogs();
375
+ try {
376
+ payload.call(instance, prevState, nextProps);
377
+ } finally {
378
+ reenableLogs();
379
+ }
380
}
381
}
382
partialState = payload.call(instance, prevState, nextProps);
packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js
+1
-1
@@ -12,7 +12,7 @@ describe('ErrorBoundaryReconciliation', () => {
12
jest.resetModules();
13
14
ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
15
+
16
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
17
ReactTestRenderer = require('react-test-renderer');
18
React = require('react');
packages/react-reconciler/src/__tests__/ReactBatchedMode-test.internal.js
+1
-1
@@ -10,7 +10,7 @@ describe('ReactBlockingMode', () => {
10
beforeEach(() => {
11
jest.resetModules();
12
ReactFeatureFlags = require('shared/ReactFeatureFlags');
13
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
13
+
14
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
15
React = require('react');
16
ReactNoop = require('react-noop-renderer');
packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js
+1
-1
@@ -10,7 +10,7 @@ describe('ReactSuspenseList', () => {
10
beforeEach(() => {
11
jest.resetModules();
12
ReactFeatureFlags = require('shared/ReactFeatureFlags');
13
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
13
+
14
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
15
ReactFeatureFlags.disableSchedulerTimeoutBasedOnReactExpirationTime = true;
16
React = require('react');
packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js
+1
-3
@@ -10,15 +10,13 @@
10
'use strict';
11
12
let React;
13
-let ReactFeatureFlags;
13
let ReactNoop;
14
let Scheduler;
15
16
describe('ReactExpiration', () => {
17
beforeEach(() => {
18
jest.resetModules();
20
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
21
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
19
+
20
React = require('react');
21
ReactNoop = require('react-noop-renderer');
22
Scheduler = require('scheduler');
packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js
+1
-1
@@ -26,7 +26,7 @@ describe('ReactHooks', () => {
26
jest.resetModules();
27
28
ReactFeatureFlags = require('shared/ReactFeatureFlags');
29
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
29
+
30
React = require('react');
31
ReactTestRenderer = require('react-test-renderer');
32
Scheduler = require('scheduler');
packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js
+20
-8
@@ -42,7 +42,7 @@ describe('ReactHooksWithNoopRenderer', () => {
42
jest.useFakeTimers();
43
44
ReactFeatureFlags = require('shared/ReactFeatureFlags');
45
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
45
+
46
ReactFeatureFlags.enableSchedulerTracing = true;
47
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
48
ReactFeatureFlags.enableProfilerTimer = true;
@@ -299,25 +299,29 @@ describe('ReactHooksWithNoopRenderer', () => {
299
});
300
301
it('returns the same updater function every time', () => {
302
- const updaters = [];
302
+ let updater = null;
303
function Counter() {
304
const [count, updateCount] = useState(0);
305
- updaters.push(updateCount);
305
+ updater = updateCount;
306
return <Text text={'Count: ' + count} />;
307
}
308
ReactNoop.render(<Counter />);
309
expect(Scheduler).toFlushAndYield(['Count: 0']);
310
expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
311
312
- act(() => updaters[0](1));
312
+ const firstUpdater = updater;
313
+
314
+ act(() => firstUpdater(1));
315
expect(Scheduler).toHaveYielded(['Count: 1']);
316
expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]);
317
316
- act(() => updaters[0](count => count + 10));
318
+ const secondUpdater = updater;
319
+
320
+ act(() => firstUpdater(count => count + 10));
321
expect(Scheduler).toHaveYielded(['Count: 11']);
322
expect(ReactNoop.getChildren()).toEqual([span('Count: 11')]);
323
320
- expect(updaters).toEqual([updaters[0], updaters[0], updaters[0]]);
324
+ expect(firstUpdater).toBe(secondUpdater);
325
});
326
327
it('warns on set after unmount', () => {
@@ -476,7 +480,11 @@ describe('ReactHooksWithNoopRenderer', () => {
480
</>,
481
);
482
expect(() =>
479
- expect(Scheduler).toFlushAndYield(['Foo [0]', 'Bar', 'Foo [1]']),
483
+ expect(Scheduler).toFlushAndYield(
484
+ __DEV__
485
+ ? ['Foo [0]', 'Bar', 'Foo [2]']
486
+ : ['Foo [0]', 'Bar', 'Foo [1]'],
487
+ ),
488
).toErrorDev([
489
'Cannot update a component (`Foo`) while rendering a ' +
490
'different component (`Bar`). To locate the bad setState() call inside `Bar`',
@@ -491,7 +499,11 @@ describe('ReactHooksWithNoopRenderer', () => {
499
<Bar triggerUpdate={true} />
500
</>,
501
);
494
- expect(Scheduler).toFlushAndYield(['Foo [1]', 'Bar', 'Foo [2]']);
502
+ expect(Scheduler).toFlushAndYield(
503
+ __DEV__
504
+ ? ['Foo [2]', 'Bar', 'Foo [4]']
505
+ : ['Foo [1]', 'Bar', 'Foo [2]'],
506
+ );
507
});
508
});
509
packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js
+2
-3
@@ -188,14 +188,13 @@ describe('ReactIncrementalErrorLogging', () => {
188
expect(Scheduler).toFlushAndYield(
189
[
190
'render: 0',
191
- __DEV__ && 'render: 0', // replay
191
192
'render: 1',
194
- __DEV__ && 'render: 1', // replay
193
+ __DEV__ && 'render: 1', // replay due to invokeGuardedCallback
194
195
// Retry one more time before handling error
196
'render: 1',
198
- __DEV__ && 'render: 1', // replay
197
+ __DEV__ && 'render: 1', // replay due to invokeGuardedCallback
198
199
'componentWillUnmount: 0',
200
].filter(Boolean),
packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js
+1
-3
@@ -11,15 +11,13 @@
11
'use strict';
12
13
let React;
14
-let ReactFeatureFlags;
14
let ReactNoop;
15
let Scheduler;
16
17
describe('ReactIncrementalReflection', () => {
18
beforeEach(() => {
19
jest.resetModules();
21
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
22
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
20
+
21
React = require('react');
22
ReactNoop = require('react-noop-renderer');
23
Scheduler = require('scheduler');
packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.internal.js
+2
-4
@@ -11,15 +11,13 @@
11
'use strict';
12
13
let React;
14
-let ReactFeatureFlags;
14
let ReactNoop;
15
let Scheduler;
16
17
describe('ReactIncrementalSideEffects', () => {
18
beforeEach(() => {
19
jest.resetModules();
21
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
22
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
20
+
21
React = require('react');
22
ReactNoop = require('react-noop-renderer');
23
Scheduler = require('scheduler');
@@ -897,12 +895,12 @@ describe('ReactIncrementalSideEffects', () => {
895
constructor() {
896
super();
897
this.state = {active: false};
900
- barInstances.push(this);
898
}
899
activate() {
900
this.setState({active: true});
901
}
902
render() {
903
+ barInstances.push(this);
904
Scheduler.unstable_yieldValue('Bar');
905
return <span prop={this.state.active ? 'X' : this.props.idx} />;
906
}
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+1
-1
@@ -10,7 +10,7 @@ describe('ReactLazy', () => {
10
beforeEach(() => {
11
jest.resetModules();
12
ReactFeatureFlags = require('shared/ReactFeatureFlags');
13
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
13
+
14
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
15
PropTypes = require('prop-types');
16
React = require('react');
packages/react-reconciler/src/__tests__/ReactMemo-test.internal.js
+1
-3
@@ -14,7 +14,6 @@
14
15
let PropTypes;
16
let React;
17
-let ReactFeatureFlags;
17
let ReactNoop;
18
let Suspense;
19
let Scheduler;
@@ -22,8 +21,7 @@ let Scheduler;
21
describe('memo', () => {
22
beforeEach(() => {
23
jest.resetModules();
25
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
26
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
24
+
25
PropTypes = require('prop-types');
26
React = require('react');
27
ReactNoop = require('react-noop-renderer');
packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js
+4
-8
@@ -9,8 +9,6 @@
9
10
'use strict';
11
12
-let ReactFeatureFlags = require('shared/ReactFeatureFlags');
13
-
12
let React = require('react');
13
let useContext;
14
let ReactNoop;
@@ -20,8 +18,7 @@ let gen;
18
describe('ReactNewContext', () => {
19
beforeEach(() => {
20
jest.resetModules();
23
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
21
+
22
React = require('react');
23
useContext = React.useContext;
24
ReactNoop = require('react-noop-renderer');
@@ -1096,16 +1093,13 @@ describe('ReactNewContext', () => {
1093
1094
// Get a new copy of ReactNoop
1095
jest.resetModules();
1099
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
1096
React = require('react');
1097
ReactNoop = require('react-noop-renderer');
1098
Scheduler = require('scheduler');
1099
1100
// Render the provider again using a different renderer
1101
ReactNoop.render(<App value={1} />);
1106
- expect(Scheduler).toFlushAndYield(
1107
- __DEV__ ? ['Foo', 'Foo', 'Foo', 'Foo'] : ['Foo', 'Foo'],
1108
- );
1102
+ expect(Scheduler).toFlushAndYield(['Foo', 'Foo']);
1103
1104
if (__DEV__) {
1105
expect(console.error.calls.argsFor(0)[0]).toContain(
@@ -1481,6 +1475,8 @@ describe('ReactNewContext', () => {
1475
1476
ReactNoop.render(<Cls />);
1477
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev([
1478
+ 'Context can only be read while React is rendering',
1479
+ // A second warning comes from to setStates being added to the queue.
1480
'Context can only be read while React is rendering',
1481
'Cannot update during an existing state transition',
1482
]);
packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.internal.js
+1
-5
@@ -11,7 +11,6 @@
11
'use strict';
12
13
let React;
14
-let ReactFeatureFlags;
14
let ReactNoop;
15
let Scheduler;
16
let ImmediatePriority;
@@ -24,8 +23,7 @@ let runWithPriority;
23
describe('ReactSchedulerIntegration', () => {
24
beforeEach(() => {
25
jest.resetModules();
27
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
28
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
26
+
27
React = require('react');
28
ReactNoop = require('react-noop-renderer');
29
Scheduler = require('scheduler');
@@ -417,8 +415,6 @@ describe(
415
416
beforeEach(() => {
417
jest.resetModules();
420
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
421
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
418
419
jest.mock('scheduler', () => {
420
const actual = require.requireActual('scheduler/unstable_mock');
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+1
-1
@@ -16,7 +16,7 @@ describe('ReactSuspense', () => {
16
beforeEach(() => {
17
jest.resetModules();
18
ReactFeatureFlags = require('shared/ReactFeatureFlags');
19
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
19
+
20
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
21
ReactFeatureFlags.enableSchedulerTracing = true;
22
React = require('react');
packages/react-reconciler/src/__tests__/ReactSuspenseFuzz-test.internal.js
+1
-1
@@ -21,7 +21,7 @@ describe('ReactSuspenseFuzz', () => {
21
beforeEach(() => {
22
jest.resetModules();
23
ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
24
+
25
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
26
React = require('react');
27
Suspense = React.Suspense;
packages/react-reconciler/src/__tests__/ReactSuspenseList-test.internal.js
+1
-1
@@ -14,7 +14,7 @@ describe('ReactSuspenseList', () => {
14
beforeEach(() => {
15
jest.resetModules();
16
ReactFeatureFlags = require('shared/ReactFeatureFlags');
17
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
17
+
18
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
19
ReactFeatureFlags.enableSuspenseServerRenderer = true;
20
React = require('react');
packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js
+1
-1
@@ -23,7 +23,7 @@ describe('ReactSuspensePlaceholder', () => {
23
jest.resetModules();
24
25
ReactFeatureFlags = require('shared/ReactFeatureFlags');
26
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
26
+
27
ReactFeatureFlags.enableProfilerTimer = true;
28
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
29
React = require('react');
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js
+1
-1
@@ -20,7 +20,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
20
jest.resetModules();
21
22
ReactFeatureFlags = require('shared/ReactFeatureFlags');
23
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
23
+
24
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
25
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
26
React = require('react');
packages/react-reconciler/src/__tests__/ReactTransition-test.internal.js
+1
-1
@@ -24,7 +24,7 @@ describe('ReactTransition', () => {
24
jest.resetModules();
25
26
ReactFeatureFlags = require('shared/ReactFeatureFlags');
27
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
27
+
28
ReactFeatureFlags.enableSchedulerTracing = true;
29
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
30
React = require('react');
packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js
+1
-1
@@ -24,7 +24,7 @@ function loadModules() {
24
jest.useFakeTimers();
25
26
ReactFeatureFlags = require('shared/ReactFeatureFlags');
27
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
27
+
28
ReactFeatureFlags.enableSchedulerTracing = true;
29
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
30
ReactFeatureFlags.enableProfilerTimer = true;
packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.internal.js
+1
-3
@@ -11,15 +11,13 @@
11
'use strict';
12
13
let React;
14
-let ReactFeatureFlags;
14
let ReactTestRenderer;
15
let Scheduler;
16
17
describe('ReactTestRendererAsync', () => {
18
beforeEach(() => {
19
jest.resetModules();
21
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
22
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
20
+
21
React = require('react');
22
ReactTestRenderer = require('react-test-renderer');
23
Scheduler = require('scheduler');
packages/react/src/__tests__/ReactDOMTracing-test.internal.js
+1
-1
@@ -25,7 +25,7 @@ let onWorkStopped;
25
26
function loadModules() {
27
ReactFeatureFlags = require('shared/ReactFeatureFlags');
28
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
28
+
29
ReactFeatureFlags.enableProfilerTimer = true;
30
ReactFeatureFlags.enableSchedulerTracing = true;
31
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
packages/react/src/__tests__/ReactProfiler-test.internal.js
+1
-1
@@ -32,7 +32,7 @@ function loadModules({
32
useNoopRenderer = false,
33
} = {}) {
34
ReactFeatureFlags = require('shared/ReactFeatureFlags');
35
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
35
+
36
ReactFeatureFlags.deferPassiveEffectCleanupDuringUnmount = deferPassiveEffectCleanupDuringUnmount;
37
ReactFeatureFlags.runAllPassiveEffectDestroysBeforeCreates = deferPassiveEffectCleanupDuringUnmount;
38
ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;
packages/react/src/__tests__/ReactProfilerDOM-test.internal.js
+1
-1
@@ -17,7 +17,7 @@ let Scheduler;
17
18
function loadModules() {
19
ReactFeatureFlags = require('shared/ReactFeatureFlags');
20
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
20
+
21
ReactFeatureFlags.enableProfilerTimer = true;
22
ReactFeatureFlags.enableSchedulerTracing = true;
23
packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js
+2
-2
@@ -188,7 +188,7 @@ describe('ReactProfiler DevTools integration', () => {
188
189
// Commit something
190
root.update(<Text text="A" />);
191
- expect(Scheduler).toFlushAndYield(__DEV__ ? ['A', 'A'] : ['A']);
191
+ expect(Scheduler).toFlushAndYield(['A']);
192
expect(root).toMatchRenderedOutput('A');
193
194
// Advance time by many seconds, larger than the default expiration time
@@ -200,7 +200,7 @@ describe('ReactProfiler DevTools integration', () => {
200
// Update B should not instantly expire.
201
expect(Scheduler).toFlushExpired([]);
202
203
- expect(Scheduler).toFlushAndYield(__DEV__ ? ['B', 'B'] : ['B']);
203
+ expect(Scheduler).toFlushAndYield(['B']);
204
expect(root).toMatchRenderedOutput('B');
205
});
206
});
packages/react/src/__tests__/forwardRef-test.internal.js
+1
-1
@@ -18,7 +18,7 @@ describe('forwardRef', () => {
18
beforeEach(() => {
19
jest.resetModules();
20
ReactFeatureFlags = require('shared/ReactFeatureFlags');
21
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
21
+
22
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
23
React = require('react');
24
ReactNoop = require('react-noop-renderer');
packages/scheduler/src/forks/SchedulerHostConfig.mock.js
+12
@@ -192,6 +192,12 @@ export function unstable_flushAll(): void {
192
}
193
194
export function unstable_yieldValue(value: mixed): void {
195
+ // eslint-disable-next-line react-internal/no-production-logging
196
+ if (console.log.name === 'disabledLog') {
197
+ // If console.log has been patched, we assume we're in render
198
+ // replaying and we ignore any values yielding in the second pass.
199
+ return;
200
+ }
201
if (yieldedValues === null) {
202
yieldedValues = [value];
203
} else {
@@ -200,6 +206,12 @@ export function unstable_yieldValue(value: mixed): void {
206
}
207
208
export function unstable_advanceTime(ms: number) {
209
+ // eslint-disable-next-line react-internal/no-production-logging
210
+ if (console.log.name === 'disabledLog') {
211
+ // If console.log has been patched, we assume we're in render
212
+ // replaying and we ignore any time advancing in the second pass.
213
+ return;
214
+ }
215
currentTime += ms;
216
if (scheduledTimeout !== null && timeoutTime <= currentTime) {
217
scheduledTimeout(currentTime);
packages/shared/ConsolePatchingDev.js
new
+48
@@ -0,0 +1,48 @@
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
+// Helpers to patch console.logs to avoid logging during side-effect free
11
+// replaying on render function. This currently only patches the object
12
+// lazily which won't cover if the log function was extracted eagerly.
13
+// We could also eagerly patch the method.
14
+
15
+let prevLog;
16
+let prevInfo;
17
+let prevWarn;
18
+let prevError;
19
+
20
+function disabledLog() {}
21
+
22
+export function disableLogs(): void {
23
+ if (__DEV__) {
24
+ /* eslint-disable react-internal/no-production-logging */
25
+ prevLog = console.log;
26
+ prevInfo = console.info;
27
+ prevWarn = console.warn;
28
+ prevError = console.error;
29
+ // $FlowFixMe Flow thinks console is immutable.
30
+ console.log = console.info = console.warn = console.error = disabledLog;
31
+ /* eslint-enable react-internal/no-production-logging */
32
+ }
33
+}
34
+
35
+export function reenableLogs(): void {
36
+ if (__DEV__) {
37
+ /* eslint-disable react-internal/no-production-logging */
38
+ // $FlowFixMe Flow thinks console is immutable.
39
+ console.log = prevLog;
40
+ // $FlowFixMe Flow thinks console is immutable.
41
+ console.info = prevInfo;
42
+ // $FlowFixMe Flow thinks console is immutable.
43
+ console.warn = prevWarn;
44
+ // $FlowFixMe Flow thinks console is immutable.
45
+ console.error = prevError;
46
+ /* eslint-enable react-internal/no-production-logging */
47
+ }
48
+}
packages/use-subscription/src/__tests__/useSubscription-test.internal.js
-3
@@ -22,9 +22,6 @@ describe('useSubscription', () => {
22
jest.resetModules();
23
jest.mock('scheduler', () => require('scheduler/unstable_mock'));
24
25
- const ReactFeatureFlags = require('shared/ReactFeatureFlags');
26
- ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
27
-
25
useSubscription = require('use-subscription').useSubscription;
26
React = require('react');
27
ReactTestRenderer = require('react-test-renderer');