@@ -138,6 +138,13 @@ pub const XMLHttpRequest = struct {
138138 done = 4 ,
139139 };
140140
141+ // class attributes
142+ pub const _UNSENT = @intFromEnum (State .unsent );
143+ pub const _OPENED = @intFromEnum (State .opened );
144+ pub const _HEADERS_RECEIVED = @intFromEnum (State .headers_received );
145+ pub const _LOADING = @intFromEnum (State .loading );
146+ pub const _DONE = @intFromEnum (State .done );
147+
141148 // https://xhr.spec.whatwg.org/#response-type
142149 const ResponseType = enum {
143150 Empty ,
@@ -360,6 +367,8 @@ pub const XMLHttpRequest = struct {
360367 // We can we defer event destroy once the event is dispatched.
361368 defer parser .eventDestroy (evt );
362369
370+ try parser .eventSetInternalType (evt , .xhr_event );
371+
363372 try parser .eventInit (evt , typ , .{ .bubbles = true , .cancelable = true });
364373 _ = try parser .eventTargetDispatchEvent (@as (* parser .EventTarget , @ptrCast (self )), evt );
365374 }
@@ -579,11 +588,27 @@ pub const XMLHttpRequest = struct {
579588 }
580589
581590 fn onErr (self : * XMLHttpRequest , err : anyerror ) void {
582- self .state = .done ;
583591 self .send_flag = false ;
584- self .dispatchEvt ("readystatechange" );
585- self .dispatchProgressEvent ("error" , .{});
586- self .dispatchProgressEvent ("loadend" , .{});
592+
593+ // capture the state before we change it
594+ const s = self .state ;
595+
596+ const is_abort = err == DOMError .Abort ;
597+
598+ if (is_abort ) {
599+ self .state = .unsent ;
600+ } else {
601+ self .state = .done ;
602+ self .dispatchEvt ("error" );
603+ }
604+
605+ if (s != .done or s != .unsent ) {
606+ self .dispatchEvt ("readystatechange" );
607+ if (is_abort ) {
608+ self .dispatchProgressEvent ("abort" , .{});
609+ }
610+ self .dispatchProgressEvent ("loadend" , .{});
611+ }
587612
588613 const level : log.Level = if (err == DOMError .Abort ) .debug else .err ;
589614 log .log (.http , level , "error" , .{
@@ -922,4 +947,26 @@ test "Browser.XHR.XMLHttpRequest" {
922947 // So the url has been retrieved.
923948 .{ "status" , "200" },
924949 }, .{});
950+
951+ try runner .testCases (&.{
952+ .{ "const req6 = new XMLHttpRequest()" , null },
953+ .{
954+ \\ var readyStates = [];
955+ \\ var currentTarget = null;
956+ \\ req6.onreadystatechange = (e) => {
957+ \\ currentTarget = e.currentTarget;
958+ \\ readyStates.push(req6.readyState);
959+ \\ }
960+ ,
961+ null ,
962+ },
963+ .{ "req6.open('GET', 'https://127.0.0.1:9581/xhr')" , null },
964+ .{ "req6.send()" , null },
965+ .{ "readyStates.length" , "4" },
966+ .{ "readyStates[0] === XMLHttpRequest.OPENED" , "true" },
967+ .{ "readyStates[1] === XMLHttpRequest.HEADERS_RECEIVED" , "true" },
968+ .{ "readyStates[2] === XMLHttpRequest.LOADING" , "true" },
969+ .{ "readyStates[3] === XMLHttpRequest.DONE" , "true" },
970+ .{ "currentTarget == req6" , "true" },
971+ }, .{});
925972}
0 commit comments