From 3c7d52c3d6d316d09d5c2479c6851acecccc6325 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Sat, 2 May 2020 00:41:39 +0100 Subject: [PATCH] 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 --- .../src/__tests__/ReactLazy-test.internal.js | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js index 4c2b44d62307..2f79cdf653ef 100644 --- a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js @@ -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( + + }> + + + , + {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( + + }> + + + , + ); + + expect(Scheduler).toHaveYielded([]); + + expect(componentStackMessage).toContain('in Lazy'); + }); });