@@ -84,16 +84,30 @@ class Fetch extends EE {
84
84
this . emit ( 'terminated' , reason )
85
85
}
86
86
87
- abort ( ) {
87
+ // https://fetch.spec.whatwg.org/#fetch-controller-abort
88
+ abort ( error ) {
88
89
if ( this . state !== 'ongoing' ) {
89
90
return
90
91
}
91
92
92
- const reason = new DOMException ( 'The operation was aborted.' , 'AbortError' )
93
-
93
+ // 1. Set controller’s state to "aborted".
94
94
this . state = 'aborted'
95
- this . connection ?. destroy ( reason )
96
- this . emit ( 'terminated' , reason )
95
+
96
+ // 2. Let fallbackError be an "AbortError" DOMException.
97
+ // 3. Set error to fallbackError if it is not given.
98
+ if ( ! error ) {
99
+ error = new DOMException ( 'The operation was aborted.' , 'AbortError' )
100
+ }
101
+
102
+ // 4. Let serializedError be StructuredSerialize(error).
103
+ // If that threw an exception, catch it, and let
104
+ // serializedError be StructuredSerialize(fallbackError).
105
+
106
+ // 5. Set controller’s serialized abort reason to serializedError.
107
+ this . serializedAbortReason = error
108
+
109
+ this . connection ?. destroy ( error )
110
+ this . emit ( 'terminated' , error )
97
111
}
98
112
}
99
113
@@ -125,8 +139,9 @@ async function fetch (input, init = {}) {
125
139
126
140
// 4. If requestObject’s signal’s aborted flag is set, then:
127
141
if ( requestObject . signal . aborted ) {
128
- // 1. Abort fetch with p, request, and null.
129
- abortFetch ( p , request , null )
142
+ // 1. Abort the fetch() call with p, request, null, and
143
+ // requestObject’s signal’s abort reason.
144
+ abortFetch ( p , request , null , requestObject . signal . reason )
130
145
131
146
// 2. Return p.
132
147
return p . promise
@@ -160,8 +175,9 @@ async function fetch (input, init = {}) {
160
175
// 1. Set locallyAborted to true.
161
176
locallyAborted = true
162
177
163
- // 2. Abort fetch with p, request, and responseObject.
164
- abortFetch ( p , request , responseObject )
178
+ // 2. Abort the fetch() call with p, request, responseObject,
179
+ // and requestObject’s signal’s abort reason.
180
+ abortFetch ( p , request , responseObject , requestObject . signal . reason )
165
181
166
182
// 3. If controller is not null, then abort controller.
167
183
if ( controller != null ) {
@@ -186,10 +202,16 @@ async function fetch (input, init = {}) {
186
202
return
187
203
}
188
204
189
- // 2. If response’s aborted flag is set, then abort fetch with p,
190
- // request, and responseObject, and terminate these substeps.
205
+ // 2. If response’s aborted flag is set, then:
191
206
if ( response . aborted ) {
192
- abortFetch ( p , request , responseObject )
207
+ // 1. Let deserializedError be the result of deserialize a serialized
208
+ // abort reason given controller’s serialized abort reason and
209
+ // relevantRealm.
210
+
211
+ // 2. Abort the fetch() call with p, request, responseObject, and
212
+ // deserializedError.
213
+
214
+ abortFetch ( p , request , responseObject , controller . serializedAbortReason )
193
215
return
194
216
}
195
217
@@ -297,14 +319,18 @@ function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis,
297
319
}
298
320
299
321
// https://fetch.spec.whatwg.org/#abort-fetch
300
- function abortFetch ( p , request , responseObject ) {
301
- // 1. Let error be an "AbortError" DOMException.
302
- const error = new DOMException ( 'The operation was aborted.' , 'AbortError' )
322
+ function abortFetch ( p , request , responseObject , error ) {
323
+ // Note: AbortSignal.reason was added in node v17.2.0
324
+ // which would give us an undefined error to reject with.
325
+ // Remove this once node v16 is no longer supported.
326
+ if ( ! error ) {
327
+ error = new DOMException ( 'The operation was aborted.' , 'AbortError' )
328
+ }
303
329
304
- // 2 . Reject promise with error.
330
+ // 1 . Reject promise with error.
305
331
p . reject ( error )
306
332
307
- // 3 . If request’s body is not null and is readable, then cancel request’s
333
+ // 2 . If request’s body is not null and is readable, then cancel request’s
308
334
// body with error.
309
335
if ( request . body != null && isReadable ( request . body ?. stream ) ) {
310
336
request . body . stream . cancel ( error ) . catch ( ( err ) => {
@@ -316,15 +342,15 @@ function abortFetch (p, request, responseObject) {
316
342
} )
317
343
}
318
344
319
- // 4 . If responseObject is null, then return.
345
+ // 3 . If responseObject is null, then return.
320
346
if ( responseObject == null ) {
321
347
return
322
348
}
323
349
324
- // 5 . Let response be responseObject’s response.
350
+ // 4 . Let response be responseObject’s response.
325
351
const response = responseObject [ kState ]
326
352
327
- // 6 . If response’s body is not null and is readable, then error response’s
353
+ // 5 . If response’s body is not null and is readable, then error response’s
328
354
// body with error.
329
355
if ( response . body != null && isReadable ( response . body ?. stream ) ) {
330
356
response . body . stream . cancel ( error ) . catch ( ( err ) => {
@@ -1720,9 +1746,9 @@ async function httpNetworkFetch (
1720
1746
}
1721
1747
1722
1748
// 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s
1723
- // controller.
1724
- const cancelAlgorithm = ( ) => {
1725
- fetchParams . controller . abort ( )
1749
+ // controller with reason, given reason .
1750
+ const cancelAlgorithm = ( reason ) => {
1751
+ fetchParams . controller . abort ( reason )
1726
1752
}
1727
1753
1728
1754
// 13. Let highWaterMark be a non-negative, non-NaN number, chosen by
@@ -1862,10 +1888,13 @@ async function httpNetworkFetch (
1862
1888
// 1. Set response’s aborted flag.
1863
1889
response . aborted = true
1864
1890
1865
- // 2. If stream is readable, error stream with an "AbortError" DOMException.
1891
+ // 2. If stream is readable, then error stream with the result of
1892
+ // deserialize a serialized abort reason given fetchParams’s
1893
+ // controller’s serialized abort reason and an
1894
+ // implementation-defined realm.
1866
1895
if ( isReadable ( stream ) ) {
1867
1896
fetchParams . controller . controller . error (
1868
- new DOMException ( 'The operation was aborted.' , 'AbortError' )
1897
+ fetchParams . controller . serializedAbortReason
1869
1898
)
1870
1899
}
1871
1900
} else {
0 commit comments