From 77f576ce16d02322eabc7a3e754f5c7fb44bc375 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Wed, 15 Nov 2017 12:17:21 -0800 Subject: [PATCH] Bugfix: nextFlushedRoot should always be set when performing work (#11558) Fixes an issue where performWorkOnRoot was called, but nextFlushedRoot was not set. This happened in a special branch where we synchronously flush newly mounted DOM trees outside the normal work loop. Arguably, performWorkOnRoot should read from the globally assigned root and expiration time instead of accepting arguments, since those arguments are expected to be the same as the global values, anyway. I decided against that since the global values could be null, so reading from them would require extra null checks. --- .../src/__tests__/ReactErrorBoundaries-test.js | 12 ++++++++++++ packages/react-reconciler/src/ReactFiberScheduler.js | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.js b/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.js index 01b2b33f34..266e196ba8 100644 --- a/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.js +++ b/packages/react-dom/src/__tests__/ReactErrorBoundaries-test.js @@ -2001,4 +2001,16 @@ describe('ReactErrorBoundaries', () => { // Error should be the first thrown expect(caughtError.message).toBe('child sad'); }); + + it('propagates uncaught error inside unbatched initial mount', () => { + function Foo() { + throw new Error('foo error'); + } + const container = document.createElement('div'); + expect(() => { + ReactDOM.unstable_batchedUpdates(() => { + ReactDOM.render(, container); + }); + }).toThrow('foo error'); + }); }); diff --git a/packages/react-reconciler/src/ReactFiberScheduler.js b/packages/react-reconciler/src/ReactFiberScheduler.js index 66c05df6cc..3ec8cdde42 100644 --- a/packages/react-reconciler/src/ReactFiberScheduler.js +++ b/packages/react-reconciler/src/ReactFiberScheduler.js @@ -1330,7 +1330,9 @@ export default function( if (isUnbatchingUpdates) { // ...unless we're inside unbatchedUpdates, in which case we should // flush it now. - performWorkOnRoot(root, Sync); + nextFlushedRoot = root; + nextFlushedExpirationTime = Sync; + performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime); } return; }