( root: FiberRoot, unitOfWork: Fiber, thrownValue: mixed, suspendedReason: SuspendedReason, )
| 3137 | } |
| 3138 | |
| 3139 | function throwAndUnwindWorkLoop( |
| 3140 | root: FiberRoot, |
| 3141 | unitOfWork: Fiber, |
| 3142 | thrownValue: mixed, |
| 3143 | suspendedReason: SuspendedReason, |
| 3144 | ) { |
| 3145 | // This is a fork of performUnitOfWork specifcally for unwinding a fiber |
| 3146 | // that threw an exception. |
| 3147 | // |
| 3148 | // Return to the normal work loop. This will unwind the stack, and potentially |
| 3149 | // result in showing a fallback. |
| 3150 | resetSuspendedWorkLoopOnUnwind(unitOfWork); |
| 3151 | |
| 3152 | const returnFiber = unitOfWork.return; |
| 3153 | try { |
| 3154 | // Find and mark the nearest Suspense or error boundary that can handle |
| 3155 | // this "exception". |
| 3156 | const didFatal = throwException( |
| 3157 | root, |
| 3158 | returnFiber, |
| 3159 | unitOfWork, |
| 3160 | thrownValue, |
| 3161 | workInProgressRootRenderLanes, |
| 3162 | ); |
| 3163 | if (didFatal) { |
| 3164 | panicOnRootError(root, thrownValue); |
| 3165 | return; |
| 3166 | } |
| 3167 | } catch (error) { |
| 3168 | // We had trouble processing the error. An example of this happening is |
| 3169 | // when accessing the `componentDidCatch` property of an error boundary |
| 3170 | // throws an error. A weird edge case. There's a regression test for this. |
| 3171 | // To prevent an infinite loop, bubble the error up to the next parent. |
| 3172 | if (returnFiber !== null) { |
| 3173 | workInProgress = returnFiber; |
| 3174 | throw error; |
| 3175 | } else { |
| 3176 | panicOnRootError(root, thrownValue); |
| 3177 | return; |
| 3178 | } |
| 3179 | } |
| 3180 | |
| 3181 | if (unitOfWork.flags & Incomplete) { |
| 3182 | // Unwind the stack until we reach the nearest boundary. |
| 3183 | let skipSiblings; |
| 3184 | |
| 3185 | if ( |
| 3186 | // The current algorithm for both hydration and error handling assumes |
| 3187 | // that the tree is rendered sequentially. So we always skip the siblings. |
| 3188 | getIsHydrating() || |
| 3189 | suspendedReason === SuspendedOnError |
| 3190 | ) { |
| 3191 | skipSiblings = true; |
| 3192 | // We intentionally don't set workInProgressRootDidSkipSuspendedSiblings, |
| 3193 | // because we don't want to trigger another prerender attempt. |
| 3194 | } else if ( |
| 3195 | // Check whether this is a prerender |
| 3196 | !workInProgressRootIsPrerendering && |
no test coverage detected