mshtml: Block load event until dynamically created script elements that are part of the document are loaded.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
34dd3dd217
commit
e5da8dbfb7
|
@ -154,6 +154,7 @@ HRESULT create_channelbsc(IMoniker*,const WCHAR*,BYTE*,DWORD,BOOL,nsChannelBSC**
|
|||
HRESULT channelbsc_load_stream(HTMLInnerWindow*,IMoniker*,IStream*) DECLSPEC_HIDDEN;
|
||||
void channelbsc_set_channel(nsChannelBSC*,nsChannel*,nsIStreamListener*,nsISupports*) 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;
|
||||
|
||||
|
|
|
@ -3980,3 +3980,21 @@ void release_nsio(void)
|
|||
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 {
|
|||
BSCallback bsc;
|
||||
|
||||
HTMLScriptElement *script_elem;
|
||||
nsILoadGroup *load_group;
|
||||
nsIRequest *request;
|
||||
DWORD scheme;
|
||||
|
||||
DWORD size;
|
||||
|
@ -945,6 +947,13 @@ static void ScriptBSC_destroy(BSCallback *bsc)
|
|||
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);
|
||||
}
|
||||
|
@ -957,9 +966,19 @@ static HRESULT ScriptBSC_init_bindinfo(BSCallback *bsc)
|
|||
static HRESULT ScriptBSC_start_binding(BSCallback *bsc)
|
||||
{
|
||||
ScriptBSC *This = impl_from_BSCallback(bsc);
|
||||
nsresult nsres;
|
||||
|
||||
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. */
|
||||
if(This->scheme == URL_SCHEME_HTTPS || This->scheme == URL_SCHEME_HTTP)
|
||||
set_script_elem_readystate(This->script_elem, READYSTATE_LOADING);
|
||||
|
@ -970,6 +989,7 @@ static HRESULT ScriptBSC_start_binding(BSCallback *bsc)
|
|||
static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result)
|
||||
{
|
||||
ScriptBSC *This = impl_from_BSCallback(bsc);
|
||||
nsresult nsres;
|
||||
|
||||
if(SUCCEEDED(result) && !This->script_elem)
|
||||
result = E_UNEXPECTED;
|
||||
|
@ -989,6 +1009,14 @@ static HRESULT ScriptBSC_stop_binding(BSCallback *bsc, HRESULT result)
|
|||
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);
|
||||
This->script_elem = NULL;
|
||||
return S_OK;
|
||||
|
@ -1099,6 +1127,20 @@ HRESULT load_script(HTMLScriptElement *script_elem, const WCHAR *src, BOOL async
|
|||
IHTMLScriptElement_AddRef(&script_elem->IHTMLScriptElement_iface);
|
||||
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);
|
||||
|
||||
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
|
||||
|
|
|
@ -90,3 +90,19 @@ async_test("append_script", function() {
|
|||
elem.src = "jsstream.php?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);
|
||||
})();
|
||||
|
|
Loading…
Reference in New Issue