( request: Request, task: Task, children: $AsyncIterable<ReactClientValue, ReactClientValue, void>, getAsyncIterator: () => $AsyncIterator<any, any, any>, )
| 1916 | } |
| 1917 | |
| 1918 | function renderAsyncFragment( |
| 1919 | request: Request, |
| 1920 | task: Task, |
| 1921 | children: $AsyncIterable<ReactClientValue, ReactClientValue, void>, |
| 1922 | getAsyncIterator: () => $AsyncIterator<any, any, any>, |
| 1923 | ): ReactJSONValue { |
| 1924 | if (task.keyPath !== null) { |
| 1925 | // We have a Server Component that specifies a key but we're now splitting |
| 1926 | // the tree using a fragment. |
| 1927 | const fragment = __DEV__ |
| 1928 | ? [ |
| 1929 | REACT_ELEMENT_TYPE, |
| 1930 | REACT_FRAGMENT_TYPE, |
| 1931 | task.keyPath, |
| 1932 | {children}, |
| 1933 | null, |
| 1934 | null, |
| 1935 | 0, |
| 1936 | ] |
| 1937 | : [REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE, task.keyPath, {children}]; |
| 1938 | if (!task.implicitSlot) { |
| 1939 | // If this was keyed inside a set. I.e. the outer Server Component was keyed |
| 1940 | // then we need to handle reorders of the whole set. To do this we need to wrap |
| 1941 | // this array in a keyed Fragment. |
| 1942 | return fragment; |
| 1943 | } |
| 1944 | // If the outer Server Component was implicit but then an inner one had a key |
| 1945 | // we don't actually need to be able to move the whole set around. It'll always be |
| 1946 | // in an implicit slot. The key only exists to be able to reset the state of the |
| 1947 | // children. We could achieve the same effect by passing on the keyPath to the next |
| 1948 | // set of components inside the fragment. This would also allow a keyless fragment |
| 1949 | // reconcile against a single child. |
| 1950 | // Unfortunately because of JSON.stringify, we can't call the recursive loop for |
| 1951 | // each child within this context because we can't return a set with already resolved |
| 1952 | // values. E.g. a string would get double encoded. Returning would pop the context. |
| 1953 | // So instead, we wrap it with an unkeyed fragment and inner keyed fragment. |
| 1954 | return [fragment]; |
| 1955 | } |
| 1956 | |
| 1957 | // Since we're yielding here, that implicitly resets the keyPath context on the |
| 1958 | // way up. Which is what we want since we've consumed it. If this changes to |
| 1959 | // be recursive serialization, we need to reset the keyPath and implicitSlot, |
| 1960 | // before recursing here. |
| 1961 | const asyncIterator = getAsyncIterator.call(children); |
| 1962 | return serializeAsyncIterable(request, task, children, asyncIterator); |
| 1963 | } |
| 1964 | |
| 1965 | function renderClientElement( |
| 1966 | request: Request, |
no test coverage detected