@@ -160,6 +160,61 @@ describe('ReactFlightDOMEdge', () => {
160160 } ) ;
161161 }
162162
163+ function dripStream ( input ) {
164+ const reader = input . getReader ( ) ;
165+ let nextDrop = 0 ;
166+ let controller = null ;
167+ let streamDone = false ;
168+ const buffer = [ ] ;
169+ function flush ( ) {
170+ if ( controller === null || nextDrop === 0 ) {
171+ return ;
172+ }
173+ while ( buffer . length > 0 && nextDrop > 0 ) {
174+ const nextChunk = buffer [ 0 ] ;
175+ if ( nextChunk . byteLength <= nextDrop ) {
176+ nextDrop -= nextChunk . byteLength ;
177+ controller . enqueue ( nextChunk ) ;
178+ buffer . shift ( ) ;
179+ if ( streamDone && buffer . length === 0 ) {
180+ controller . done ( ) ;
181+ }
182+ } else {
183+ controller . enqueue ( nextChunk . subarray ( 0 , nextDrop ) ) ;
184+ buffer [ 0 ] = nextChunk . subarray ( nextDrop ) ;
185+ nextDrop = 0 ;
186+ }
187+ }
188+ }
189+ const output = new ReadableStream ( {
190+ start ( c ) {
191+ controller = c ;
192+ async function pump ( ) {
193+ for ( ; ; ) {
194+ const { value, done} = await reader . read ( ) ;
195+ if ( done ) {
196+ streamDone = true ;
197+ break ;
198+ }
199+ buffer . push ( value ) ;
200+ flush ( ) ;
201+ }
202+ }
203+ pump ( ) ;
204+ } ,
205+ pull ( ) { } ,
206+ cancel ( reason ) {
207+ reader . cancel ( reason ) ;
208+ } ,
209+ } ) ;
210+ function drip ( n ) {
211+ nextDrop += n ;
212+ flush ( ) ;
213+ }
214+
215+ return [ output , drip ] ;
216+ }
217+
163218 async function readResult ( stream ) {
164219 const reader = stream . getReader ( ) ;
165220 let result = '' ;
@@ -576,6 +631,67 @@ describe('ReactFlightDOMEdge', () => {
576631 expect ( serializedContent . length ) . toBeLessThan ( 150 + expectedDebugInfoSize ) ;
577632 } ) ;
578633
634+ it ( 'should break up large sync components by outlining into streamable elements' , async ( ) => {
635+ const paragraphs = [ ] ;
636+ for ( let i = 0 ; i < 20 ; i ++ ) {
637+ const text =
638+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris' +
639+ 'porttitor tortor ac lectus faucibus, eget eleifend elit hendrerit.' +
640+ 'Integer porttitor nisi in leo congue rutrum. Morbi sed ante posuere,' +
641+ 'aliquam lorem ac, imperdiet orci. Duis malesuada gravida pharetra. Cras' +
642+ 'facilisis arcu diam, id dictum lorem imperdiet a. Suspendisse aliquet' +
643+ 'tempus tortor et ultricies. Aliquam libero velit, posuere tempus ante' +
644+ 'sed, pellentesque tincidunt lorem. Nullam iaculis, eros a varius' +
645+ 'aliquet, tortor felis tempor metus, nec cursus felis eros aliquam nulla.' +
646+ 'Vivamus ut orci sed mauris congue lacinia. Cras eget blandit neque.' +
647+ 'Pellentesque a massa in turpis ullamcorper volutpat vel at massa. Sed' +
648+ 'ante est, auctor non diam non, vulputate ultrices metus. Maecenas dictum' +
649+ 'fermentum quam id aliquam. Donec porta risus vitae pretium posuere.' +
650+ 'Fusce facilisis eros in lacus tincidunt congue.' +
651+ i ; /* trick dedupe */
652+ paragraphs . push ( < p key = { i } > { text } </ p > ) ;
653+ }
654+
655+ const stream = await serverAct ( ( ) =>
656+ ReactServerDOMServer . renderToReadableStream ( paragraphs ) ,
657+ ) ;
658+
659+ const [ stream2 , drip ] = dripStream ( stream ) ;
660+
661+ // Allow some of the content through.
662+ drip ( 5000 ) ;
663+
664+ const result = await ReactServerDOMClient . createFromReadableStream (
665+ stream2 ,
666+ {
667+ serverConsumerManifest : {
668+ moduleMap : null ,
669+ moduleLoading : null ,
670+ } ,
671+ } ,
672+ ) ;
673+
674+ // We should have resolved enough to be able to get the array even though some
675+ // of the items inside are still lazy.
676+ expect ( result . length ) . toBe ( 20 ) ;
677+
678+ // Unblock the rest
679+ drip ( Infinity ) ;
680+
681+ // Use the SSR render to resolve any lazy elements
682+ const ssrStream = await serverAct ( ( ) =>
683+ ReactDOMServer . renderToReadableStream ( result ) ,
684+ ) ;
685+ const html = await readResult ( ssrStream ) ;
686+
687+ const ssrStream2 = await serverAct ( ( ) =>
688+ ReactDOMServer . renderToReadableStream ( paragraphs ) ,
689+ ) ;
690+ const html2 = await readResult ( ssrStream2 ) ;
691+
692+ expect ( html ) . toBe ( html2 ) ;
693+ } ) ;
694+
579695 it ( 'should be able to serialize any kind of typed array' , async ( ) => {
580696 const buffer = new Uint8Array ( [
581697 123 , 4 , 10 , 5 , 100 , 255 , 244 , 45 , 56 , 67 , 43 , 124 , 67 , 89 , 100 , 20 ,
0 commit comments