(root, returnFiber, sourceFiber, value, rootRenderLanes)
| 19025 | } |
| 19026 | |
| 19027 | function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) { |
| 19028 | // The source fiber did not complete. |
| 19029 | sourceFiber.flags |= Incomplete; |
| 19030 | |
| 19031 | { |
| 19032 | if (isDevToolsPresent) { |
| 19033 | // If we have pending work still, restore the original updaters |
| 19034 | restorePendingUpdaters(root, rootRenderLanes); |
| 19035 | } |
| 19036 | } |
| 19037 | |
| 19038 | if (value !== null && typeof value === 'object' && typeof value.then === 'function') { |
| 19039 | // This is a wakeable. The component suspended. |
| 19040 | var wakeable = value; |
| 19041 | resetSuspendedComponent(sourceFiber); |
| 19042 | |
| 19043 | { |
| 19044 | if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) { |
| 19045 | markDidThrowWhileHydratingDEV(); |
| 19046 | } |
| 19047 | } |
| 19048 | |
| 19049 | |
| 19050 | var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); |
| 19051 | |
| 19052 | if (suspenseBoundary !== null) { |
| 19053 | suspenseBoundary.flags &= ~ForceClientRender; |
| 19054 | markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // We only attach ping listeners in concurrent mode. Legacy Suspense always |
| 19055 | // commits fallbacks synchronously, so there are no pings. |
| 19056 | |
| 19057 | if (suspenseBoundary.mode & ConcurrentMode) { |
| 19058 | attachPingListener(root, wakeable, rootRenderLanes); |
| 19059 | } |
| 19060 | |
| 19061 | attachRetryListener(suspenseBoundary, root, wakeable); |
| 19062 | return; |
| 19063 | } else { |
| 19064 | // No boundary was found. Unless this is a sync update, this is OK. |
| 19065 | // We can suspend and wait for more data to arrive. |
| 19066 | if (!includesSyncLane(rootRenderLanes)) { |
| 19067 | // This is not a sync update. Suspend. Since we're not activating a |
| 19068 | // Suspense boundary, this will unwind all the way to the root without |
| 19069 | // performing a second pass to render a fallback. (This is arguably how |
| 19070 | // refresh transitions should work, too, since we're not going to commit |
| 19071 | // the fallbacks anyway.) |
| 19072 | // |
| 19073 | // This case also applies to initial hydration. |
| 19074 | attachPingListener(root, wakeable, rootRenderLanes); |
| 19075 | renderDidSuspendDelayIfPossible(); |
| 19076 | return; |
| 19077 | } // This is a sync/discrete update. We treat this case like an error |
| 19078 | // because discrete renders are expected to produce a complete tree |
| 19079 | // synchronously to maintain consistency with external state. |
| 19080 | |
| 19081 | |
| 19082 | var uncaughtSuspenseError = new Error('A component suspended while responding to synchronous input. This ' + 'will cause the UI to be replaced with a loading indicator. To ' + 'fix, updates that suspend should be wrapped ' + 'with startTransition.'); // If we're outside a transition, fall through to the regular error path. |
| 19083 | // The error will be caught by the nearest suspense boundary. |
| 19084 |
no test coverage detected
searching dependent graphs…