( request: Request, task: Task, keyPath: KeyNode, rows: Array<ReactNodeList>, revealOrder: 'forwards' | 'backwards' | 'unstable_legacy-backwards', )
| 1909 | } |
| 1910 | |
| 1911 | function renderSuspenseListRows( |
| 1912 | request: Request, |
| 1913 | task: Task, |
| 1914 | keyPath: KeyNode, |
| 1915 | rows: Array<ReactNodeList>, |
| 1916 | revealOrder: 'forwards' | 'backwards' | 'unstable_legacy-backwards', |
| 1917 | ): void { |
| 1918 | // This is a fork of renderChildrenArray that's aware of tracking rows. |
| 1919 | const prevKeyPath = task.keyPath; |
| 1920 | const prevTreeContext = task.treeContext; |
| 1921 | const prevRow = task.row; |
| 1922 | const previousComponentStack = task.componentStack; |
| 1923 | let previousDebugTask = null; |
| 1924 | if (__DEV__) { |
| 1925 | previousDebugTask = task.debugTask; |
| 1926 | // We read debugInfo from task.node.props.children instead of rows because it |
| 1927 | // might have been an unwrapped iterable so we read from the original node. |
| 1928 | pushServerComponentStack(task, (task.node: any).props.children._debugInfo); |
| 1929 | } |
| 1930 | |
| 1931 | task.keyPath = keyPath; |
| 1932 | |
| 1933 | const totalChildren = rows.length; |
| 1934 | let previousSuspenseListRow: null | SuspenseListRow = null; |
| 1935 | if (task.replay !== null) { |
| 1936 | // Replay |
| 1937 | // First we need to check if we have any resume slots at this level. |
| 1938 | const resumeSlots = task.replay.slots; |
| 1939 | if (resumeSlots !== null && typeof resumeSlots === 'object') { |
| 1940 | for (let n = 0; n < totalChildren; n++) { |
| 1941 | // Since we are going to resume into a slot whose order was already |
| 1942 | // determined by the prerender, we can safely resume it even in reverse |
| 1943 | // render order. |
| 1944 | const i = |
| 1945 | revealOrder !== 'backwards' && |
| 1946 | revealOrder !== 'unstable_legacy-backwards' |
| 1947 | ? n |
| 1948 | : totalChildren - 1 - n; |
| 1949 | const node = rows[i]; |
| 1950 | task.row = previousSuspenseListRow = createSuspenseListRow( |
| 1951 | previousSuspenseListRow, |
| 1952 | ); |
| 1953 | task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i); |
| 1954 | const resumeSegmentID = resumeSlots[i]; |
| 1955 | // TODO: If this errors we should still continue with the next sibling. |
| 1956 | if (typeof resumeSegmentID === 'number') { |
| 1957 | resumeNode(request, task, resumeSegmentID, node, i); |
| 1958 | // We finished rendering this node, so now we can consume this |
| 1959 | // slot. This must happen after in case we rerender this task. |
| 1960 | delete resumeSlots[i]; |
| 1961 | } else { |
| 1962 | renderNode(request, task, node, i); |
| 1963 | } |
| 1964 | if (--previousSuspenseListRow.pendingTasks === 0) { |
| 1965 | finishSuspenseListRow(request, previousSuspenseListRow); |
| 1966 | } |
| 1967 | } |
| 1968 | } else { |
no test coverage detected