@@ -581,6 +581,8 @@ function createModelResolver<T>(
581581 parentObject: Object,
582582 key: string,
583583 cyclic: boolean,
584+ response: Response,
585+ map: (response: Response, model: any) => T ,
584586) : ( value : any ) => void {
585587 let blocked ;
586588 if ( initializingChunkBlockedModel ) {
@@ -595,12 +597,12 @@ function createModelResolver<T>(
595597 } ;
596598 }
597599 return value => {
598- parentObject [ key ] = value ;
600+ parentObject [ key ] = map ( response , value ) ;
599601
600602 // If this is the root object for a model reference, where `blocked.value`
601603 // is a stale `null`, the resolved value can be used directly.
602604 if ( key === '' && blocked . value === null ) {
603- blocked . value = value ;
605+ blocked . value = parentObject [ key ] ;
604606 }
605607
606608 blocked.deps--;
@@ -651,24 +653,103 @@ function createServerReferenceProxy<A: Iterable<any>, T>(
651653 return proxy;
652654}
653655
654- function getOutlinedModel ( response : Response , id : number ) : any {
656+ function getOutlinedModel < T > (
657+ response: Response,
658+ id: number,
659+ parentObject: Object,
660+ key: string,
661+ map: (response: Response, model: any) => T ,
662+ ) : T {
655663 const chunk = getChunk ( response , id ) ;
656664 switch ( chunk . status ) {
657665 case RESOLVED_MODEL :
658666 initializeModelChunk ( chunk ) ;
659667 break ;
668+ case RESOLVED_MODULE :
669+ initializeModuleChunk ( chunk ) ;
670+ break ;
660671 }
661672 // The status might have changed after initialization.
662673 switch ( chunk . status ) {
663- case INITIALIZED : {
664- return chunk . value ;
665- }
666- // We always encode it first in the stream so it won't be pending.
674+ case INITIALIZED :
675+ const chunkValue = map ( response , chunk . value ) ;
676+ if ( __DEV__ && chunk . _debugInfo ) {
677+ // If we have a direct reference to an object that was rendered by a synchronous
678+ // server component, it might have some debug info about how it was rendered.
679+ // We forward this to the underlying object. This might be a React Element or
680+ // an Array fragment.
681+ // If this was a string / number return value we lose the debug info. We choose
682+ // that tradeoff to allow sync server components to return plain values and not
683+ // use them as React Nodes necessarily. We could otherwise wrap them in a Lazy.
684+ if (
685+ typeof chunkValue === 'object' &&
686+ chunkValue !== null &&
687+ ( Array . isArray ( chunkValue ) ||
688+ chunkValue . $$typeof === REACT_ELEMENT_TYPE ) &&
689+ ! chunkValue . _debugInfo
690+ ) {
691+ // We should maybe use a unique symbol for arrays but this is a React owned array.
692+ // $FlowFixMe[prop-missing]: This should be added to elements.
693+ Object . defineProperty ( ( chunkValue : any ) , '_debugInfo' , {
694+ configurable : false ,
695+ enumerable : false ,
696+ writable : true ,
697+ value : chunk . _debugInfo ,
698+ } ) ;
699+ }
700+ }
701+ return chunkValue ;
702+ case PENDING :
703+ case BLOCKED :
704+ case CYCLIC :
705+ const parentChunk = initializingChunk ;
706+ chunk . then (
707+ createModelResolver (
708+ parentChunk ,
709+ parentObject ,
710+ key ,
711+ chunk . status === CYCLIC ,
712+ response ,
713+ map ,
714+ ) ,
715+ createModelReject ( parentChunk ) ,
716+ ) ;
717+ return ( null : any ) ;
667718 default :
668719 throw chunk . reason ;
669720 }
670721}
671722
723+ function createMap(
724+ response: Response,
725+ model: Array< [ any , any ] > ,
726+ ): Map< any , any > {
727+ return new Map ( model ) ;
728+ }
729+
730+ function createSet(response: Response, model: Array< any > ): Set< any > {
731+ return new Set ( model ) ;
732+ }
733+
734+ function createBlob(response: Response, model: Array< any > ): Blob {
735+ return new Blob ( model . slice ( 1 ) , { type : model [ 0 ] } ) ;
736+ }
737+
738+ function createFormData(
739+ response: Response,
740+ model: Array< [ any , any ] > ,
741+ ): FormData {
742+ const formData = new FormData ( ) ;
743+ for ( let i = 0 ; i < model . length ; i ++ ) {
744+ formData . append ( model [ i ] [ 0 ] , model [ i ] [ 1 ] ) ;
745+ }
746+ return formData;
747+ }
748+
749+ function createModel ( response : Response , model : any ) : any {
750+ return model ;
751+ }
752+
672753function parseModelString(
673754 response: Response,
674755 parentObject: Object,
@@ -710,8 +791,13 @@ function parseModelString(
710791 case 'F' : {
711792 // Server Reference
712793 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
713- const metadata = getOutlinedModel ( response , id ) ;
714- return createServerReferenceProxy ( response , metadata ) ;
794+ return getOutlinedModel (
795+ response ,
796+ id ,
797+ parentObject ,
798+ key ,
799+ createServerReferenceProxy ,
800+ ) ;
715801 }
716802 case 'T' : {
717803 // Temporary Reference
@@ -728,33 +814,31 @@ function parseModelString(
728814 case 'Q ': {
729815 // Map
730816 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
731- const data = getOutlinedModel ( response , id ) ;
732- return new Map ( data ) ;
817+ return getOutlinedModel ( response , id , parentObject , key , createMap ) ;
733818 }
734819 case 'W' : {
735820 // Set
736821 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
737- const data = getOutlinedModel ( response , id ) ;
738- return new Set ( data ) ;
822+ return getOutlinedModel ( response , id , parentObject , key , createSet ) ;
739823 }
740824 case 'B ': {
741825 // Blob
742826 if ( enableBinaryFlight ) {
743827 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
744- const data = getOutlinedModel ( response , id ) ;
745- return new Blob ( data . slice ( 1 ) , { type : data [ 0 ] } ) ;
828+ return getOutlinedModel ( response , id , parentObject , key , createBlob ) ;
746829 }
747830 return undefined ;
748831 }
749832 case 'K ': {
750833 // FormData
751834 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
752- const data = getOutlinedModel ( response , id ) ;
753- const formData = new FormData ( ) ;
754- for ( let i = 0 ; i < data . length ; i ++ ) {
755- formData . append ( data [ i ] [ 0 ] , data [ i ] [ 1 ] ) ;
756- }
757- return formData ;
835+ return getOutlinedModel (
836+ response ,
837+ id ,
838+ parentObject ,
839+ key ,
840+ createFormData ,
841+ ) ;
758842 }
759843 case 'I ': {
760844 // $Infinity
@@ -803,62 +887,7 @@ function parseModelString(
803887 default : {
804888 // We assume that anything else is a reference ID.
805889 const id = parseInt ( value . slice ( 1 ) , 16 ) ;
806- const chunk = getChunk ( response , id ) ;
807- switch ( chunk . status ) {
808- case RESOLVED_MODEL :
809- initializeModelChunk ( chunk ) ;
810- break ;
811- case RESOLVED_MODULE :
812- initializeModuleChunk ( chunk ) ;
813- break ;
814- }
815- // The status might have changed after initialization.
816- switch ( chunk . status ) {
817- case INITIALIZED :
818- const chunkValue = chunk . value ;
819- if ( __DEV__ && chunk . _debugInfo ) {
820- // If we have a direct reference to an object that was rendered by a synchronous
821- // server component, it might have some debug info about how it was rendered.
822- // We forward this to the underlying object. This might be a React Element or
823- // an Array fragment.
824- // If this was a string / number return value we lose the debug info. We choose
825- // that tradeoff to allow sync server components to return plain values and not
826- // use them as React Nodes necessarily. We could otherwise wrap them in a Lazy.
827- if (
828- typeof chunkValue === 'object' &&
829- chunkValue !== null &&
830- ( Array . isArray ( chunkValue ) ||
831- chunkValue . $$typeof === REACT_ELEMENT_TYPE ) &&
832- ! chunkValue . _debugInfo
833- ) {
834- // We should maybe use a unique symbol for arrays but this is a React owned array.
835- // $FlowFixMe[prop-missing]: This should be added to elements.
836- Object . defineProperty ( chunkValue , '_debugInfo' , {
837- configurable : false ,
838- enumerable : false ,
839- writable : true ,
840- value : chunk . _debugInfo ,
841- } ) ;
842- }
843- }
844- return chunkValue ;
845- case PENDING :
846- case BLOCKED :
847- case CYCLIC :
848- const parentChunk = initializingChunk ;
849- chunk . then (
850- createModelResolver (
851- parentChunk ,
852- parentObject ,
853- key ,
854- chunk . status === CYCLIC ,
855- ) ,
856- createModelReject ( parentChunk ) ,
857- ) ;
858- return null ;
859- default :
860- throw chunk . reason ;
861- }
890+ return getOutlinedModel ( response , id , parentObject , key , createModel ) ;
862891 }
863892 }
864893 }
0 commit comments