import type {ReactNodeList, Wakeable} from 'shared/ReactTypes';
import type {Fiber} from './ReactInternalTypes';
import type {SuspenseInstance} from './ReactFiberConfig';
import type {Lane} from './ReactFiberLane';
import type {TreeContext} from './ReactFiberTreeContext';
import {SuspenseComponent, SuspenseListComponent} from './ReactWorkTags';
import {NoFlags, DidCapture} from './ReactFiberFlags';
import {
isSuspenseInstancePending,
isSuspenseInstanceFallback,
} from './ReactFiberConfig';
export type SuspenseProps = {
children?: ReactNodeList,
fallback?: ReactNodeList,
suspenseCallback?: (Set<Wakeable> | null) => mixed,
unstable_avoidThisFallback?: boolean,
unstable_expectedLoadTime?: number,
unstable_name?: string,
};
export type SuspenseState = {
dehydrated: null | SuspenseInstance,
treeContext: null | TreeContext,
retryLane: Lane,
};
export type SuspenseListTailMode = 'collapsed' | 'hidden' | void;
export type SuspenseListRenderState = {
isBackwards: boolean,
rendering: null | Fiber,
renderingStartTime: number,
last: null | Fiber,
tail: null | Fiber,
tailMode: SuspenseListTailMode,
};
export type RetryQueue = Set<Wakeable>;
export function findFirstSuspended(row: Fiber): null | Fiber {
let node = row;
while (node !== null) {
if (node.tag === SuspenseComponent) {
const state: SuspenseState | null = node.memoizedState;
if (state !== null) {
const dehydrated: null | SuspenseInstance = state.dehydrated;
if (
dehydrated === null ||
isSuspenseInstancePending(dehydrated) ||
isSuspenseInstanceFallback(dehydrated)
) {
return node;
}
}
} else if (
node.tag === SuspenseListComponent &&
node.memoizedProps.revealOrder !== undefined
) {
const didSuspend = (node.flags & DidCapture) !== NoFlags;
if (didSuspend) {
return node;
}
} else if (node.child !== null) {
node.child.return = node;
node = node.child;
continue;
}
if (node === row) {
return null;
}
while (node.sibling === null) {
if (node.return === null || node.return === row) {
return null;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
}
return null;
}