diff --git a/src/renderers/shared/fiber/ReactFiberScheduler.js b/src/renderers/shared/fiber/ReactFiberScheduler.js index d861c81cd17d..757b9244eb6f 100644 --- a/src/renderers/shared/fiber/ReactFiberScheduler.js +++ b/src/renderers/shared/fiber/ReactFiberScheduler.js @@ -70,11 +70,19 @@ module.exports = function(config : HostConfig) { let nextUnitOfWork : ?Fiber = null; let nextPriorityLevel : PriorityLevel = NoWork; + // The next errors we need to handle before next item of work. + let nextTrappedErrors : Array | null = null; + // Linked list of roots with scheduled work on them. let nextScheduledRoot : ?FiberRoot = null; let lastScheduledRoot : ?FiberRoot = null; function findNextUnitOfWork() { + if (nextTrappedErrors) { + // While we have errors, we can't perform any normal work. + return null; + } + // Clear out roots with no more work on them. while (nextScheduledRoot && nextScheduledRoot.current.pendingWorkPriority === NoWork) { nextScheduledRoot.isScheduled = false; @@ -204,10 +212,7 @@ module.exports = function(config : HostConfig) { } } - // Now that the tree has been committed, we can handle errors. - if (allTrappedErrors) { - handleErrors(allTrappedErrors); - } + nextTrappedErrors = allTrappedErrors; } function resetWorkPriority(workInProgress : Fiber) { @@ -377,7 +382,10 @@ module.exports = function(config : HostConfig) { throw error; } const trappedError = trapError(failedUnitOfWork, error); - handleErrors([trappedError]); + nextTrappedErrors = [trappedError]; + } + if (nextTrappedErrors) { + handleErrors(); } } @@ -444,7 +452,10 @@ module.exports = function(config : HostConfig) { throw error; } const trappedError = trapError(failedUnitOfWork, error); - handleErrors([trappedError]); + nextTrappedErrors = [trappedError]; + } + if (nextTrappedErrors) { + handleErrors(); } } @@ -498,8 +509,7 @@ module.exports = function(config : HostConfig) { return root; } - function handleErrors(initialTrappedErrors : Array) : void { - let nextTrappedErrors = initialTrappedErrors; + function handleErrors() : void { let firstUncaughtError = null; // In each phase, we will attempt to pass errors to boundaries and re-render them. @@ -543,8 +553,6 @@ module.exports = function(config : HostConfig) { let fiber = cloneFiber(root.current, priority); try { while (fiber) { - // TODO: this is the only place where we recurse and it's unfortunate. - // (This may potentially get us into handleErrors() again.) fiber = performUnitOfWork(fiber, true); } } catch (nextError) {