@@ -1105,6 +1105,143 @@ function callWithDebugContextInDEV<A, T>(
11051105
11061106const  voidHandler  =  ( )  =>  { } ;
11071107
1108+ function processServerComponentReturnValue(
1109+   request: Request,
1110+   task: Task,
1111+   Component: any,
1112+   result: any,
1113+ ): any { 
1114+   // A Server Component's return value has a few special properties due to being 
1115+   // in the return position of a Component. We convert them here. 
1116+   if  ( 
1117+     typeof  result  !==  'object'  || 
1118+     result  ===  null  || 
1119+     isClientReference ( result ) 
1120+   ) { 
1121+     return  result ; 
1122+   } 
1123+ 
1124+   if (typeof result.then === 'function') { 
1125+     // When the return value is in children position we can resolve it immediately, 
1126+     // to its value without a wrapper if it's synchronously available. 
1127+     const  thenable : Thenable < any >  =  result ; 
1128+     if  ( __DEV__ )  { 
1129+       // If the thenable resolves to an element, then it was in a static position, 
1130+       // the return value of a Server Component. That doesn't need further validation 
1131+       // of keys. The Server Component itself would have had a key. 
1132+       thenable. then ( resolvedValue  =>  { 
1133+         if  ( 
1134+           typeof  resolvedValue  ===  'object'  && 
1135+           resolvedValue  !==  null  && 
1136+           resolvedValue . $$typeof  ===  REACT_ELEMENT_TYPE 
1137+         )  { 
1138+           resolvedValue . _store . validated  =  1 ; 
1139+         } 
1140+       } ,  voidHandler ) ; 
1141+     } 
1142+     if (thenable.status === 'fulfilled') { 
1143+       return  thenable . value ; 
1144+     } 
1145+     // TODO: Once we accept Promises as children on the client, we can just return
1146+     // the thenable here.
1147+     return createLazyWrapperAroundWakeable(result);
1148+   } 
1149+ 
1150+   if  ( __DEV__ )  { 
1151+     if  ( ( result : any ) . $$typeof  ===  REACT_ELEMENT_TYPE ) { 
1152+       // If the server component renders to an element, then it was in a static position. 
1153+       // That doesn't need further validation of keys. The Server Component itself would 
1154+       // have had a key. 
1155+       ( result : any ) . _store . validated  =  1 ; 
1156+     } 
1157+   } 
1158+ 
1159+   // Normally we'd serialize an Iterator/AsyncIterator as a single-shot which is not compatible 
1160+   // to be rendered as a React Child. However, because we have the function to recreate 
1161+   // an iterable from rendering the element again, we can effectively treat it as multi- 
1162+   // shot. Therefore we treat this as an Iterable/AsyncIterable, whether it was one or not, by 
1163+   // adding a wrapper so that this component effectively renders down to an AsyncIterable. 
1164+   const  iteratorFn  =  getIteratorFn ( result ) ; 
1165+   if  ( iteratorFn )  { 
1166+     const  iterableChild  =  result ; 
1167+     const  multiShot  =  { 
1168+       [ Symbol . iterator ] : function  ( )  { 
1169+         const  iterator  =  iteratorFn . call ( iterableChild ) ; 
1170+         if  ( __DEV__ )  { 
1171+           // If this was an Iterator but not a GeneratorFunction we warn because 
1172+           // it might have been a mistake. Technically you can make this mistake with 
1173+           // GeneratorFunctions and even single-shot Iterables too but it's extra 
1174+           // tempting to try to return the value from a generator. 
1175+           if  ( iterator  ===  iterableChild )  { 
1176+             const  isGeneratorComponent  = 
1177+               // $FlowIgnore[method-unbinding] 
1178+               Object . prototype . toString . call ( Component )  === 
1179+                 '[object GeneratorFunction]'  && 
1180+               // $FlowIgnore[method-unbinding] 
1181+               Object . prototype . toString . call ( iterableChild )  === 
1182+                 '[object Generator]' ; 
1183+             if  ( ! isGeneratorComponent )  { 
1184+               callWithDebugContextInDEV ( request ,  task ,  ( )  =>  { 
1185+                 console . error ( 
1186+                   'Returning an Iterator from a Server Component is not supported '  + 
1187+                     'since it cannot be looped over more than once. ' , 
1188+                 ) ; 
1189+               } ) ; 
1190+             } 
1191+           } 
1192+         } 
1193+         return  ( iterator : any ) ; 
1194+       } , 
1195+     } ; 
1196+     if  ( __DEV__ )  { 
1197+       ( multiShot : any ) . _debugInfo  =  iterableChild . _debugInfo ; 
1198+     } 
1199+     return multiShot;
1200+   } 
1201+   if  ( 
1202+     enableFlightReadableStream  && 
1203+     typeof  ( result : any ) [ ASYNC_ITERATOR ]  ===  'function ' && 
1204+     ( typeof  ReadableStream  !==  'function ' || 
1205+       ! ( result  instanceof  ReadableStream ) ) 
1206+   )  { 
1207+     const  iterableChild  =  result ; 
1208+     const  multishot  =  { 
1209+       [ ASYNC_ITERATOR ] : function  ( )  { 
1210+         const  iterator  =  ( iterableChild : any ) [ ASYNC_ITERATOR ] ( ) ; 
1211+         if  ( __DEV__ )  { 
1212+           // If this was an AsyncIterator but not an AsyncGeneratorFunction we warn because 
1213+           // it might have been a mistake. Technically you can make this mistake with 
1214+           // AsyncGeneratorFunctions and even single-shot AsyncIterables too but it's extra 
1215+           // tempting to try to return the value from a generator. 
1216+           if  ( iterator  ===  iterableChild )  { 
1217+             const  isGeneratorComponent  = 
1218+               // $FlowIgnore[method-unbinding] 
1219+               Object . prototype . toString . call ( Component )  === 
1220+                 '[object AsyncGeneratorFunction]'  && 
1221+               // $FlowIgnore[method-unbinding] 
1222+               Object . prototype . toString . call ( iterableChild )  === 
1223+                 '[object AsyncGenerator]' ; 
1224+             if  ( ! isGeneratorComponent )  { 
1225+               callWithDebugContextInDEV ( request ,  task ,  ( )  =>  { 
1226+                 console . error ( 
1227+                   'Returning an AsyncIterator from a Server Component is not supported '  + 
1228+                     'since it cannot be looped over more than once. ' , 
1229+                 ) ; 
1230+               } ) ; 
1231+             } 
1232+           } 
1233+         } 
1234+         return  iterator ; 
1235+       } , 
1236+     } ; 
1237+     if  ( __DEV__ )  { 
1238+       ( multishot : any ) . _debugInfo  =  iterableChild . _debugInfo ; 
1239+     } 
1240+     return multishot;
1241+   } 
1242+   return  result ; 
1243+ } 
1244+ 
11081245function  renderFunctionComponent < Props > (
11091246  request: Request,
11101247  task: Task,
@@ -1231,123 +1368,9 @@ function renderFunctionComponent<Props>(
12311368    throw null;
12321369  } 
12331370
1234-   if  ( 
1235-     typeof  result  ===  'object ' && 
1236-     result  !==  null  && 
1237-     ! isClientReference ( result ) 
1238-   )  { 
1239-     if  ( typeof  result . then  ===  'function' ) { 
1240-       // When the return value is in children position we can resolve it immediately, 
1241-       // to its value without a wrapper if it's synchronously available. 
1242-       const  thenable : Thenable < any >  =  result ; 
1243-       if  ( __DEV__ )  { 
1244-         // If the thenable resolves to an element, then it was in a static position, 
1245-         // the return value of a Server Component. That doesn't need further validation 
1246-         // of keys. The Server Component itself would have had a key. 
1247-         thenable. then ( resolvedValue  =>  { 
1248-           if  ( 
1249-             typeof  resolvedValue  ===  'object'  && 
1250-             resolvedValue  !==  null  && 
1251-             resolvedValue . $$typeof  ===  REACT_ELEMENT_TYPE 
1252-           )  { 
1253-             resolvedValue . _store . validated  =  1 ; 
1254-           } 
1255-         } ,  voidHandler ) ; 
1256-       } 
1257-       if (thenable.status === 'fulfilled') { 
1258-         return  thenable . value ; 
1259-       } 
1260-       // TODO: Once we accept Promises as children on the client, we can just return
1261-       // the thenable here.
1262-       result = createLazyWrapperAroundWakeable(result);
1263-     } 
1371+   // Apply special cases. 
1372+   result  =  processServerComponentReturnValue ( request ,  task ,  Component ,  result ) ; 
12641373
1265-     // Normally we'd serialize an Iterator/AsyncIterator as a single-shot which is not compatible 
1266-     // to be rendered as a React Child. However, because we have the function to recreate 
1267-     // an iterable from rendering the element again, we can effectively treat it as multi- 
1268-     // shot. Therefore we treat this as an Iterable/AsyncIterable, whether it was one or not, by 
1269-     // adding a wrapper so that this component effectively renders down to an AsyncIterable. 
1270-     const  iteratorFn  =  getIteratorFn ( result ) ; 
1271-     if  ( iteratorFn )  { 
1272-       const  iterableChild  =  result ; 
1273-       result  =  { 
1274-         [ Symbol . iterator ] : function  ( )  { 
1275-           const  iterator  =  iteratorFn . call ( iterableChild ) ; 
1276-           if  ( __DEV__ )  { 
1277-             // If this was an Iterator but not a GeneratorFunction we warn because 
1278-             // it might have been a mistake. Technically you can make this mistake with 
1279-             // GeneratorFunctions and even single-shot Iterables too but it's extra 
1280-             // tempting to try to return the value from a generator. 
1281-             if  ( iterator  ===  iterableChild )  { 
1282-               const  isGeneratorComponent  = 
1283-                 // $FlowIgnore[method-unbinding] 
1284-                 Object . prototype . toString . call ( Component )  === 
1285-                   '[object GeneratorFunction]'  && 
1286-                 // $FlowIgnore[method-unbinding] 
1287-                 Object . prototype . toString . call ( iterableChild )  === 
1288-                   '[object Generator]' ; 
1289-               if  ( ! isGeneratorComponent )  { 
1290-                 callWithDebugContextInDEV ( request ,  task ,  ( )  =>  { 
1291-                   console . error ( 
1292-                     'Returning an Iterator from a Server Component is not supported '  + 
1293-                       'since it cannot be looped over more than once. ' , 
1294-                   ) ; 
1295-                 } ) ; 
1296-               } 
1297-             } 
1298-           } 
1299-           return  ( iterator : any ) ; 
1300-         } , 
1301-       } ; 
1302-       if  ( __DEV__ )  { 
1303-         ( result : any ) . _debugInfo  =  iterableChild . _debugInfo ; 
1304-       } 
1305-     }  else  if  ( 
1306-       enableFlightReadableStream  && 
1307-       typeof  ( result : any ) [ ASYNC_ITERATOR ]  ===  'function ' && 
1308-       ( typeof  ReadableStream  !==  'function ' || 
1309-         ! ( result  instanceof  ReadableStream ) ) 
1310-     )  { 
1311-       const  iterableChild  =  result ; 
1312-       result  =  { 
1313-         [ ASYNC_ITERATOR ] : function  ( )  { 
1314-           const  iterator  =  ( iterableChild : any ) [ ASYNC_ITERATOR ] ( ) ; 
1315-           if  ( __DEV__ )  { 
1316-             // If this was an AsyncIterator but not an AsyncGeneratorFunction we warn because 
1317-             // it might have been a mistake. Technically you can make this mistake with 
1318-             // AsyncGeneratorFunctions and even single-shot AsyncIterables too but it's extra 
1319-             // tempting to try to return the value from a generator. 
1320-             if  ( iterator  ===  iterableChild )  { 
1321-               const  isGeneratorComponent  = 
1322-                 // $FlowIgnore[method-unbinding] 
1323-                 Object . prototype . toString . call ( Component )  === 
1324-                   '[object AsyncGeneratorFunction]'  && 
1325-                 // $FlowIgnore[method-unbinding] 
1326-                 Object . prototype . toString . call ( iterableChild )  === 
1327-                   '[object AsyncGenerator]' ; 
1328-               if  ( ! isGeneratorComponent )  { 
1329-                 callWithDebugContextInDEV ( request ,  task ,  ( )  =>  { 
1330-                   console . error ( 
1331-                     'Returning an AsyncIterator from a Server Component is not supported '  + 
1332-                       'since it cannot be looped over more than once. ' , 
1333-                   ) ; 
1334-                 } ) ; 
1335-               } 
1336-             } 
1337-           } 
1338-           return  iterator ; 
1339-         } , 
1340-       } ; 
1341-       if  ( __DEV__ )  { 
1342-         ( result : any ) . _debugInfo  =  iterableChild . _debugInfo ; 
1343-       } 
1344-     }  else  if  ( __DEV__  &&  ( result : any ) . $$typeof  ===  REACT_ELEMENT_TYPE )  { 
1345-       // If the server component renders to an element, then it was in a static position. 
1346-       // That doesn't need further validation of keys. The Server Component itself would 
1347-       // have had a key. 
1348-       ( result : any ) . _store . validated  =  1 ; 
1349-     } 
1350-   } 
13511374  // Track this element's key on the Server Component on the keyPath context.. 
13521375  const  prevKeyPath  =  task . keyPath ; 
13531376  const  prevImplicitSlot  =  task . implicitSlot ; 
0 commit comments