mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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
This commit is contained in:
committed by
GitHub
parent
b225d4f261
commit
5474a83e25
@@ -11,7 +11,6 @@
|
||||
|
||||
let createSubscription;
|
||||
let BehaviorSubject;
|
||||
let ReactFeatureFlags;
|
||||
let React;
|
||||
let ReactNoop;
|
||||
let Scheduler;
|
||||
@@ -21,8 +20,7 @@ describe('createSubscription', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
createSubscription = require('create-subscription').createSubscription;
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
+2
-4
@@ -391,7 +391,7 @@ describe('ReactART', () => {
|
||||
</CurrentRendererContext.Provider>,
|
||||
);
|
||||
|
||||
expect(Scheduler).toFlushAndYieldThrough(__DEV__ ? ['A', 'A'] : ['A']);
|
||||
expect(Scheduler).toFlushAndYieldThrough(['A']);
|
||||
|
||||
ReactDOM.render(
|
||||
<Surface>
|
||||
@@ -406,9 +406,7 @@ describe('ReactART', () => {
|
||||
expect(ops).toEqual([null, 'ART']);
|
||||
|
||||
ops = [];
|
||||
expect(Scheduler).toFlushAndYield(
|
||||
__DEV__ ? ['B', 'B', 'C', 'C'] : ['B', 'C'],
|
||||
);
|
||||
expect(Scheduler).toFlushAndYield(['B', 'C']);
|
||||
|
||||
expect(ops).toEqual(['Test']);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('ReactCache', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
React = require('react');
|
||||
Suspense = React.Suspense;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
|
||||
let ReactDOM;
|
||||
let Scheduler;
|
||||
@@ -149,8 +148,7 @@ describe('ReactDOMFiberAsync', () => {
|
||||
describe('concurrent mode', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactDOM = require('react-dom');
|
||||
Scheduler = require('scheduler');
|
||||
});
|
||||
@@ -639,9 +637,7 @@ describe('ReactDOMFiberAsync', () => {
|
||||
expect(container.textContent).toEqual('');
|
||||
|
||||
// Everything should render immediately in the next event
|
||||
expect(Scheduler).toFlushExpired(
|
||||
__DEV__ ? ['A', 'A', 'B', 'B', 'C', 'C'] : ['A', 'B', 'C'],
|
||||
);
|
||||
expect(Scheduler).toFlushExpired(['A', 'B', 'C']);
|
||||
expect(container.textContent).toEqual('ABC');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ function initModules() {
|
||||
jest.resetModuleRegistry();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
|
||||
@@ -77,7 +77,6 @@ describe('ReactDOMServerPartialHydration', () => {
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.enableSuspenseCallback = true;
|
||||
ReactFeatureFlags.enableDeprecatedFlareAPI = true;
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
|
||||
@@ -97,7 +97,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
|
||||
|
||||
const ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.enableDeprecatedFlareAPI = true;
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
|
||||
@@ -121,7 +121,6 @@ describe('ReactTestUtils.act()', () => {
|
||||
);
|
||||
}).toErrorDev([
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -132,7 +131,6 @@ describe('ReactTestUtils.act()', () => {
|
||||
Scheduler.unstable_flushAll();
|
||||
}).toErrorDev([
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -143,7 +141,6 @@ describe('ReactTestUtils.act()', () => {
|
||||
Scheduler.unstable_flushAll();
|
||||
}).toErrorDev([
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
'An update to App ran an effect, but was not wrapped in act(...)',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+3
-25
@@ -1324,30 +1324,12 @@ describe('ReactUpdates', () => {
|
||||
let hiddenDiv;
|
||||
act(() => {
|
||||
root.render(<Foo />);
|
||||
if (__DEV__) {
|
||||
expect(Scheduler).toFlushAndYieldThrough([
|
||||
'Foo',
|
||||
'Foo',
|
||||
'Baz',
|
||||
'Baz',
|
||||
'Foo#effect',
|
||||
]);
|
||||
} else {
|
||||
expect(Scheduler).toFlushAndYieldThrough([
|
||||
'Foo',
|
||||
'Baz',
|
||||
'Foo#effect',
|
||||
]);
|
||||
}
|
||||
expect(Scheduler).toFlushAndYieldThrough(['Foo', 'Baz', 'Foo#effect']);
|
||||
hiddenDiv = container.firstChild.firstChild;
|
||||
expect(hiddenDiv.hidden).toBe(true);
|
||||
expect(hiddenDiv.innerHTML).toBe('');
|
||||
// Run offscreen update
|
||||
if (__DEV__) {
|
||||
expect(Scheduler).toFlushAndYield(['Bar', 'Bar']);
|
||||
} else {
|
||||
expect(Scheduler).toFlushAndYield(['Bar']);
|
||||
}
|
||||
expect(Scheduler).toFlushAndYield(['Bar']);
|
||||
expect(hiddenDiv.hidden).toBe(true);
|
||||
expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');
|
||||
});
|
||||
@@ -1359,11 +1341,7 @@ describe('ReactUpdates', () => {
|
||||
expect(hiddenDiv.innerHTML).toBe('<p>bar 0</p>');
|
||||
|
||||
// Run offscreen update
|
||||
if (__DEV__) {
|
||||
expect(Scheduler).toFlushAndYield(['Bar', 'Bar']);
|
||||
} else {
|
||||
expect(Scheduler).toFlushAndYield(['Bar']);
|
||||
}
|
||||
expect(Scheduler).toFlushAndYield(['Bar']);
|
||||
expect(hiddenDiv.innerHTML).toBe('<p>bar 1</p>');
|
||||
},
|
||||
);
|
||||
|
||||
+2
-12
@@ -1701,12 +1701,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(<Test counter={0} />);
|
||||
|
||||
// Dev double-render
|
||||
if (__DEV__) {
|
||||
expect(Scheduler).toFlushAndYield(['Test', 'Test']);
|
||||
} else {
|
||||
expect(Scheduler).toFlushAndYield(['Test']);
|
||||
}
|
||||
expect(Scheduler).toFlushAndYield(['Test']);
|
||||
|
||||
// Click the button
|
||||
dispatchClickEvent(ref.current);
|
||||
@@ -1718,12 +1713,7 @@ describe('DOMModernPluginEventSystem', () => {
|
||||
// Increase counter
|
||||
root.render(<Test counter={1} />);
|
||||
// Yield before committing
|
||||
// Dev double-render
|
||||
if (__DEV__) {
|
||||
expect(Scheduler).toFlushAndYieldThrough(['Test', 'Test']);
|
||||
} else {
|
||||
expect(Scheduler).toFlushAndYieldThrough(['Test']);
|
||||
}
|
||||
expect(Scheduler).toFlushAndYieldThrough(['Test']);
|
||||
|
||||
// Click the button again
|
||||
dispatchClickEvent(ref.current);
|
||||
|
||||
+2
-4
@@ -811,7 +811,7 @@ describe('DOMEventResponderSystem', () => {
|
||||
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(<Test counter={0} />);
|
||||
expect(Scheduler).toFlushAndYield(__DEV__ ? ['Test', 'Test'] : ['Test']);
|
||||
expect(Scheduler).toFlushAndYield(['Test']);
|
||||
|
||||
// Click the button
|
||||
dispatchClickEvent(ref.current);
|
||||
@@ -823,9 +823,7 @@ describe('DOMEventResponderSystem', () => {
|
||||
// Increase counter
|
||||
root.render(<Test counter={1} />);
|
||||
// Yield before committing
|
||||
expect(Scheduler).toFlushAndYieldThrough(
|
||||
__DEV__ ? ['Test', 'Test'] : ['Test'],
|
||||
);
|
||||
expect(Scheduler).toFlushAndYieldThrough(['Test']);
|
||||
|
||||
// Click the button again
|
||||
dispatchClickEvent(ref.current);
|
||||
|
||||
+60
-33
@@ -181,6 +181,8 @@ import {
|
||||
getWorkInProgressRoot,
|
||||
} from './ReactFiberWorkLoop';
|
||||
|
||||
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
|
||||
|
||||
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
|
||||
|
||||
let didReceiveUpdate: boolean = false;
|
||||
@@ -320,14 +322,19 @@ function updateForwardRef(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
render,
|
||||
nextProps,
|
||||
ref,
|
||||
renderExpirationTime,
|
||||
);
|
||||
disableLogs();
|
||||
try {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
render,
|
||||
nextProps,
|
||||
ref,
|
||||
renderExpirationTime,
|
||||
);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
setIsRendering(false);
|
||||
} else {
|
||||
@@ -658,14 +665,19 @@ function updateFunctionComponent(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
Component,
|
||||
nextProps,
|
||||
context,
|
||||
renderExpirationTime,
|
||||
);
|
||||
disableLogs();
|
||||
try {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
Component,
|
||||
nextProps,
|
||||
context,
|
||||
renderExpirationTime,
|
||||
);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
setIsRendering(false);
|
||||
} else {
|
||||
@@ -731,14 +743,19 @@ function updateBlock<Props, Data>(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
render,
|
||||
nextProps,
|
||||
data,
|
||||
renderExpirationTime,
|
||||
);
|
||||
disableLogs();
|
||||
try {
|
||||
nextChildren = renderWithHooks(
|
||||
current,
|
||||
workInProgress,
|
||||
render,
|
||||
nextProps,
|
||||
data,
|
||||
renderExpirationTime,
|
||||
);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
setIsRendering(false);
|
||||
} else {
|
||||
@@ -923,7 +940,12 @@ function finishClassComponent(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
instance.render();
|
||||
disableLogs();
|
||||
try {
|
||||
instance.render();
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
setIsRendering(false);
|
||||
} else {
|
||||
@@ -1485,14 +1507,19 @@ function mountIndeterminateComponent(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
value = renderWithHooks(
|
||||
null,
|
||||
workInProgress,
|
||||
Component,
|
||||
props,
|
||||
context,
|
||||
renderExpirationTime,
|
||||
);
|
||||
disableLogs();
|
||||
try {
|
||||
value = renderWithHooks(
|
||||
null,
|
||||
workInProgress,
|
||||
Component,
|
||||
props,
|
||||
context,
|
||||
renderExpirationTime,
|
||||
);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
reconcileChildren(null, workInProgress, value, renderExpirationTime);
|
||||
|
||||
+22
-5
@@ -56,6 +56,8 @@ import {
|
||||
} from './ReactFiberWorkLoop';
|
||||
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
|
||||
|
||||
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
|
||||
|
||||
const fakeInternalInstance = {};
|
||||
const isArray = Array.isArray;
|
||||
|
||||
@@ -151,8 +153,13 @@ export function applyDerivedStateFromProps(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
// Invoke the function an extra time to help detect side-effects.
|
||||
getDerivedStateFromProps(nextProps, prevState);
|
||||
disableLogs();
|
||||
try {
|
||||
// Invoke the function an extra time to help detect side-effects.
|
||||
getDerivedStateFromProps(nextProps, prevState);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,8 +273,13 @@ function checkShouldComponentUpdate(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
// Invoke the function an extra time to help detect side-effects.
|
||||
instance.shouldComponentUpdate(newProps, newState, nextContext);
|
||||
disableLogs();
|
||||
try {
|
||||
// Invoke the function an extra time to help detect side-effects.
|
||||
instance.shouldComponentUpdate(newProps, newState, nextContext);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
const shouldUpdate = instance.shouldComponentUpdate(
|
||||
@@ -598,7 +610,12 @@ function constructClassInstance(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
new ctor(props, context); // eslint-disable-line no-new
|
||||
disableLogs();
|
||||
try {
|
||||
new ctor(props, context); // eslint-disable-line no-new
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-2
@@ -107,6 +107,8 @@ import {
|
||||
import invariant from 'shared/invariant';
|
||||
import {getCurrentPriorityLevel} from './SchedulerWithReactIntegration';
|
||||
|
||||
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
|
||||
|
||||
export type Update<State> = {|
|
||||
expirationTime: ExpirationTime,
|
||||
suspenseConfig: null | SuspenseConfig,
|
||||
@@ -336,7 +338,12 @@ function getStateFromUpdate<State>(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
payload.call(instance, prevState, nextProps);
|
||||
disableLogs();
|
||||
try {
|
||||
payload.call(instance, prevState, nextProps);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
const nextState = payload.call(instance, prevState, nextProps);
|
||||
@@ -364,7 +371,12 @@ function getStateFromUpdate<State>(
|
||||
debugRenderPhaseSideEffectsForStrictMode &&
|
||||
workInProgress.mode & StrictMode
|
||||
) {
|
||||
payload.call(instance, prevState, nextProps);
|
||||
disableLogs();
|
||||
try {
|
||||
payload.call(instance, prevState, nextProps);
|
||||
} finally {
|
||||
reenableLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
partialState = payload.call(instance, prevState, nextProps);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ describe('ErrorBoundaryReconciliation', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
React = require('react');
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('ReactBlockingMode', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ describe('ReactSuspenseList', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
ReactFeatureFlags.disableSchedulerTimeoutBasedOnReactExpirationTime = true;
|
||||
React = require('react');
|
||||
|
||||
@@ -10,15 +10,13 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactNoop;
|
||||
let Scheduler;
|
||||
|
||||
describe('ReactExpiration', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('ReactHooks', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
+20
-8
@@ -42,7 +42,7 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
|
||||
ReactFeatureFlags.enableProfilerTimer = true;
|
||||
@@ -299,25 +299,29 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
});
|
||||
|
||||
it('returns the same updater function every time', () => {
|
||||
const updaters = [];
|
||||
let updater = null;
|
||||
function Counter() {
|
||||
const [count, updateCount] = useState(0);
|
||||
updaters.push(updateCount);
|
||||
updater = updateCount;
|
||||
return <Text text={'Count: ' + count} />;
|
||||
}
|
||||
ReactNoop.render(<Counter />);
|
||||
expect(Scheduler).toFlushAndYield(['Count: 0']);
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
|
||||
|
||||
act(() => updaters[0](1));
|
||||
const firstUpdater = updater;
|
||||
|
||||
act(() => firstUpdater(1));
|
||||
expect(Scheduler).toHaveYielded(['Count: 1']);
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]);
|
||||
|
||||
act(() => updaters[0](count => count + 10));
|
||||
const secondUpdater = updater;
|
||||
|
||||
act(() => firstUpdater(count => count + 10));
|
||||
expect(Scheduler).toHaveYielded(['Count: 11']);
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: 11')]);
|
||||
|
||||
expect(updaters).toEqual([updaters[0], updaters[0], updaters[0]]);
|
||||
expect(firstUpdater).toBe(secondUpdater);
|
||||
});
|
||||
|
||||
it('warns on set after unmount', () => {
|
||||
@@ -476,7 +480,11 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
</>,
|
||||
);
|
||||
expect(() =>
|
||||
expect(Scheduler).toFlushAndYield(['Foo [0]', 'Bar', 'Foo [1]']),
|
||||
expect(Scheduler).toFlushAndYield(
|
||||
__DEV__
|
||||
? ['Foo [0]', 'Bar', 'Foo [2]']
|
||||
: ['Foo [0]', 'Bar', 'Foo [1]'],
|
||||
),
|
||||
).toErrorDev([
|
||||
'Cannot update a component (`Foo`) while rendering a ' +
|
||||
'different component (`Bar`). To locate the bad setState() call inside `Bar`',
|
||||
@@ -491,7 +499,11 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
<Bar triggerUpdate={true} />
|
||||
</>,
|
||||
);
|
||||
expect(Scheduler).toFlushAndYield(['Foo [1]', 'Bar', 'Foo [2]']);
|
||||
expect(Scheduler).toFlushAndYield(
|
||||
__DEV__
|
||||
? ['Foo [2]', 'Bar', 'Foo [4]']
|
||||
: ['Foo [1]', 'Bar', 'Foo [2]'],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+2
-3
@@ -188,14 +188,13 @@ describe('ReactIncrementalErrorLogging', () => {
|
||||
expect(Scheduler).toFlushAndYield(
|
||||
[
|
||||
'render: 0',
|
||||
__DEV__ && 'render: 0', // replay
|
||||
|
||||
'render: 1',
|
||||
__DEV__ && 'render: 1', // replay
|
||||
__DEV__ && 'render: 1', // replay due to invokeGuardedCallback
|
||||
|
||||
// Retry one more time before handling error
|
||||
'render: 1',
|
||||
__DEV__ && 'render: 1', // replay
|
||||
__DEV__ && 'render: 1', // replay due to invokeGuardedCallback
|
||||
|
||||
'componentWillUnmount: 0',
|
||||
].filter(Boolean),
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactNoop;
|
||||
let Scheduler;
|
||||
|
||||
describe('ReactIncrementalReflection', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
+2
-4
@@ -11,15 +11,13 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactNoop;
|
||||
let Scheduler;
|
||||
|
||||
describe('ReactIncrementalSideEffects', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
@@ -897,12 +895,12 @@ describe('ReactIncrementalSideEffects', () => {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {active: false};
|
||||
barInstances.push(this);
|
||||
}
|
||||
activate() {
|
||||
this.setState({active: true});
|
||||
}
|
||||
render() {
|
||||
barInstances.push(this);
|
||||
Scheduler.unstable_yieldValue('Bar');
|
||||
return <span prop={this.state.active ? 'X' : this.props.idx} />;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('ReactLazy', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
PropTypes = require('prop-types');
|
||||
React = require('react');
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
let PropTypes;
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactNoop;
|
||||
let Suspense;
|
||||
let Scheduler;
|
||||
@@ -22,8 +21,7 @@ let Scheduler;
|
||||
describe('memo', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
PropTypes = require('prop-types');
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
let ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
|
||||
let React = require('react');
|
||||
let useContext;
|
||||
let ReactNoop;
|
||||
@@ -20,8 +18,7 @@ let gen;
|
||||
describe('ReactNewContext', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
useContext = React.useContext;
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
@@ -1096,16 +1093,13 @@ describe('ReactNewContext', () => {
|
||||
|
||||
// Get a new copy of ReactNoop
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
// Render the provider again using a different renderer
|
||||
ReactNoop.render(<App value={1} />);
|
||||
expect(Scheduler).toFlushAndYield(
|
||||
__DEV__ ? ['Foo', 'Foo', 'Foo', 'Foo'] : ['Foo', 'Foo'],
|
||||
);
|
||||
expect(Scheduler).toFlushAndYield(['Foo', 'Foo']);
|
||||
|
||||
if (__DEV__) {
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain(
|
||||
@@ -1481,6 +1475,8 @@ describe('ReactNewContext', () => {
|
||||
|
||||
ReactNoop.render(<Cls />);
|
||||
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev([
|
||||
'Context can only be read while React is rendering',
|
||||
// A second warning comes from to setStates being added to the queue.
|
||||
'Context can only be read while React is rendering',
|
||||
'Cannot update during an existing state transition',
|
||||
]);
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactNoop;
|
||||
let Scheduler;
|
||||
let ImmediatePriority;
|
||||
@@ -24,8 +23,7 @@ let runWithPriority;
|
||||
describe('ReactSchedulerIntegration', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
@@ -417,8 +415,6 @@ describe(
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
jest.mock('scheduler', () => {
|
||||
const actual = require.requireActual('scheduler/unstable_mock');
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('ReactSuspense', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
React = require('react');
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('ReactSuspenseFuzz', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
React = require('react');
|
||||
Suspense = React.Suspense;
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('ReactSuspenseList', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
ReactFeatureFlags.enableSuspenseServerRenderer = true;
|
||||
React = require('react');
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('ReactSuspensePlaceholder', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableProfilerTimer = true;
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
React = require('react');
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
|
||||
React = require('react');
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('ReactTransition', () => {
|
||||
jest.resetModules();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
|
||||
React = require('react');
|
||||
|
||||
@@ -24,7 +24,7 @@ function loadModules() {
|
||||
jest.useFakeTimers();
|
||||
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
ReactFeatureFlags.flushSuspenseFallbacksInTests = false;
|
||||
ReactFeatureFlags.enableProfilerTimer = true;
|
||||
|
||||
@@ -11,15 +11,13 @@
|
||||
'use strict';
|
||||
|
||||
let React;
|
||||
let ReactFeatureFlags;
|
||||
let ReactTestRenderer;
|
||||
let Scheduler;
|
||||
|
||||
describe('ReactTestRendererAsync', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
React = require('react');
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
Scheduler = require('scheduler');
|
||||
|
||||
@@ -25,7 +25,7 @@ let onWorkStopped;
|
||||
|
||||
function loadModules() {
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableProfilerTimer = true;
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
|
||||
@@ -32,7 +32,7 @@ function loadModules({
|
||||
useNoopRenderer = false,
|
||||
} = {}) {
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.deferPassiveEffectCleanupDuringUnmount = deferPassiveEffectCleanupDuringUnmount;
|
||||
ReactFeatureFlags.runAllPassiveEffectDestroysBeforeCreates = deferPassiveEffectCleanupDuringUnmount;
|
||||
ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;
|
||||
|
||||
@@ -17,7 +17,7 @@ let Scheduler;
|
||||
|
||||
function loadModules() {
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.enableProfilerTimer = true;
|
||||
ReactFeatureFlags.enableSchedulerTracing = true;
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ describe('ReactProfiler DevTools integration', () => {
|
||||
|
||||
// Commit something
|
||||
root.update(<Text text="A" />);
|
||||
expect(Scheduler).toFlushAndYield(__DEV__ ? ['A', 'A'] : ['A']);
|
||||
expect(Scheduler).toFlushAndYield(['A']);
|
||||
expect(root).toMatchRenderedOutput('A');
|
||||
|
||||
// Advance time by many seconds, larger than the default expiration time
|
||||
@@ -200,7 +200,7 @@ describe('ReactProfiler DevTools integration', () => {
|
||||
// Update B should not instantly expire.
|
||||
expect(Scheduler).toFlushExpired([]);
|
||||
|
||||
expect(Scheduler).toFlushAndYield(__DEV__ ? ['B', 'B'] : ['B']);
|
||||
expect(Scheduler).toFlushAndYield(['B']);
|
||||
expect(root).toMatchRenderedOutput('B');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('forwardRef', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
|
||||
@@ -192,6 +192,12 @@ export function unstable_flushAll(): void {
|
||||
}
|
||||
|
||||
export function unstable_yieldValue(value: mixed): void {
|
||||
// eslint-disable-next-line react-internal/no-production-logging
|
||||
if (console.log.name === 'disabledLog') {
|
||||
// If console.log has been patched, we assume we're in render
|
||||
// replaying and we ignore any values yielding in the second pass.
|
||||
return;
|
||||
}
|
||||
if (yieldedValues === null) {
|
||||
yieldedValues = [value];
|
||||
} else {
|
||||
@@ -200,6 +206,12 @@ export function unstable_yieldValue(value: mixed): void {
|
||||
}
|
||||
|
||||
export function unstable_advanceTime(ms: number) {
|
||||
// eslint-disable-next-line react-internal/no-production-logging
|
||||
if (console.log.name === 'disabledLog') {
|
||||
// If console.log has been patched, we assume we're in render
|
||||
// replaying and we ignore any time advancing in the second pass.
|
||||
return;
|
||||
}
|
||||
currentTime += ms;
|
||||
if (scheduledTimeout !== null && timeoutTime <= currentTime) {
|
||||
scheduledTimeout(currentTime);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
// Helpers to patch console.logs to avoid logging during side-effect free
|
||||
// replaying on render function. This currently only patches the object
|
||||
// lazily which won't cover if the log function was extracted eagerly.
|
||||
// We could also eagerly patch the method.
|
||||
|
||||
let prevLog;
|
||||
let prevInfo;
|
||||
let prevWarn;
|
||||
let prevError;
|
||||
|
||||
function disabledLog() {}
|
||||
|
||||
export function disableLogs(): void {
|
||||
if (__DEV__) {
|
||||
/* eslint-disable react-internal/no-production-logging */
|
||||
prevLog = console.log;
|
||||
prevInfo = console.info;
|
||||
prevWarn = console.warn;
|
||||
prevError = console.error;
|
||||
// $FlowFixMe Flow thinks console is immutable.
|
||||
console.log = console.info = console.warn = console.error = disabledLog;
|
||||
/* eslint-enable react-internal/no-production-logging */
|
||||
}
|
||||
}
|
||||
|
||||
export function reenableLogs(): void {
|
||||
if (__DEV__) {
|
||||
/* eslint-disable react-internal/no-production-logging */
|
||||
// $FlowFixMe Flow thinks console is immutable.
|
||||
console.log = prevLog;
|
||||
// $FlowFixMe Flow thinks console is immutable.
|
||||
console.info = prevInfo;
|
||||
// $FlowFixMe Flow thinks console is immutable.
|
||||
console.warn = prevWarn;
|
||||
// $FlowFixMe Flow thinks console is immutable.
|
||||
console.error = prevError;
|
||||
/* eslint-enable react-internal/no-production-logging */
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,6 @@ describe('useSubscription', () => {
|
||||
jest.resetModules();
|
||||
jest.mock('scheduler', () => require('scheduler/unstable_mock'));
|
||||
|
||||
const ReactFeatureFlags = require('shared/ReactFeatureFlags');
|
||||
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
|
||||
|
||||
useSubscription = require('use-subscription').useSubscription;
|
||||
React = require('react');
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
|
||||
Reference in New Issue
Block a user