From: Gabriel Ivăncescu gabrielopcode@gmail.com
So we can properly track state for synchronous XHRs.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/xmlhttprequest.c | 90 +++++++++++++++++------------------- 1 file changed, 42 insertions(+), 48 deletions(-)
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index dff54abb8e2..8a2dc281b77 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -128,7 +128,6 @@ typedef struct { nsIDOMEventListener nsIDOMEventListener_iface; LONG ref; HTMLXMLHttpRequest *xhr; - DWORD events_mask; } XMLHttpReqEventListener;
struct HTMLXMLHttpRequest { @@ -146,16 +145,14 @@ struct HTMLXMLHttpRequest { static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener) { nsIDOMEventTarget *event_target; - DWORD events_mask, i; - nsAString str; nsresult nsres; + nsAString str; + unsigned i;
nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target); assert(nsres == NS_OK);
- for(events_mask = event_listener->events_mask, i = 0; events_mask; events_mask >>= 1, i++) { - if(!(events_mask & 1)) - continue; + for(i = 0; i < ARRAY_SIZE(events) ; i++) { nsAString_InitDepend(&str, get_event_name(events[i])); nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE); nsAString_Finish(&str); @@ -164,7 +161,6 @@ static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
nsIDOMEventTarget_Release(event_target);
- event_listener->xhr->event_listener = NULL; event_listener->xhr = NULL; nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface); } @@ -298,8 +294,7 @@ static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface) TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) { - if(This->event_listener) - detach_xhr_event_listener(This->event_listener); + detach_xhr_event_listener(This->event_listener); release_event_target(&This->event_target); release_dispex(&This->event_target.dispex); nsIXMLHttpRequest_Release(This->nsxhr); @@ -1287,45 +1282,8 @@ static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex)
static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid) { - HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - nsIDOMEventTarget *nstarget; - nsAString type_str; - const WCHAR *name; - nsresult nsres; - unsigned i; - - TRACE("(%p)\n", This); - - for(i = 0; i < ARRAY_SIZE(events); i++) - if(eid == events[i]) - break; - if(i >= ARRAY_SIZE(events)) - return; - - if(!This->event_listener) { - This->event_listener = malloc(sizeof(*This->event_listener)); - if(!This->event_listener) - return; - - This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl; - This->event_listener->ref = 1; - This->event_listener->xhr = This; - This->event_listener->events_mask = 0; - } - - nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget); - assert(nsres == NS_OK); - - name = get_event_name(events[i]); - nsAString_InitDepend(&type_str, name); - nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2); - nsAString_Finish(&type_str); - if(NS_FAILED(nsres)) - ERR("AddEventListener(%s) failed: %08lx\n", debugstr_w(name), nsres); - - nsIDOMEventTarget_Release(nstarget); - - This->event_listener->events_mask |= 1 << i; + /* Do nothing. To be able to track state and queue events manually, when blocked + * by sync XHRs in their send() event loop, we always register the handlers. */ }
static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode) @@ -1471,6 +1429,10 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface); HTMLXMLHttpRequest *ret; nsIXMLHttpRequest *nsxhr; + nsIDOMEventTarget *nstarget; + XMLHttpReqEventListener *event_listener; + nsresult nsres; + unsigned i;
TRACE("(%p)->(%p)\n", This, p);
@@ -1483,6 +1445,14 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor nsIXMLHttpRequest_Release(nsxhr); return E_OUTOFMEMORY; } + + event_listener = malloc(sizeof(*event_listener)); + if(!event_listener) { + free(ret); + nsIXMLHttpRequest_Release(nsxhr); + return E_OUTOFMEMORY; + } + ret->nsxhr = nsxhr;
ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl; @@ -1493,6 +1463,30 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor &HTMLXMLHttpRequest_dispex, This->window->doc->document_mode); ret->ref = 1;
+ /* Always register the handlers because we need them to track state */ + event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl; + event_listener->ref = 1; + event_listener->xhr = ret; + ret->event_listener = event_listener; + + nsres = nsIXMLHttpRequest_QueryInterface(nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget); + assert(nsres == NS_OK); + + for(i = 0; i < ARRAY_SIZE(events); i++) { + const WCHAR *name = get_event_name(events[i]); + nsAString type_str; + + nsAString_InitDepend(&type_str, name); + nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2); + nsAString_Finish(&type_str); + if(NS_FAILED(nsres)) { + WARN("AddEventListener(%s) failed: %08lx\n", debugstr_w(name), nsres); + IHTMLXMLHttpRequest_Release(&ret->IHTMLXMLHttpRequest_iface); + return map_nsresult(nsres); + } + } + nsIDOMEventTarget_Release(nstarget); + *p = &ret->IHTMLXMLHttpRequest_iface; return S_OK; }