@samitouri / QOS-React-2 / commits / 5474a83e25

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');