Give unresolved lazy() a name in component stack (#16104)

* Give unresolved lazy() a name in component stack

* Normalize stack in tests

Co-authored-by: Sebastian Markbage <sema@fb.com>
This commit is contained in:
Moti Zilberman
2020-05-01 16:41:39 -07:00
committed by GitHub
co-authored by Sebastian Markbage
parent 333deb707d
commit 3c7d52c3d6
@@ -6,6 +6,15 @@ let ReactFeatureFlags;
let Suspense;
let lazy;
function normalizeCodeLocInfo(str) {
return (
str &&
str.replace(/\n +(?:at|in) ([\S]+)[^\n]*/g, function(m, name) {
return '\n in ' + name + ' (at **)';
})
);
}
describe('ReactLazy', () => {
beforeEach(() => {
jest.resetModules();
@@ -1183,4 +1192,85 @@ describe('ReactLazy', () => {
expect(Scheduler).toFlushAndYield([]);
}).toErrorDev('Function components cannot be given refs');
});
it('should error with a component stack naming the resolved component', async () => {
let componentStackMessage;
const LazyText = lazy(() =>
fakeImport(function ResolvedText() {
throw new Error('oh no');
}),
);
class ErrorBoundary extends React.Component {
state = {error: null};
componentDidCatch(error, errMessage) {
componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);
this.setState({
error,
});
}
render() {
return this.state.error ? null : this.props.children;
}
}
ReactTestRenderer.create(
<ErrorBoundary>
<Suspense fallback={<Text text="Loading..." />}>
<LazyText text="Hi" />
</Suspense>
</ErrorBoundary>,
{unstable_isConcurrent: true},
);
expect(Scheduler).toFlushAndYield(['Loading...']);
try {
await Promise.resolve();
} catch (e) {}
expect(Scheduler).toFlushAndYield([]);
expect(componentStackMessage).toContain('in ResolvedText');
});
it('should error with a component stack containing Lazy if unresolved', () => {
let componentStackMessage;
const LazyText = lazy(() => ({
then(resolve, reject) {
reject(new Error('oh no'));
},
}));
class ErrorBoundary extends React.Component {
state = {error: null};
componentDidCatch(error, errMessage) {
componentStackMessage = normalizeCodeLocInfo(errMessage.componentStack);
this.setState({
error,
});
}
render() {
return this.state.error ? null : this.props.children;
}
}
ReactTestRenderer.create(
<ErrorBoundary>
<Suspense fallback={<Text text="Loading..." />}>
<LazyText text="Hi" />
</Suspense>
</ErrorBoundary>,
);
expect(Scheduler).toHaveYielded([]);
expect(componentStackMessage).toContain('in Lazy');
});
});