(
returnFiber: Fiber,
currentFirstChild: Fiber | null,
newChild: any,
lanes: Lanes,
)
| 1944 | } |
| 1945 | |
| 1946 | function reconcileChildFibers( |
| 1947 | returnFiber: Fiber, |
| 1948 | currentFirstChild: Fiber | null, |
| 1949 | newChild: any, |
| 1950 | lanes: Lanes, |
| 1951 | ): Fiber | null { |
| 1952 | const prevDebugInfo = currentDebugInfo; |
| 1953 | currentDebugInfo = null; |
| 1954 | try { |
| 1955 | // This indirection only exists so we can reset `thenableState` at the end. |
| 1956 | // It should get inlined by Closure. |
| 1957 | thenableIndexCounter = 0; |
| 1958 | const firstChildFiber = reconcileChildFibersImpl( |
| 1959 | returnFiber, |
| 1960 | currentFirstChild, |
| 1961 | newChild, |
| 1962 | lanes, |
| 1963 | ); |
| 1964 | thenableState = null; |
| 1965 | // Don't bother to reset `thenableIndexCounter` to 0 because it always gets |
| 1966 | // set at the beginning. |
| 1967 | return firstChildFiber; |
| 1968 | } catch (x) { |
| 1969 | if ( |
| 1970 | x === SuspenseException || |
| 1971 | x === SuspenseActionException || |
| 1972 | (!disableLegacyMode && |
| 1973 | (returnFiber.mode & ConcurrentMode) === NoMode && |
| 1974 | typeof x === 'object' && |
| 1975 | x !== null && |
| 1976 | typeof x.then === 'function') |
| 1977 | ) { |
| 1978 | // Suspense exceptions need to read the current suspended state before |
| 1979 | // yielding and replay it using the same sequence so this trick doesn't |
| 1980 | // work here. |
| 1981 | // Suspending in legacy mode actually mounts so if we let the child |
| 1982 | // mount then we delete its state in an update. |
| 1983 | throw x; |
| 1984 | } |
| 1985 | // Something errored during reconciliation but it's conceptually a child that |
| 1986 | // errored and not the current component itself so we create a virtual child |
| 1987 | // that throws in its begin phase. That way the current component can handle |
| 1988 | // the error or suspending if needed. |
| 1989 | const throwFiber = createFiberFromThrow(x, returnFiber.mode, lanes); |
| 1990 | throwFiber.return = returnFiber; |
| 1991 | if (__DEV__) { |
| 1992 | const debugInfo = (throwFiber._debugInfo = currentDebugInfo); |
| 1993 | // Conceptually the error's owner should ideally be captured when the |
| 1994 | // Error constructor is called but we don't override them to capture our |
| 1995 | // `owner`. So instead, we use the nearest parent as the owner/task of the |
| 1996 | // error. This is usually the same thing when it's thrown from the same |
| 1997 | // async component but not if you await a promise started from a different |
| 1998 | // component/task. |
| 1999 | // In newer Chrome, Error constructor does capture the Task which is what |
| 2000 | // is logged by reportError. In that case this debugTask isn't used. |
| 2001 | throwFiber._debugOwner = returnFiber._debugOwner; |
| 2002 | throwFiber._debugTask = returnFiber._debugTask; |
| 2003 | if (debugInfo != null) { |
no test coverage detected