mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Fix an infinite loop in new context (#12402)
* Add a regression test for the context infinite loop * Fix the bug We set .return pointer inside the loop, but the top-level parent-child relationship happens outside. This ensures the top-level parent's child points to the right copy of the parent. Otherwise we may end up in a situation where (workInProgress === nextFiber) is never true and we loop forever.
This commit is contained in:
@@ -776,6 +776,10 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
|
||||
renderExpirationTime: ExpirationTime,
|
||||
): void {
|
||||
let fiber = workInProgress.child;
|
||||
if (fiber !== null) {
|
||||
// Set the return pointer of the child to the work-in-progress fiber.
|
||||
fiber.return = workInProgress;
|
||||
}
|
||||
while (fiber !== null) {
|
||||
let nextFiber;
|
||||
// Visit this fiber.
|
||||
|
||||
@@ -762,6 +762,41 @@ describe('ReactNewContext', () => {
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Child')]);
|
||||
});
|
||||
|
||||
// This is a regression case for https://github.com/facebook/react/issues/12389.
|
||||
it('does not run into an infinite loop', () => {
|
||||
const Context = React.createContext(null);
|
||||
|
||||
class App extends React.Component {
|
||||
renderItem(id) {
|
||||
return (
|
||||
<span key={id}>
|
||||
<Context.Consumer>{() => <span>inner</span>}</Context.Consumer>
|
||||
<span>outer</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
renderList() {
|
||||
const list = [1, 2].map(id => this.renderItem(id));
|
||||
if (this.props.reverse) {
|
||||
list.reverse();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Context.Provider value={{}}>{this.renderList()}</Context.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactNoop.render(<App reverse={false} />);
|
||||
ReactNoop.flush();
|
||||
ReactNoop.render(<App reverse={true} />);
|
||||
ReactNoop.flush();
|
||||
ReactNoop.render(<App reverse={false} />);
|
||||
ReactNoop.flush();
|
||||
});
|
||||
|
||||
describe('fuzz test', () => {
|
||||
const Fragment = React.Fragment;
|
||||
const contextKeys = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
||||
|
||||
Reference in New Issue
Block a user