@@ -102,6 +102,7 @@ function XMLHttpRequest(opts) {
102102 var sendFlag = false ;
103103 // Error flag, used when errors occur or abort is called
104104 var errorFlag = false ;
105+ var abortedFlag = false ;
105106
106107 // Event listeners
107108 var listeners = { } ;
@@ -172,10 +173,11 @@ function XMLHttpRequest(opts) {
172173 this . open = function ( method , url , async , user , password ) {
173174 this . abort ( ) ;
174175 errorFlag = false ;
176+ abortedFlag = false ;
175177
176178 // Check for valid request method
177179 if ( ! isAllowedHttpMethod ( method ) ) {
178- throw "SecurityError: Request method not allowed" ;
180+ throw new Error ( "SecurityError: Request method not allowed" ) ;
179181 }
180182
181183 settings = {
@@ -208,16 +210,14 @@ function XMLHttpRequest(opts) {
208210 */
209211 this . setRequestHeader = function ( header , value ) {
210212 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" ) ;
213214 }
214215 if ( ! isAllowedHttpHeader ( header ) ) {
215216 console . warn ( 'Refused to set unsafe header "' + header + '"' ) ;
216217 return false ;
217218 }
218219 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" ) ;
221221 }
222222 headers [ header ] = value ;
223223 return true ;
@@ -283,11 +283,11 @@ function XMLHttpRequest(opts) {
283283 */
284284 this . send = function ( data ) {
285285 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" ) ;
287287 }
288288
289289 if ( sendFlag ) {
290- throw "INVALID_STATE_ERR: send has already been called" ;
290+ throw new Error ( "INVALID_STATE_ERR: send has already been called" ) ;
291291 }
292292
293293 var ssl = false , local = false ;
@@ -312,13 +312,13 @@ function XMLHttpRequest(opts) {
312312 break ;
313313
314314 default :
315- throw "Protocol not supported." ;
315+ throw new Error ( "Protocol not supported." ) ;
316316 }
317317
318318 // Load files off the local filesystem (file://)
319319 if ( local ) {
320320 if ( settings . method !== "GET" ) {
321- throw "XMLHttpRequest: Only GET method is supported" ;
321+ throw new Error ( "XMLHttpRequest: Only GET method is supported" ) ;
322322 }
323323
324324 if ( settings . async ) {
@@ -402,7 +402,6 @@ function XMLHttpRequest(opts) {
402402
403403 // Reset error flag
404404 errorFlag = false ;
405-
406405 // Handle async requests
407406 if ( settings . async ) {
408407 // Use the proper protocol
@@ -545,7 +544,7 @@ function XMLHttpRequest(opts) {
545544 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 : / ) ) {
546545 // If the file returned an error, handle it
547546 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 ) ;
549548 } else {
550549 // If the file returned okay, parse its data and move to the DONE state
551550 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) {
557556
558557 /**
559558 * 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.
560560 */
561- this . handleError = function ( error ) {
562- this . status = 503 ;
561+ this . handleError = function ( error , status ) {
562+ this . status = + status || 0 ;
563563 this . statusText = error ;
564564 this . responseText = error . stack ;
565565 errorFlag = true ;
@@ -579,8 +579,7 @@ function XMLHttpRequest(opts) {
579579 this . responseText = "" ;
580580 this . responseXML = "" ;
581581
582- errorFlag = true ;
583-
582+ errorFlag = abortedFlag = true
584583 if ( this . readyState !== this . UNSENT
585584 && ( this . readyState !== this . OPENED || sendFlag )
586585 && this . readyState !== this . DONE ) {
@@ -619,11 +618,17 @@ function XMLHttpRequest(opts) {
619618 */
620619 this . dispatchEvent = function ( event ) {
621620 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 ] ( )
623625 }
624626 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 )
627632 }
628633 }
629634 } ;
@@ -634,18 +639,29 @@ function XMLHttpRequest(opts) {
634639 * @param int state New state
635640 */
636641 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
639644
640- if ( settings . async || self . readyState < self . OPENED || self . readyState === self . DONE ) {
641- self . dispatchEvent ( "readystatechange" ) ;
642- }
645+ self . readyState = state ;
643646
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" ) ;
649665 }
650666 } ;
651667} ;
0 commit comments