-- v4: mshtml: Return proper errors when navigating with no browser. mshtml: Set outer window to uninitialized page when document obj is released.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 2 +- dlls/mshtml/navigate.c | 5 +- dlls/mshtml/nsevents.c | 8 +- dlls/mshtml/oleobj.c | 71 ++++++++++++++++- dlls/mshtml/tests/events.c | 148 ++++++++++++++++++++++++++++++++++++ dlls/mshtml/tests/htmldoc.c | 36 ++++++++- dlls/mshtml/tests/script.c | 17 +++++ 7 files changed, 278 insertions(+), 9 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 2034ae8487a..388a8ddd1e8 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2906,7 +2906,7 @@ static HRESULT WINAPI HTMLPrivateWindow_GetAddressBarUrl(IHTMLPrivateWindow *ifa if(!url) return E_INVALIDARG;
- *url = SysAllocString(This->outer_window->url); + *url = SysAllocString(This->outer_window->url ? This->outer_window->url : L"about:blank"); return S_OK; }
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 8172abd8040..53f18bdc8d6 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1012,7 +1012,10 @@ static HRESULT on_start_nsrequest(nsChannelBSC *This)
if(This->bsc.binding) process_document_response_headers(This->bsc.window->doc, This->bsc.binding); - if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING) + + if(!(This->bsc.bindf & BINDF_ASYNCHRONOUS)) + This->bsc.window->doc->skip_mutation_notif = TRUE; + else if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING) set_ready_state(This->bsc.window->base.outer_window, READYSTATE_LOADING); }
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 78a54c83955..7bbddd33d2b 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -190,7 +190,7 @@ static nsresult handle_blur(HTMLDocumentNode *doc, nsIDOMEvent *event)
TRACE("(%p)\n", doc);
- if(!doc->doc_obj) + if(doc->skip_mutation_notif || !doc->doc_obj) return NS_ERROR_FAILURE; doc_obj = doc->doc_obj;
@@ -208,6 +208,8 @@ static nsresult handle_focus(HTMLDocumentNode *doc, nsIDOMEvent *event)
TRACE("(%p)\n", doc);
+ if(doc->skip_mutation_notif || !doc->doc_obj) + return NS_ERROR_FAILURE; doc_obj = doc->doc_obj;
if(!doc_obj->focus) { @@ -336,7 +338,7 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event)
if(!doc->outer_window) return NS_ERROR_FAILURE; - if(doc->doc_obj && doc->doc_obj->doc_node == doc) { + if(!doc->skip_mutation_notif && doc->doc_obj && doc->doc_obj->doc_node == doc) { doc_obj = doc->doc_obj; IUnknown_AddRef(doc_obj->outer_unk); } @@ -391,7 +393,7 @@ static nsresult handle_beforeunload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent) DOMEvent *event; HRESULT hres;
- if(!(window = doc->window)) + if(!(window = doc->window) || doc->unload_sent) return NS_OK;
/* Gecko dispatches this to the document, but IE dispatches it to the window */ diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index 870500ff0ab..d039fda064b 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -35,6 +35,7 @@
#include "mshtml_private.h" #include "htmlevent.h" +#include "binding.h"
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
@@ -3403,6 +3404,60 @@ static ULONG WINAPI HTMLDocumentObj_AddRef(IUnknown *iface) return ref; }
+static void set_window_uninitialized(HTMLOuterWindow *window) +{ + nsChannelBSC *channelbsc; + nsWineURI *nsuri; + IMoniker *mon; + HRESULT hres; + IUri *uri; + + window->readystate = READYSTATE_UNINITIALIZED; + set_current_uri(window, NULL); + if(window->mon) { + IMoniker_Release(window->mon); + window->mon = NULL; + } + + if(!window->base.inner_window) + return; + + hres = create_uri(L"about:blank", 0, &uri); + if(FAILED(hres)) + return; + + hres = create_doc_uri(uri, &nsuri); + IUri_Release(uri); + if(FAILED(hres)) + return; + + hres = CreateURLMoniker(NULL, L"about:blank", &mon); + if(SUCCEEDED(hres)) { + hres = create_channelbsc(mon, NULL, NULL, 0, TRUE, &channelbsc); + IMoniker_Release(mon); + + if(SUCCEEDED(hres)) { + channelbsc->bsc.bindf = 0; /* synchronous binding */ + + if(window->base.inner_window->doc) + remove_target_tasks(window->base.inner_window->task_magic); + abort_window_bindings(window->base.inner_window); + window->base.inner_window->doc->unload_sent = TRUE; + + hres = load_nsuri(window, nsuri, NULL, channelbsc, LOAD_FLAGS_BYPASS_CACHE); + if(SUCCEEDED(hres)) + hres = create_pending_window(window, channelbsc); + IBindStatusCallback_Release(&channelbsc->bsc.IBindStatusCallback_iface); + } + } + nsISupports_Release((nsISupports*)nsuri); + if(FAILED(hres)) + return; + + window->load_flags |= BINDING_REPLACE; + start_binding(window->pending_window, &window->pending_window->bscallback->bsc, NULL); +} + static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface) { HTMLDocumentObj *This = impl_from_IUnknown(iface); @@ -3412,8 +3467,20 @@ static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface)
if(!ref) { if(This->doc_node) { - This->doc_node->doc_obj = NULL; - IHTMLDOMNode_Release(&This->doc_node->node.IHTMLDOMNode_iface); + /* Protect against re-entry by grabbing it here */ + This->ref++; + set_window_uninitialized(This->window); + + if(This->doc_node) { + HTMLDocumentNode *doc_node = This->doc_node; + + This->doc_node = NULL; + doc_node->doc_obj = NULL; + IHTMLDOMNode_Release(&doc_node->node.IHTMLDOMNode_iface); + } + + /* Since we grabbed it, releasing it here will take care of freeing it */ + return HTMLDocumentObj_Release(&This->IUnknown_inner); } if(This->window) IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index f972c2a8316..56b62aa418c 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -5999,6 +5999,151 @@ static void test_empty_document(void) IHTMLDocument2_Release(doc); }
+static void test_document_close(void) +{ + IHTMLPrivateWindow *priv_window; + IHTMLDocument2 *doc, *doc_node; + IHTMLDocument3 *doc3; + IHTMLElement *elem; + DWORD cookie; + HRESULT hres; + VARIANT v; + BSTR bstr; + LONG ref; + MSG msg; + + doc = create_document_with_origin(input_doc_str); + if(!doc) + return; + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLPrivateWindow, (void**)&priv_window); + ok(hres == S_OK, "Could not get IHTMLPrivateWindow) interface: %08lx\n", hres); + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &bstr); + ok(hres == S_OK, "GetAddressBarUrl failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"http://winetest.example.org/"), "unexpected address bar: %s\n", wine_dbgstr_w(bstr)); + IHTMLPrivateWindow_Release(priv_window); + SysFreeString(bstr); + + elem = get_elem_id(doc_node, L"inputid"); + IHTMLElement_Release(elem); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLPrivateWindow, (void**)&priv_window); + ok(hres == S_OK, "Could not get IHTMLPrivateWindow) interface: %08lx\n", hres); + hres = IHTMLPrivateWindow_GetAddressBarUrl(priv_window, &bstr); + ok(hres == S_OK, "GetAddressBarUrl failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"about:blank"), "unexpected address bar: %s\n", wine_dbgstr_w(bstr)); + IHTMLPrivateWindow_Release(priv_window); + SysFreeString(bstr); + + bstr = SysAllocString(L"inputid"); + doc3 = get_doc3_iface((IUnknown*)doc); + hres = IHTMLDocument3_getElementById(doc3, bstr, &elem); + ok(hres == S_OK, "getElementById returned: %08lx\n", hres); + ok(elem == NULL, "elem != NULL\n"); + IHTMLDocument3_Release(doc3); + SysFreeString(bstr); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + window = NULL; + + doc = create_document(); + if(!doc) + return; + set_client_site(doc, TRUE); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + window = NULL; + + doc = create_document(); + if(!doc) + return; + set_client_site(doc, TRUE); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + doc_load_string(doc, empty_doc_ie9_str); + cookie = register_cp((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + while(!doc_complete && GetMessageA(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + unregister_cp((IUnknown*)doc, &IID_IPropertyNotifySink, cookie); + document_mode = 9; + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&onunload_obj; + hres = IHTMLWindow2_put_onunload(window, v); + ok(hres == S_OK, "put_onunload failed: %08lx\n", hres); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)&onbeforeunload_obj; + hres = IHTMLWindow2_put_onbeforeunload(window, v); + ok(hres == S_OK, "put_onbeforeunload failed: %08lx\n", hres); + + IOleDocumentView_Release(view); + view = NULL; + + ref = IHTMLDocument2_Release(doc); + ok(ref == 0, "ref = %ld\n", ref); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + + V_VT(&v) = VT_EMPTY; + IHTMLWindow2_put_onunload(window, v); + IHTMLWindow2_put_onbeforeunload(window, v); + IHTMLWindow2_Release(window); + window = NULL; +} + static void test_storage_events(const char *doc_str) { static struct { @@ -6372,6 +6517,9 @@ START_TEST(events) test_sync_xhr_events(empty_doc_ie9_str); }
+ /* Test this last since it doesn't close the view properly. */ + test_document_close(); + DestroyWindow(container_hwnd); }else { #if !defined(__i386__) && !defined(__x86_64__) diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index 9874540e973..4db4777dca4 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -8461,10 +8461,12 @@ static void test_doc_domain(IHTMLDocument2 *doc)
static void test_HTMLDocument_http(BOOL with_wbapp) { + IHTMLDocument2 *doc, *doc_node; + IHTMLWindow2 *window; IMoniker *http_mon; - IHTMLDocument2 *doc; - ULONG ref; HRESULT hres; + ULONG ref; + BSTR bstr;
trace("Testing HTMLDocument (http%s)...\n", with_wbapp ? " with IWebBrowserApp" : "");
@@ -8529,12 +8531,42 @@ static void test_HTMLDocument_http(BOOL with_wbapp) test_IsDirty(doc, S_FALSE); test_GetCurMoniker((IUnknown*)doc, NULL, prev_url, support_wbapp);
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + todo_wine_if(support_wbapp) + ok(!wcscmp(bstr, support_wbapp ? L"interactive" : L"complete"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + if(view) IOleDocumentView_Release(view); view = NULL;
release_document(doc);
+ hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + hres = IHTMLDocument2_get_readyState(doc_node, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); + ok(!wcscmp(bstr, L"uninitialized"), "readyState = %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); + ref = IMoniker_Release(http_mon); ok(!ref, "ref=%ld, expected 0\n", ref); } diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index dc5dac98ee7..de1fd056169 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -4525,7 +4525,10 @@ static void test_exec_script(IHTMLDocument2 *doc, const WCHAR *codew, const WCHA
static void test_simple_script(void) { + IHTMLDocument2 *doc_node; + IHTMLWindow2 *window; IHTMLDocument2 *doc; + HRESULT hres;
doc = create_document(); if(!doc) @@ -4596,6 +4599,12 @@ static void test_simple_script(void) if(window_dispex) IDispatchEx_Release(window_dispex);
+ hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_get_document(window, &doc_node); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + SET_EXPECT(SetScriptState_DISCONNECTED); SET_EXPECT(Close); SET_EXPECT(Close2); @@ -4605,6 +4614,14 @@ static void test_simple_script(void) CHECK_CALLED(SetScriptState_DISCONNECTED); CHECK_CALLED(Close); CHECK_CALLED(Close2); + + hres = IHTMLWindow2_get_document(window, &doc); + ok(hres == S_OK, "get_document failed: %08lx\n", hres); + ok(doc != doc_node, "doc == doc_node\n"); + + IHTMLDocument2_Release(doc_node); + IHTMLDocument2_Release(doc); + IHTMLWindow2_Release(window); }
static void run_from_moniker(IMoniker *mon)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 2 +- dlls/mshtml/navigate.c | 3 +++ dlls/mshtml/tests/events.c | 21 ++++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 388a8ddd1e8..7bc2507619b 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -2832,7 +2832,7 @@ static HRESULT WINAPI HTMLPrivateWindow_SuperNavigate(IHTMLPrivateWindow *iface, FIXME("unimplemented flags %lx\n", flags & ~2);
if(!window || !window->browser) - return E_UNEXPECTED; + return E_FAIL;
if(window->browser->doc->hostui) { hres = IDocHostUIHandler_TranslateUrl(window->browser->doc->hostui, 0, url, &translated_url); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 53f18bdc8d6..9bc0c0db7d7 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -2681,6 +2681,9 @@ HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_u BSTR display_uri; HRESULT hres;
+ if(!window->browser) + return E_UNEXPECTED; + if(new_url && base_uri) hres = CoInternetCombineUrlEx(base_uri, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO, &nav_uri, 0); diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 56b62aa418c..5b917652ce9 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -6003,12 +6003,13 @@ static void test_document_close(void) { IHTMLPrivateWindow *priv_window; IHTMLDocument2 *doc, *doc_node; + IHTMLLocation *location; IHTMLDocument3 *doc3; IHTMLElement *elem; DWORD cookie; + BSTR bstr, bstr2; HRESULT hres; VARIANT v; - BSTR bstr; LONG ref; MSG msg;
@@ -6091,6 +6092,24 @@ static void test_document_close(void)
IHTMLDocument2_Release(doc_node); IHTMLDocument2_Release(doc); + + bstr = SysAllocString(L"about:blank"); + hres = IHTMLWindow2_get_location(window, &location); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + hres = IHTMLLocation_put_href(location, bstr); + ok(hres == E_UNEXPECTED, "put_href returned: %08lx\n", hres); + IHTMLLocation_Release(location); + + V_VT(&v) = VT_EMPTY; + bstr2 = SysAllocString(L""); + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLPrivateWindow, (void**)&priv_window); + ok(hres == S_OK, "Could not get IHTMLPrivateWindow) interface: %08lx\n", hres); + hres = IHTMLPrivateWindow_SuperNavigate(priv_window, bstr, bstr2, NULL, NULL, &v, &v, 0); + ok(hres == E_FAIL, "SuperNavigate returned: %08lx\n", hres); + IHTMLPrivateWindow_Release(priv_window); + SysFreeString(bstr2); + SysFreeString(bstr); + IHTMLWindow2_Release(window); window = NULL;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=138775
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w7u_adm (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w7u_el (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w8 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w8adm (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w864 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064v1809 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064_tsign (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64_en_AE_u8 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w11pro64 (32 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w7pro64 (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w864 (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064v1809 (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064_2qxl (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064_adm (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w1064_tsign (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64 (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64_ar (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64_ja (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w10pro64_zh_CN (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
=== w11pro64_amd (64 bit report) ===
mshtml: events.c:6100: Test failed: put_href returned: 80004004
I've fixed the `beforeunload` case, since it happens during `load_nsuri`. I added tests for both it and `unload`, but unfortunately the new tests are somewhat hackish, as we have to release the View without actually closing it to test this, because closing the view sends those events (this is already tested by existing tests), and we want to test if releasing the doc obj sends those events. As for why we have to release the View, it's because it holds a ref to the doc obj.
So I placed the test last now since it doesn't close the view properly. If you think the test is too hackish I can remove it.
Jacek Caban (@jacek) commented about dlls/mshtml/oleobj.c:
if(!ref) { if(This->doc_node) {
This->doc_node->doc_obj = NULL;
IHTMLDOMNode_Release(&This->doc_node->node.IHTMLDOMNode_iface);
/* Protect against re-entry by grabbing it here */
This->ref++;
Please avoid it. You may just fully detach document object early, before releasing and uninitializing window and document node to be sure that we don't reenter the destructor. It could also simplify handling of skipping mutation events.
To be honest I'm not thrilled with the idea of doing full load like that. I was hoping for something "lighter". Sadly, I don't see a good alternative to do that in Gecko in a way fully compatible with MSHTML. I'm not sure how much we really care about this thing being exactly compatible, but if we do, I guess we need something like that...
FWIW, one alternative would be to do `document.open(); document.close();`. It would work only on HTML documents (no SVG/XML equivalent) and it replaces a document instead of creating a new one, so it's not really a good fit.
BTW, it 's hard to judge without seeing the code, but find it surprising that this thing matters for MessageEvent.source.
On Fri Oct 20 16:29:39 2023 +0000, Jacek Caban wrote:
To be honest I'm not thrilled with the idea of doing full load like that. I was hoping for something "lighter". Sadly, I don't see a good alternative to do that in Gecko in a way fully compatible with MSHTML. I'm not sure how much we really care about this thing being exactly compatible, but if we do, I guess we need something like that... FWIW, one alternative would be to do `document.open(); document.close();`. It would work only on HTML documents (no SVG/XML equivalent) and it replaces a document instead of creating a new one, so it's not really a good fit. BTW, it 's hard to judge without seeing the code, but find it surprising that this thing matters for MessageEvent.source.
Yeah I tried a bunch of things and arrived to this one. I agree something lighter would be nicer, but I'm not sure if it's that bad since it happens on the document obj release (which is typically not that often, since it's the "root"), and we're already doing some other potential heavy things here, such as forcing a cycle collection. I haven't tested but this *might* also help with the gecko nsevents that hold refs (unsure if they're processed in sync bindings, I see it does have a "hidden" message loop in urlmon) since it's navigating away, so at least Gecko is "aware" of it.
Also what I meant is that at least I found it useful to test some behaviors of things required by MessageEvent.source, not itself; mostly related to ScriptHosts (that's how I found out about it in the first place), and of course we need SciptHosts fixed to be able to implement the CommandTargets that are ultimately needed for MessageEvent.source.
One weird behavior is, for example, "moving" the script hosts if they're on the initial (blank) window—this can happen if you obtain it via CommandTarget *before* loading the document via message pump, and it matches on the loaded document afterwards (but not after that).