@@ -581,6 +581,8 @@ function createModelResolver<T>(
581
581
parentObject: Object,
582
582
key: string,
583
583
cyclic: boolean,
584
+ response: Response,
585
+ map: (response: Response, model: any) => T ,
584
586
) : ( value : any ) => void {
585
587
let blocked ;
586
588
if ( initializingChunkBlockedModel ) {
@@ -595,12 +597,12 @@ function createModelResolver<T>(
595
597
} ;
596
598
}
597
599
return value => {
598
- parentObject [ key ] = value ;
600
+ parentObject [ key ] = map ( response , value ) ;
599
601
600
602
// If this is the root object for a model reference, where `blocked.value`
601
603
// is a stale `null`, the resolved value can be used directly.
602
604
if ( key === '' && blocked . value === null ) {
603
- blocked . value = value ;
605
+ blocked . value = parentObject [ key ] ;
604
606
}
605
607
606
608
blocked.deps--;
@@ -651,24 +653,103 @@ function createServerReferenceProxy<A: Iterable<any>, T>(
651
653
return proxy;
652
654
}
653
655
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 {
655
663
const chunk = getChunk ( response , id ) ;
656
664
switch ( chunk . status ) {
657
665
case RESOLVED_MODEL :
658
666
initializeModelChunk ( chunk ) ;
659
667
break ;
668
+ case RESOLVED_MODULE :
669
+ initializeModuleChunk ( chunk ) ;
670
+ break ;
660
671
}
661
672
// The status might have changed after initialization.
662
673
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 ) ;
667
718
default :
668
719
throw chunk . reason ;
669
720
}
670
721
}
671
722
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
+
672
753
function parseModelString(
673
754
response: Response,
674
755
parentObject: Object,
@@ -710,8 +791,13 @@ function parseModelString(
710
791
case 'F' : {
711
792
// Server Reference
712
793
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
+ ) ;
715
801
}
716
802
case 'T' : {
717
803
// Temporary Reference
@@ -728,33 +814,31 @@ function parseModelString(
728
814
case 'Q ': {
729
815
// Map
730
816
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 ) ;
733
818
}
734
819
case 'W' : {
735
820
// Set
736
821
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 ) ;
739
823
}
740
824
case 'B ': {
741
825
// Blob
742
826
if ( enableBinaryFlight ) {
743
827
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 ) ;
746
829
}
747
830
return undefined ;
748
831
}
749
832
case 'K ': {
750
833
// FormData
751
834
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
+ ) ;
758
842
}
759
843
case 'I ': {
760
844
// $Infinity
@@ -803,62 +887,7 @@ function parseModelString(
803
887
default : {
804
888
// We assume that anything else is a reference ID.
805
889
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 ) ;
862
891
}
863
892
}
864
893
}
0 commit comments