@@ -102,6 +102,7 @@ function XMLHttpRequest(opts) {
102
102
var sendFlag = false ;
103
103
// Error flag, used when errors occur or abort is called
104
104
var errorFlag = false ;
105
+ var abortedFlag = false ;
105
106
106
107
// Event listeners
107
108
var listeners = { } ;
@@ -172,10 +173,11 @@ function XMLHttpRequest(opts) {
172
173
this . open = function ( method , url , async , user , password ) {
173
174
this . abort ( ) ;
174
175
errorFlag = false ;
176
+ abortedFlag = false ;
175
177
176
178
// Check for valid request method
177
179
if ( ! isAllowedHttpMethod ( method ) ) {
178
- throw "SecurityError: Request method not allowed" ;
180
+ throw new Error ( "SecurityError: Request method not allowed" ) ;
179
181
}
180
182
181
183
settings = {
@@ -208,16 +210,14 @@ function XMLHttpRequest(opts) {
208
210
*/
209
211
this . setRequestHeader = function ( header , value ) {
210
212
if ( this . readyState != this . OPENED ) {
211
- throw "INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN" ;
212
- return false ;
213
+ throw new Error ( "INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN" ) ;
213
214
}
214
215
if ( ! isAllowedHttpHeader ( header ) ) {
215
216
console . warn ( 'Refused to set unsafe header "' + header + '"' ) ;
216
217
return false ;
217
218
}
218
219
if ( sendFlag ) {
219
- throw "INVALID_STATE_ERR: send flag is true" ;
220
- return false ;
220
+ throw new Error ( "INVALID_STATE_ERR: send flag is true" ) ;
221
221
}
222
222
headers [ header ] = value ;
223
223
return true ;
@@ -283,11 +283,11 @@ function XMLHttpRequest(opts) {
283
283
*/
284
284
this . send = function ( data ) {
285
285
if ( this . readyState != this . OPENED ) {
286
- throw "INVALID_STATE_ERR: connection must be opened before send() is called" ;
286
+ throw new Error ( "INVALID_STATE_ERR: connection must be opened before send() is called" ) ;
287
287
}
288
288
289
289
if ( sendFlag ) {
290
- throw "INVALID_STATE_ERR: send has already been called" ;
290
+ throw new Error ( "INVALID_STATE_ERR: send has already been called" ) ;
291
291
}
292
292
293
293
var ssl = false , local = false ;
@@ -312,13 +312,13 @@ function XMLHttpRequest(opts) {
312
312
break ;
313
313
314
314
default :
315
- throw "Protocol not supported." ;
315
+ throw new Error ( "Protocol not supported." ) ;
316
316
}
317
317
318
318
// Load files off the local filesystem (file://)
319
319
if ( local ) {
320
320
if ( settings . method !== "GET" ) {
321
- throw "XMLHttpRequest: Only GET method is supported" ;
321
+ throw new Error ( "XMLHttpRequest: Only GET method is supported" ) ;
322
322
}
323
323
324
324
if ( settings . async ) {
@@ -402,7 +402,6 @@ function XMLHttpRequest(opts) {
402
402
403
403
// Reset error flag
404
404
errorFlag = false ;
405
-
406
405
// Handle async requests
407
406
if ( settings . async ) {
408
407
// Use the proper protocol
@@ -545,7 +544,7 @@ function XMLHttpRequest(opts) {
545
544
if ( self . responseText . match ( / ^ N O D E - X M L H T T P R E Q U E S T - E R R O R : / ) ) {
546
545
// If the file returned an error, handle it
547
546
var errorObj = self . responseText . replace ( / ^ N O D E - X M L H T T P R E Q U E S T - E R R O R : / , "" ) ;
548
- self . handleError ( errorObj ) ;
547
+ self . handleError ( errorObj , 503 ) ;
549
548
} else {
550
549
// If the file returned okay, parse its data and move to the DONE state
551
550
self . status = self . responseText . replace ( / ^ N O D E - X M L H T T P R E Q U E S T - S T A T U S : ( [ 0 - 9 ] * ) , .* / , "$1" ) ;
@@ -557,9 +556,10 @@ function XMLHttpRequest(opts) {
557
556
558
557
/**
559
558
* Called when an error is encountered to deal with it.
559
+ * @param status {number} HTTP status code to use rather than the default (0) for XHR errors.
560
560
*/
561
- this . handleError = function ( error ) {
562
- this . status = 503 ;
561
+ this . handleError = function ( error , status ) {
562
+ this . status = + status || 0 ;
563
563
this . statusText = error ;
564
564
this . responseText = error . stack ;
565
565
errorFlag = true ;
@@ -579,8 +579,7 @@ function XMLHttpRequest(opts) {
579
579
this . responseText = "" ;
580
580
this . responseXML = "" ;
581
581
582
- errorFlag = true ;
583
-
582
+ errorFlag = abortedFlag = true
584
583
if ( this . readyState !== this . UNSENT
585
584
&& ( this . readyState !== this . OPENED || sendFlag )
586
585
&& this . readyState !== this . DONE ) {
@@ -619,11 +618,17 @@ function XMLHttpRequest(opts) {
619
618
*/
620
619
this . dispatchEvent = function ( event ) {
621
620
if ( typeof self [ "on" + event ] === "function" ) {
622
- self [ "on" + event ] ( ) ;
621
+ if ( this . readyState === this . DONE )
622
+ setImmediate ( function ( ) { self [ "on" + event ] ( ) } )
623
+ else
624
+ self [ "on" + event ] ( )
623
625
}
624
626
if ( event in listeners ) {
625
- for ( var i = 0 , len = listeners [ event ] . length ; i < len ; i ++ ) {
626
- listeners [ event ] [ i ] . call ( self ) ;
627
+ for ( let i = 0 , len = listeners [ event ] . length ; i < len ; i ++ ) {
628
+ if ( this . readyState === this . DONE )
629
+ setImmediate ( function ( ) { listeners [ event ] [ i ] . call ( self ) } )
630
+ else
631
+ listeners [ event ] [ i ] . call ( self )
627
632
}
628
633
}
629
634
} ;
@@ -634,18 +639,29 @@ function XMLHttpRequest(opts) {
634
639
* @param int state New state
635
640
*/
636
641
var setState = function ( state ) {
637
- if ( self . readyState !== state ) {
638
- self . readyState = state ;
642
+ if ( ( self . readyState === state ) || ( self . readyState === self . UNSENT && abortedFlag ) )
643
+ return
639
644
640
- if ( settings . async || self . readyState < self . OPENED || self . readyState === self . DONE ) {
641
- self . dispatchEvent ( "readystatechange" ) ;
642
- }
645
+ self . readyState = state ;
643
646
644
- if ( self . readyState === self . DONE && ! errorFlag ) {
645
- self . dispatchEvent ( "load" ) ;
646
- // @TODO figure out InspectorInstrumentation::didLoadXHR(cookie)
647
- self . dispatchEvent ( "loadend" ) ;
648
- }
647
+ if ( settings . async || self . readyState < self . OPENED || self . readyState === self . DONE ) {
648
+ self . dispatchEvent ( "readystatechange" ) ;
649
+ }
650
+
651
+ if ( self . readyState === self . DONE ) {
652
+ let fire
653
+
654
+ if ( abortedFlag )
655
+ fire = "abort"
656
+ else if ( errorFlag )
657
+ fire = "error"
658
+ else
659
+ fire = "load"
660
+
661
+ self . dispatchEvent ( fire )
662
+
663
+ // @TODO figure out InspectorInstrumentation::didLoadXHR(cookie)
664
+ self . dispatchEvent ( "loadend" ) ;
649
665
}
650
666
} ;
651
667
} ;
0 commit comments