Commit e5da8dbf authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

mshtml: Block load event until dynamically created script elements that are part…

mshtml: Block load event until dynamically created script elements that are part of the document are loaded. Signed-off-by: 's avatarJacek Caban <jacek@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 34dd3dd2
...@@ -154,6 +154,7 @@ HRESULT create_channelbsc(IMoniker*,const WCHAR*,BYTE*,DWORD,BOOL,nsChannelBSC** ...@@ -154,6 +154,7 @@ HRESULT create_channelbsc(IMoniker*,const WCHAR*,BYTE*,DWORD,BOOL,nsChannelBSC**
HRESULT channelbsc_load_stream(HTMLInnerWindow*,IMoniker*,IStream*) DECLSPEC_HIDDEN; HRESULT channelbsc_load_stream(HTMLInnerWindow*,IMoniker*,IStream*) DECLSPEC_HIDDEN;
void channelbsc_set_channel(nsChannelBSC*,nsChannel*,nsIStreamListener*,nsISupports*) DECLSPEC_HIDDEN; void channelbsc_set_channel(nsChannelBSC*,nsChannel*,nsIStreamListener*,nsISupports*) DECLSPEC_HIDDEN;
IUri *nsuri_get_uri(nsWineURI*) DECLSPEC_HIDDEN; IUri *nsuri_get_uri(nsWineURI*) DECLSPEC_HIDDEN;
nsresult create_onload_blocker_request(nsIRequest**) DECLSPEC_HIDDEN;
HRESULT read_stream(BSCallback*,IStream*,void*,DWORD,DWORD*) DECLSPEC_HIDDEN; HRESULT read_stream(BSCallback*,IStream*,void*,DWORD,DWORD*) DECLSPEC_HIDDEN;
......
...@@ -3980,3 +3980,21 @@ void release_nsio(void) ...@@ -3980,3 +3980,21 @@ void release_nsio(void)
nsio = NULL; nsio = NULL;
} }
} }
nsresult create_onload_blocker_request(nsIRequest **ret)
{
nsIChannel *channel;
nsACString spec;
nsresult nsres;
nsACString_InitDepend(&spec, "about:wine-script-onload-blocker");
nsres = nsIIOService_NewChannel(nsio, &spec, NULL, NULL, &channel);
nsACString_Finish(&spec);
if(NS_FAILED(nsres)) {
ERR("Failed to create channel: %08x\n", nsres);
return nsres;
}
*ret = (nsIRequest *)channel;
return NS_OK;
}
...@@ -822,6 +822,8 @@ typedef struct { ...@@ -822,6 +822,8 @@ typedef struct {
BSCallback bsc; BSCallback bsc;
HTMLScriptElement *script_elem; HTMLScriptElement *script_elem;
nsILoadGroup *load_group;
nsIRequest *request;
DWORD scheme; DWORD scheme;
DWORD size; DWORD size;
...@@ -945,6 +947,13 @@ static void ScriptBSC_destroy(BSCallback *bsc) ...@@ -945,6 +947,13 @@ static void ScriptBSC_destroy(BSCallback *bsc)
This->script_elem = NULL; This->script_elem = NULL;
} }
if(This->request) {
ERR("Unfinished request\n");
nsIRequest_Release(This->request);
}
if(This->load_group)
nsILoadGroup_Release(This->load_group);
heap_free(This->buf); heap_free(This->buf);
heap_free(This); heap_free(This);
} }
...@@ -957,9 +966,19 @@ static HRESULT ScriptBSC_init_bindinfo(BSCallback *bsc) ...@@ -957,9 +966,19 @@ static HRESULT ScriptBSC_init_bindinfo(BSCallback *bsc)
static HRESULT ScriptBSC_start_binding(BSCallback *bsc) static HRESULT ScriptBSC_start_binding(BSCallback *bsc)
{ {
ScriptBSC *This = impl_from_BSCallback(bsc); ScriptBSC *This = impl_from_BSCallback(bsc);
nsresult nsres;
This->script_elem->binding = &This->bsc; This->script_elem->binding = &This->bsc;
if(This->load_group) {
nsres = create_onload_blocker_request(&This->request);
if(NS_SUCCEEDED(nsres)) {
nsres = nsILoadGroup_AddRequest(This->load_group, This->request, NULL);
if(NS_FAILED(nsres))
ERR("AddRequest failed: %08x\n", nsres);
}
}
/* FIXME: We should find a better to decide if 'loading' state is supposed to be used by the protocol. */ /* FIXME: We should find a better to decide if 'loading' state is supposed to be used by the protocol. */
if(This->scheme == URL_SCHEME_HTTPS || This->scheme == URL_SCHEME_HTTP) if(This->scheme == URL_SCHEME_HTTPS || This->scheme == URL_SCHEME_HTTP)
set_script_elem_readystate(This->script_elem, READYSTATE_LOADING); set_script_elem_readystate(This->script_elem, READYSTATE_LOADING);
...@@ -970,6 +989,7 @@ static HRESULT ScriptBSC_start_binding(BSCallback *bsc) ...@@ -970,6 +989,7 @@ static HRESULT ScriptBSC_start_binding(BSCallback *bsc)
static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result) static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result)
{ {
ScriptBSC *This = impl_from_BSCallback(bsc); ScriptBSC *This = impl_from_BSCallback(bsc);
nsresult nsres;
if(SUCCEEDED(result) && !This->script_elem) if(SUCCEEDED(result) && !This->script_elem)
result = E_UNEXPECTED; result = E_UNEXPECTED;
...@@ -989,6 +1009,14 @@ static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result) ...@@ -989,6 +1009,14 @@ static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result)
This->size = 0; This->size = 0;
} }
if(This->request) {
nsres = nsILoadGroup_RemoveRequest(This->load_group, This->request, NULL, NS_OK);
if(NS_FAILED(nsres))
ERR("RemoveRequest failed: %08x\n", nsres);
nsIRequest_Release(This->request);
This->request = NULL;
}
IHTMLScriptElement_Release(&This->script_elem->IHTMLScriptElement_iface); IHTMLScriptElement_Release(&This->script_elem->IHTMLScriptElement_iface);
This->script_elem = NULL; This->script_elem = NULL;
return S_OK; return S_OK;
...@@ -1099,6 +1127,20 @@ HRESULT load_script(HTMLScriptElement *script_elem, const WCHAR *src, BOOL async ...@@ -1099,6 +1127,20 @@ HRESULT load_script(HTMLScriptElement *script_elem, const WCHAR *src, BOOL async
IHTMLScriptElement_AddRef(&script_elem->IHTMLScriptElement_iface); IHTMLScriptElement_AddRef(&script_elem->IHTMLScriptElement_iface);
bsc->script_elem = script_elem; bsc->script_elem = script_elem;
if(window->bscallback && window->bscallback->nschannel &&
window->bscallback->nschannel->load_group) {
cpp_bool contains;
nsresult nsres;
nsres = nsIDOMNode_Contains(script_elem->element.node.doc->node.nsnode,
script_elem->element.node.nsnode, &contains);
if(NS_SUCCEEDED(nsres) && contains) {
TRACE("script %p will block load event\n", script_elem);
bsc->load_group = window->bscallback->nschannel->load_group;
nsILoadGroup_AddRef(bsc->load_group);
}
}
hres = start_binding(window, &bsc->bsc, NULL); hres = start_binding(window, &bsc->bsc, NULL);
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface); IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
......
...@@ -90,3 +90,19 @@ async_test("append_script", function() { ...@@ -90,3 +90,19 @@ async_test("append_script", function() {
elem.src = "jsstream.php?simple"; elem.src = "jsstream.php?simple";
external.writeStream("simple", " "); external.writeStream("simple", " ");
}); });
function unexpected_load(e) {
ok(false, "onload event before executing script");
}
guard(function() {
var elem = document.createElement("script");
document.head.appendChild(elem);
elem.src = "jsstream.php?blockload";
window.addEventListener("load", unexpected_load, true);
setTimeout(guard(function() {
external.writeStream("blockload", "window.removeEventListener('load', unexpected_load, true);");
}), 100);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment