diff --git a/dlls/mshtml/tests/xhr.js b/dlls/mshtml/tests/xhr.js
index 0edbc1529aa..2deb526cfe1 100644
--- a/dlls/mshtml/tests/xhr.js
+++ b/dlls/mshtml/tests/xhr.js
@@ -161,7 +161,6 @@ function test_sync_xhr() {
window.setTimeout(function() {
var r = a.join(",");
- todo_wine_if(document.documentMode < 10).
ok(r === "0,1,2,3," + (document.documentMode < 10 ? "sync_xhr(1),sync_xhr(2),sync_xhr(3)," : "") +
"sync_xhr(4)," + (document.documentMode < 10 ? "nested(1),nested(2),nested(3)," : "") +
"nested(4),4,async_xhr(3),async_xhr(4),sync_xhr_in_async,async_xhr2(3),async_xhr2(4)," +
diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c
index 2415ac8eb0f..6226461a502 100644
--- a/dlls/mshtml/tests/xmlhttprequest.c
+++ b/dlls/mshtml/tests/xmlhttprequest.c
@@ -712,11 +712,11 @@ static void test_sync_xhr(IHTMLDocument2 *doc, const WCHAR *xml_url, const WCHAR
loading_cnt = 0;
hres = IHTMLXMLHttpRequest_send(xhr, vempty);
ok(hres == S_OK, "send failed: %08lx\n", hres);
- todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
- todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received);
- todo_wine CHECK_CALLED(xmlhttprequest_onreadystatechange_loading);
+ CHECK_CALLED(xmlhttprequest_onreadystatechange_opened);
+ CHECK_CALLED(xmlhttprequest_onreadystatechange_headers_received);
+ CHECK_CALLED(xmlhttprequest_onreadystatechange_loading);
CHECK_CALLED(xmlhttprequest_onreadystatechange_done);
- todo_wine ok(loading_cnt == 1, "loading_cnt = %d\n", loading_cnt);
+ ok(loading_cnt == 1, "loading_cnt = %d\n", loading_cnt);
text = NULL;
hres = IHTMLXMLHttpRequest_getResponseHeader(xhr, content_type, &text);
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index dcd13bdfb57..17f29396b8f 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -380,6 +380,7 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
HTMLXMLHttpRequest *blocking_xhr = NULL;
thread_data_t *thread_data;
+ compat_mode_t compat_mode;
LONG ready_state;
DOMEvent *event;
HRESULT hres;
@@ -397,7 +398,8 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
if((thread_data = get_thread_data(FALSE)))
blocking_xhr = thread_data->blocking_xhr;
- hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&This->xhr->event_target.dispex), &event);
+ compat_mode = dispex_compat_mode(&This->xhr->event_target.dispex);
+ hres = create_event_from_nsevent(nsevent, compat_mode, &event);
if(FAILED(hres)) {
if(!blocking_xhr || This->xhr == blocking_xhr)
This->xhr->ready_state = ready_state;
@@ -459,6 +461,30 @@ static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *i
This->xhr->ready_state = ready_state;
return NS_OK;
}
+
+ /* IE10+ only send readystatechange event when it is DONE for sync XHRs, but older modes
+ send all the others here, including OPENED state change (even if it was opened earlier). */
+ if(compat_mode < COMPAT_MODE_IE10 && This->xhr->ready_state < READYSTATE_COMPLETE && (
+ event->event_id == EVENTID_READYSTATECHANGE || event->event_id == EVENTID_PROGRESS || event->event_id == EVENTID_LOADSTART)) {
+ DOMEvent *readystatechange_event;
+ DWORD magic = This->xhr->magic;
+ unsigned i;
+
+ for(i = READYSTATE_LOADING; i < READYSTATE_COMPLETE; i++) {
+ hres = create_document_event(This->xhr->window->doc, EVENTID_READYSTATECHANGE, &readystatechange_event);
+ if(FAILED(hres))
+ break;
+
+ This->xhr->ready_state = i;
+ dispatch_event(&This->xhr->event_target, readystatechange_event);
+ IDOMEvent_Release(&readystatechange_event->IDOMEvent_iface);
+
+ if(This->xhr->magic != magic) {
+ IDOMEvent_Release(&event->IDOMEvent_iface);
+ return NS_OK;
+ }
+ }
+ }
}
This->xhr->ready_state = ready_state;