@@ -130,6 +130,7 @@ export function createBufferedTransformStream(): TransformStream<
130
130
try {
131
131
const chunk = new Uint8Array ( bufferByteLength )
132
132
let copiedBytes = 0
133
+
133
134
for ( let i = 0 ; i < bufferedChunks . length ; i ++ ) {
134
135
const bufferedChunk = bufferedChunks [ i ]
135
136
chunk . set ( bufferedChunk , copiedBytes )
@@ -376,31 +377,29 @@ function createMergedTransformStream(
376
377
} )
377
378
}
378
379
380
+ const CLOSE_TAG = '</body></html>'
381
+
379
382
/**
380
383
* This transform stream moves the suffix to the end of the stream, so results
381
384
* like `</body></html><script>...</script>` will be transformed to
382
385
* `<script>...</script></body></html>`.
383
386
*/
384
- function createMoveSuffixStream (
385
- suffix : string
386
- ) : TransformStream < Uint8Array , Uint8Array > {
387
+ function createMoveSuffixStream ( ) : TransformStream < Uint8Array , Uint8Array > {
387
388
let foundSuffix = false
388
389
389
- const encodedSuffix = encoder . encode ( suffix )
390
-
391
390
return new TransformStream ( {
392
391
transform ( chunk , controller ) {
393
392
if ( foundSuffix ) {
394
393
return controller . enqueue ( chunk )
395
394
}
396
395
397
- const index = indexOfUint8Array ( chunk , encodedSuffix )
396
+ const index = indexOfUint8Array ( chunk , ENCODED_TAGS . CLOSED . BODY_AND_HTML )
398
397
if ( index > - 1 ) {
399
398
foundSuffix = true
400
399
401
400
// If the whole chunk is the suffix, then don't write anything, it will
402
401
// be written in the flush.
403
- if ( chunk . length === suffix . length ) {
402
+ if ( chunk . length === ENCODED_TAGS . CLOSED . BODY_AND_HTML . length ) {
404
403
return
405
404
}
406
405
@@ -410,9 +409,11 @@ function createMoveSuffixStream(
410
409
411
410
// In the case where the suffix is in the middle of the chunk, we need
412
411
// to split the chunk into two parts.
413
- if ( chunk . length > suffix . length + index ) {
412
+ if ( chunk . length > ENCODED_TAGS . CLOSED . BODY_AND_HTML . length + index ) {
414
413
// Write out the part after the suffix.
415
- const after = chunk . slice ( index + suffix . length )
414
+ const after = chunk . slice (
415
+ index + ENCODED_TAGS . CLOSED . BODY_AND_HTML . length
416
+ )
416
417
controller . enqueue ( after )
417
418
}
418
419
} else {
@@ -422,7 +423,7 @@ function createMoveSuffixStream(
422
423
flush ( controller ) {
423
424
// Even if we didn't find the suffix, the HTML is not valid if we don't
424
425
// add it, so insert it at the end.
425
- controller . enqueue ( encodedSuffix )
426
+ controller . enqueue ( ENCODED_TAGS . CLOSED . BODY_AND_HTML )
426
427
} ,
427
428
} )
428
429
}
@@ -542,10 +543,8 @@ export async function continueFizzStream(
542
543
validateRootLayout,
543
544
} : ContinueStreamOptions
544
545
) : Promise < ReadableStream < Uint8Array > > {
545
- const closeTag = '</body></html>'
546
-
547
546
// Suffix itself might contain close tags at the end, so we need to split it.
548
- const suffixUnclosed = suffix ? suffix . split ( closeTag , 1 ) [ 0 ] : null
547
+ const suffixUnclosed = suffix ? suffix . split ( CLOSE_TAG , 1 ) [ 0 ] : null
549
548
550
549
// If we're generating static HTML and there's an `allReady` promise on the
551
550
// stream, we need to wait for it to resolve before continuing.
@@ -574,7 +573,7 @@ export async function continueFizzStream(
574
573
validateRootLayout ? createRootLayoutValidatorStream ( ) : null ,
575
574
576
575
// Close tags should always be deferred to the end
577
- createMoveSuffixStream ( closeTag ) ,
576
+ createMoveSuffixStream ( ) ,
578
577
579
578
// Special head insertions
580
579
// TODO-APP: Insert server side html to end of head in app layout rendering, to avoid
@@ -612,8 +611,6 @@ export async function continueStaticPrerender(
612
611
prerenderStream : ReadableStream < Uint8Array > ,
613
612
{ inlinedDataStream, getServerInsertedHTML } : ContinueStaticPrerenderOptions
614
613
) {
615
- const closeTag = '</body></html>'
616
-
617
614
return (
618
615
prerenderStream
619
616
// Buffer everything to avoid flushing too frequently
@@ -623,7 +620,7 @@ export async function continueStaticPrerender(
623
620
// Insert the inlined data (Flight data, form state, etc.) stream into the HTML
624
621
. pipeThrough ( createMergedTransformStream ( inlinedDataStream ) )
625
622
// Close tags should always be deferred to the end
626
- . pipeThrough ( createMoveSuffixStream ( closeTag ) )
623
+ . pipeThrough ( createMoveSuffixStream ( ) )
627
624
)
628
625
}
629
626
@@ -636,8 +633,6 @@ export async function continueDynamicHTMLResume(
636
633
renderStream : ReadableStream < Uint8Array > ,
637
634
{ inlinedDataStream, getServerInsertedHTML } : ContinueResumeOptions
638
635
) {
639
- const closeTag = '</body></html>'
640
-
641
636
return (
642
637
renderStream
643
638
// Buffer everything to avoid flushing too frequently
@@ -647,7 +642,7 @@ export async function continueDynamicHTMLResume(
647
642
// Insert the inlined data (Flight data, form state, etc.) stream into the HTML
648
643
. pipeThrough ( createMergedTransformStream ( inlinedDataStream ) )
649
644
// Close tags should always be deferred to the end
650
- . pipeThrough ( createMoveSuffixStream ( closeTag ) )
645
+ . pipeThrough ( createMoveSuffixStream ( ) )
651
646
)
652
647
}
653
648
@@ -659,13 +654,11 @@ export async function continueDynamicDataResume(
659
654
renderStream : ReadableStream < Uint8Array > ,
660
655
{ inlinedDataStream } : ContinueDynamicDataResumeOptions
661
656
) {
662
- const closeTag = '</body></html>'
663
-
664
657
return (
665
658
renderStream
666
659
// Insert the inlined data (Flight data, form state, etc.) stream into the HTML
667
660
. pipeThrough ( createMergedTransformStream ( inlinedDataStream ) )
668
661
// Close tags should always be deferred to the end
669
- . pipeThrough ( createMoveSuffixStream ( closeTag ) )
662
+ . pipeThrough ( createMoveSuffixStream ( ) )
670
663
)
671
664
}
0 commit comments