@@ -14,7 +14,7 @@ export default function handleRequest(
14
14
responseStatusCode : number ,
15
15
responseHeaders : Headers ,
16
16
routerContext : EntryContext ,
17
- loadContext : AppLoadContext ,
17
+ loadContext : AppLoadContext
18
18
// If you have middleware enabled:
19
19
// loadContext: unstable_RouterContextProvider
20
20
) {
@@ -29,24 +29,38 @@ export default function handleRequest(
29
29
? "onAllReady"
30
30
: "onShellReady" ;
31
31
32
+ // Abort the rendering stream after the `streamTimeout` so it has time to
33
+ // flush down the rejected boundaries
34
+ let timeoutId : ReturnType < typeof setTimeout > | undefined = setTimeout (
35
+ ( ) => abort ( ) ,
36
+ streamTimeout + 1000
37
+ ) ;
38
+
32
39
const { pipe, abort } = renderToPipeableStream (
33
40
< ServerRouter context = { routerContext } url = { request . url } /> ,
34
41
{
35
42
[ readyOption ] ( ) {
36
43
shellRendered = true ;
37
- const body = new PassThrough ( ) ;
44
+ const body = new PassThrough ( {
45
+ final ( callback ) {
46
+ // Clear the timeout to prevent retaining the closure and memory leak
47
+ clearTimeout ( timeoutId ) ;
48
+ timeoutId = undefined ;
49
+ callback ( ) ;
50
+ } ,
51
+ } ) ;
38
52
const stream = createReadableStreamFromReadable ( body ) ;
39
53
40
54
responseHeaders . set ( "Content-Type" , "text/html" ) ;
41
55
56
+ pipe ( body ) ;
57
+
42
58
resolve (
43
59
new Response ( stream , {
44
60
headers : responseHeaders ,
45
61
status : responseStatusCode ,
46
- } ) ,
62
+ } )
47
63
) ;
48
-
49
- pipe ( body ) ;
50
64
} ,
51
65
onShellError ( error : unknown ) {
52
66
reject ( error ) ;
@@ -60,11 +74,7 @@ export default function handleRequest(
60
74
console . error ( error ) ;
61
75
}
62
76
} ,
63
- } ,
77
+ }
64
78
) ;
65
-
66
- // Abort the rendering stream after the `streamTimeout` so it has time to
67
- // flush down the rejected boundaries
68
- setTimeout ( abort , streamTimeout + 1000 ) ;
69
79
} ) ;
70
80
}
0 commit comments