5
5
*/
6
6
7
7
var Fetch = {
8
- xhrs : [ ] ,
8
+ // Map of integer fetch id to XHR request object
9
+ xhrs : { } ,
9
10
10
11
// The web worker that runs proxied file I/O requests. (this field is populated on demand, start as undefined to save code size)
11
12
// worker: undefined,
@@ -314,21 +315,22 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
314
315
xhr . setRequestHeader ( keyStr , valueStr ) ;
315
316
}
316
317
}
317
- Fetch . xhrs . push ( xhr ) ;
318
- var id = Fetch . xhrs . length ;
319
- HEAPU32 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . id } } } >> 2 ] = id ;
318
+ var id = HEAPU32 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . id } } } >> 2 ] ;
319
+ Fetch . xhrs [ id ] = xhr ;
320
320
var data = ( dataPtr && dataLength ) ? HEAPU8 . slice ( dataPtr , dataPtr + dataLength ) : null ;
321
321
// TODO: Support specifying custom headers to the request.
322
322
323
323
// Share the code to save the response, as we need to do so both on success
324
324
// and on error (despite an error, there may be a response, like a 404 page).
325
325
// This receives a condition, which determines whether to save the xhr's
326
326
// response, or just 0.
327
- function saveResponse ( condition ) {
327
+ function saveResponseAndStatus ( ) {
328
328
var ptr = 0 ;
329
329
var ptrLen = 0 ;
330
- if ( condition ) {
331
- ptrLen = xhr . response ? xhr . response . byteLength : 0 ;
330
+ if ( xhr . response && fetchAttrLoadToMemory && HEAPU32 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . data } } } >> 2 ] === 0 ) {
331
+ ptrLen = xhr . response . byteLength ;
332
+ }
333
+ if ( ptrLen > 0 ) {
332
334
#if FETCH_DEBUG
333
335
console . log ( 'fetch: allocating ' + ptrLen + ' bytes in Emscripten heap for xhr data' ) ;
334
336
#endif
@@ -339,12 +341,8 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
339
341
}
340
342
HEAPU32 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . data } } } >> 2 ] = ptr ;
341
343
Fetch . setu64 ( fetch + { { { C_STRUCTS . emscripten_fetch_t . numBytes } } } , ptrLen ) ;
342
- }
343
-
344
- xhr . onload = ( e ) => {
345
- saveResponse ( fetchAttrLoadToMemory && ! fetchAttrStreamData ) ;
346
- var len = xhr . response ? xhr . response . byteLength : 0 ;
347
344
Fetch . setu64 ( fetch + { { { C_STRUCTS . emscripten_fetch_t . dataOffset } } } , 0 ) ;
345
+ var len = xhr . response ? xhr . response . byteLength : 0 ;
348
346
if ( len ) {
349
347
// If the final XHR.onload handler receives the bytedata to compute total length, report that,
350
348
// otherwise don't write anything out here, which will retain the latest byte size reported in
@@ -354,9 +352,17 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
354
352
HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . readyState } } } >> 1 ] = xhr . readyState ;
355
353
HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . status } } } >> 1 ] = xhr . status ;
356
354
if ( xhr . statusText ) stringToUTF8 ( xhr . statusText , fetch + { { { C_STRUCTS . emscripten_fetch_t . statusText } } } , 64 ) ;
355
+ }
356
+
357
+ xhr . onload = ( e ) => {
358
+ // check if xhr was aborted by user and don't try to call back
359
+ if ( ! ( id in Fetch . xhrs ) ) {
360
+ return ;
361
+ }
362
+ saveResponseAndStatus ( ) ;
357
363
if ( xhr . status >= 200 && xhr . status < 300 ) {
358
364
#if FETCH_DEBUG
359
- console . log ( 'fetch: xhr of URL "' + xhr . url_ + '" / responseURL "' + xhr . responseURL + '" succeeded with status 200' ) ;
365
+ console . log ( 'fetch: xhr of URL "' + xhr . url_ + '" / responseURL "' + xhr . responseURL + '" succeeded with status ' + xhr . status ) ;
360
366
#endif
361
367
if ( onsuccess ) onsuccess ( fetch , xhr , e ) ;
362
368
} else {
@@ -367,27 +373,34 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
367
373
}
368
374
} ;
369
375
xhr . onerror = ( e ) => {
370
- saveResponse ( fetchAttrLoadToMemory ) ;
371
- var status = xhr . status ; // XXX TODO: Overwriting xhr.status doesn't work here, so don't override anywhere else either.
376
+ // check if xhr was aborted by user and don't try to call back
377
+ if ( ! ( id in Fetch . xhrs ) ) {
378
+ return ;
379
+ }
372
380
#if FETCH_DEBUG
373
- console . error ( 'fetch: xhr of URL "' + xhr . url_ + '" / responseURL "' + xhr . responseURL + '" finished with error, readyState ' + xhr . readyState + ' and status ' + status ) ;
381
+ console . error ( 'fetch: xhr of URL "' + xhr . url_ + '" / responseURL "' + xhr . responseURL + '" finished with error, readyState ' + xhr . readyState + ' and status ' + xhr . status ) ;
374
382
#endif
375
- Fetch . setu64 ( fetch + { { { C_STRUCTS . emscripten_fetch_t . dataOffset } } } , 0 ) ;
376
- Fetch . setu64 ( fetch + { { { C_STRUCTS . emscripten_fetch_t . totalBytes } } } , xhr . response ? xhr . response . byteLength : 0 ) ;
377
- HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . readyState } } } >> 1 ] = xhr . readyState ;
378
- HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . status } } } >> 1 ] = status ;
383
+ saveResponseAndStatus ( ) ;
379
384
if ( onerror ) onerror ( fetch , xhr , e ) ;
380
385
} ;
381
386
xhr . ontimeout = ( e ) => {
387
+ // check if xhr was aborted by user and don't try to call back
388
+ if ( ! ( id in Fetch . xhrs ) ) {
389
+ return ;
390
+ }
382
391
#if FETCH_DEBUG
383
392
console . error ( 'fetch: xhr of URL "' + xhr . url_ + '" / responseURL "' + xhr . responseURL + '" timed out, readyState ' + xhr . readyState + ' and status ' + xhr . status ) ;
384
393
#endif
385
394
if ( onerror ) onerror ( fetch , xhr , e ) ;
386
395
} ;
387
396
xhr . onprogress = ( e ) => {
397
+ // check if xhr was aborted by user and don't try to call back
398
+ if ( ! ( id in Fetch . xhrs ) ) {
399
+ return ;
400
+ }
388
401
var ptrLen = ( fetchAttrLoadToMemory && fetchAttrStreamData && xhr . response ) ? xhr . response . byteLength : 0 ;
389
402
var ptr = 0 ;
390
- if ( fetchAttrLoadToMemory && fetchAttrStreamData ) {
403
+ if ( ptrLen > 0 && fetchAttrLoadToMemory && fetchAttrStreamData ) {
391
404
#if FETCH_DEBUG
392
405
console . log ( 'fetch: allocating ' + ptrLen + ' bytes in Emscripten heap for xhr data' ) ;
393
406
#endif
@@ -413,6 +426,11 @@ function fetchXHR(fetch, onsuccess, onerror, onprogress, onreadystatechange) {
413
426
}
414
427
} ;
415
428
xhr . onreadystatechange = ( e ) => {
429
+ // check if xhr was aborted by user and don't try to call back
430
+ if ( ! ( id in Fetch . xhrs ) ) {
431
+ { { { runtimeKeepalivePop ( ) } } }
432
+ return ;
433
+ }
416
434
HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . readyState } } } >> 1 ] = xhr . readyState ;
417
435
if ( xhr . readyState >= 2 ) {
418
436
HEAPU16 [ fetch + { { { C_STRUCTS . emscripten_fetch_t . status } } } >> 1 ] = xhr . status ;
@@ -567,21 +585,27 @@ function startFetch(fetch, successcb, errorcb, progresscb, readystatechangecb) {
567
585
}
568
586
569
587
function fetchGetResponseHeadersLength ( id ) {
570
- return lengthBytesUTF8 ( Fetch . xhrs [ id - 1 ] . getAllResponseHeaders ( ) ) + 1 ;
588
+ return lengthBytesUTF8 ( Fetch . xhrs [ id ] . getAllResponseHeaders ( ) ) + 1 ;
571
589
}
572
590
573
591
function fetchGetResponseHeaders ( id , dst , dstSizeBytes ) {
574
- var responseHeaders = Fetch . xhrs [ id - 1 ] . getAllResponseHeaders ( ) ;
592
+ var responseHeaders = Fetch . xhrs [ id ] . getAllResponseHeaders ( ) ;
575
593
var lengthBytes = lengthBytesUTF8 ( responseHeaders ) + 1 ;
576
594
stringToUTF8 ( responseHeaders , dst , dstSizeBytes ) ;
577
595
return Math . min ( lengthBytes , dstSizeBytes ) ;
578
596
}
579
597
580
598
//Delete the xhr JS object, allowing it to be garbage collected.
581
599
function fetchFree ( id ) {
582
- //Note: should just be [id], but indexes off by 1 (see: #8803)
583
600
#if FETCH_DEBUG
584
- console . log ( "fetch: Deleting id:" + ( id - 1 ) + " of " + Fetch . xhrs ) ;
601
+ console . log ( "fetch: Deleting id:" + id + " of " + Fetch . xhrs ) ;
585
602
#endif
586
- delete Fetch . xhrs [ id - 1 ] ;
603
+ var xhr = Fetch . xhrs [ id ] ;
604
+ if ( xhr ) {
605
+ delete Fetch . xhrs [ id ] ;
606
+ // check if fetch is still in progress and should be aborted
607
+ if ( xhr . readyState > 0 && xhr . readyState < 4 ) {
608
+ xhr . abort ( ) ;
609
+ }
610
+ }
587
611
}
0 commit comments