@@ -43,9 +43,11 @@ export async function callRouteAction({
43
43
singleFetch : boolean ;
44
44
} ) {
45
45
let result = await action ( {
46
- request : singleFetch
47
- ? stripRoutesParam ( stripIndexParam ( request ) )
48
- : stripDataParam ( stripIndexParam ( request ) ) ,
46
+ request : makeRequestSignalGcSafe (
47
+ singleFetch
48
+ ? stripRoutesParam ( stripIndexParam ( request ) )
49
+ : stripDataParam ( stripIndexParam ( request ) )
50
+ ) ,
49
51
context : loadContext ,
50
52
params,
51
53
} ) ;
@@ -81,9 +83,11 @@ export async function callRouteLoader({
81
83
singleFetch : boolean ;
82
84
} ) {
83
85
let result = await loader ( {
84
- request : singleFetch
85
- ? stripRoutesParam ( stripIndexParam ( request ) )
86
- : stripDataParam ( stripIndexParam ( request ) ) ,
86
+ request : makeRequestSignalGcSafe (
87
+ singleFetch
88
+ ? stripRoutesParam ( stripIndexParam ( request ) )
89
+ : stripDataParam ( stripIndexParam ( request ) )
90
+ ) ,
87
91
context : loadContext ,
88
92
params,
89
93
} ) ;
@@ -113,6 +117,15 @@ export async function callRouteLoader({
113
117
return isResponse ( result ) ? result : json ( result ) ;
114
118
}
115
119
120
+ function makeRequestSignalGcSafe ( request : Request ) {
121
+ // `undici` wraps the signal passed to the `Request` constructor. When the
122
+ // request object is garbage collected, the signal stops working. This is
123
+ // problematic when a loader or action is waiting for a signal to be aborted.
124
+ // To fix this, we hold a reference to the request in the signal.
125
+ Object . defineProperty ( request . signal , "__request" , request ) ;
126
+ return request ;
127
+ }
128
+
116
129
// TODO: Document these search params better
117
130
// and stop stripping these in V2. These break
118
131
// support for running in a SW and also expose
@@ -136,7 +149,7 @@ function stripIndexParam(request: Request) {
136
149
method : request . method ,
137
150
body : request . body ,
138
151
headers : request . headers ,
139
- signal : request . signal ,
152
+ signal : makeRequestSignalGcSafe ( request ) . signal ,
140
153
} ;
141
154
142
155
if ( init . body ) {
@@ -153,7 +166,7 @@ function stripDataParam(request: Request) {
153
166
method : request . method ,
154
167
body : request . body ,
155
168
headers : request . headers ,
156
- signal : request . signal ,
169
+ signal : makeRequestSignalGcSafe ( request ) . signal ,
157
170
} ;
158
171
159
172
if ( init . body ) {
@@ -170,7 +183,7 @@ function stripRoutesParam(request: Request) {
170
183
method : request . method ,
171
184
body : request . body ,
172
185
headers : request . headers ,
173
- signal : request . signal ,
186
+ signal : makeRequestSignalGcSafe ( request ) . signal ,
174
187
} ;
175
188
176
189
if ( init . body ) {
0 commit comments