( root: FiberRoot, returnFiber: Fiber | null, sourceFiber: Fiber, value: mixed, rootRenderLanes: Lanes, )
| 360 | } |
| 361 | |
| 362 | function throwException( |
| 363 | root: FiberRoot, |
| 364 | returnFiber: Fiber | null, |
| 365 | sourceFiber: Fiber, |
| 366 | value: mixed, |
| 367 | rootRenderLanes: Lanes, |
| 368 | ): boolean { |
| 369 | // The source fiber did not complete. |
| 370 | sourceFiber.flags |= Incomplete; |
| 371 | |
| 372 | if (enableUpdaterTracking) { |
| 373 | if (isDevToolsPresent) { |
| 374 | // If we have pending work still, restore the original updaters |
| 375 | restorePendingUpdaters(root, rootRenderLanes); |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | if (value !== null && typeof value === 'object') { |
| 380 | if (enablePostpone && value.$$typeof === REACT_POSTPONE_TYPE) { |
| 381 | // Act as if this is an infinitely suspending promise. |
| 382 | value = {then: function () {}}; |
| 383 | } |
| 384 | if (typeof value.then === 'function') { |
| 385 | // This is a wakeable. The component suspended. |
| 386 | const wakeable: Wakeable = (value: any); |
| 387 | resetSuspendedComponent(sourceFiber, rootRenderLanes); |
| 388 | |
| 389 | if (__DEV__) { |
| 390 | if ( |
| 391 | getIsHydrating() && |
| 392 | (disableLegacyMode || sourceFiber.mode & ConcurrentMode) |
| 393 | ) { |
| 394 | markDidThrowWhileHydratingDEV(); |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | // Mark the nearest Suspense boundary to switch to rendering a fallback. |
| 399 | const suspenseBoundary = getSuspenseHandler(); |
| 400 | if (suspenseBoundary !== null) { |
| 401 | switch (suspenseBoundary.tag) { |
| 402 | case ActivityComponent: |
| 403 | case SuspenseComponent: { |
| 404 | // If this suspense/activity boundary is not already showing a fallback, mark |
| 405 | // the in-progress render as suspended. We try to perform this logic |
| 406 | // as soon as soon as possible during the render phase, so the work |
| 407 | // loop can know things like whether it's OK to switch to other tasks, |
| 408 | // or whether it can wait for data to resolve before continuing. |
| 409 | // TODO: Most of these checks are already performed when entering a |
| 410 | // Suspense boundary. We should track the information on the stack so |
| 411 | // we don't have to recompute it on demand. This would also allow us |
| 412 | // to unify with `use` which needs to perform this logic even sooner, |
| 413 | // before `throwException` is called. |
| 414 | if (disableLegacyMode || sourceFiber.mode & ConcurrentMode) { |
| 415 | if (getShellBoundary() === null) { |
| 416 | // Suspended in the "shell" of the app. This is an undesirable |
| 417 | // loading state. We should avoid committing this tree. |
| 418 | renderDidSuspendDelayIfPossible(); |
| 419 | } else { |
no test coverage detected