Skip to content

Commit

Permalink
Handle errors thrown in gDSFP of a module-style context provider (#13269
Browse files Browse the repository at this point in the history
)

Context should be pushed before calling any user code, so if it errors
the stack unwinds correctly.
  • Loading branch information
acdlite committed Jul 25, 2018
1 parent 0154a79 commit bc1ea9c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
9 changes: 5 additions & 4 deletions packages/react-reconciler/src/ReactFiberBeginWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,11 @@ function mountIndeterminateComponent(
// Proceed under the assumption that this is a class instance
workInProgress.tag = ClassComponent;

// Push context providers early to prevent context stack mismatches.
// During mounting we don't know the child context yet as the instance doesn't exist.
// We will invalidate the child context in finishClassComponent() right after rendering.
const hasContext = pushLegacyContextProvider(workInProgress);

workInProgress.memoizedState =
value.state !== null && value.state !== undefined ? value.state : null;

Expand All @@ -630,10 +635,6 @@ function mountIndeterminateComponent(
);
}

// Push context providers early to prevent context stack mismatches.
// During mounting we don't know the child context yet as the instance doesn't exist.
// We will invalidate the child context in finishClassComponent() right after rendering.
const hasContext = pushLegacyContextProvider(workInProgress);
adoptClassInstance(workInProgress, value);
mountClassInstance(workInProgress, renderExpirationTime);
return finishClassComponent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1469,4 +1469,26 @@ describe('ReactIncrementalErrorHandling', () => {
ReactNoop.flushDeferredPri();
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]);
});

it('handles error thrown inside getDerivedStateFromProps of a module-style context provider', () => {
function Provider() {
return {
getChildContext() {
return {foo: 'bar'};
},
render() {
return 'Hi';
},
};
}
Provider.childContextTypes = {
x: () => {},
};
Provider.getDerivedStateFromProps = () => {
throw new Error('Oops!');
};

ReactNoop.render(<Provider />);
expect(() => ReactNoop.flush()).toThrow('Oops!');
});
});

0 comments on commit bc1ea9c

Please sign in to comment.