-- v3: mshtml/tests: Accept rare return value from ReportResult on native. mshtml: Don't process tasks in message loop during parse complete mshtml: Implement EmulateIE* modes for X-UA-Compatible. mshtml: Don't return default ports from location.host in IE10+ modes. mshtml: Avoid calling remove_target_tasks needlessly.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
It's already called by abort_window_bindings.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 1 - dlls/mshtml/oleobj.c | 2 -- dlls/mshtml/persist.c | 2 -- 3 files changed, 5 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index ea1f7f4b278..a5aeb1f4fa6 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -135,7 +135,6 @@ static void detach_inner_window(HTMLInnerWindow *window) dispex_props_unlink(&outer_window->location->dispex);
abort_window_bindings(window); - remove_target_tasks(window->task_magic); release_script_hosts(window); unlink_ref(&window->jscript); window->base.outer_window = NULL; diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index 2374ce0ea81..7dffdbeeec2 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -3441,8 +3441,6 @@ static void set_window_uninitialized(HTMLOuterWindow *window) 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;
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index bea2ab65750..5d55dac6826 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -381,8 +381,6 @@ HRESULT set_moniker(HTMLOuterWindow *window, IMoniker *mon, IUri *nav_uri, IBind hres = create_channelbsc(mon, NULL, NULL, 0, TRUE, &bscallback);
if(SUCCEEDED(hres)) { - if(window->base.inner_window->doc) - remove_target_tasks(window->base.inner_window->task_magic); abort_window_bindings(window->base.inner_window);
hres = load_nsuri(window, nsuri, NULL, bscallback, LOAD_FLAGS_BYPASS_CACHE);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmllocation.c | 16 ++++++++++++++++ dlls/mshtml/tests/documentmode.js | 3 +++ 2 files changed, 19 insertions(+)
diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 5c7e66c40df..b176b56280c 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -225,12 +225,28 @@ static HRESULT WINAPI HTMLLocation_get_host(IHTMLLocation *iface, BSTR *p) HTMLLocation *This = impl_from_IHTMLLocation(iface); URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)}; HRESULT hres; + IUri *uri;
TRACE("(%p)->(%p)\n", This, p);
if(!p) return E_POINTER;
+ if(dispex_compat_mode(&This->window->base.inner_window->event_target.dispex) >= COMPAT_MODE_IE10) { + if(!(uri = get_uri(This))) { + *p = NULL; + return S_OK; + } + + hres = IUri_GetAuthority(uri, p); + if(hres == S_OK || FAILED(hres)) + return hres; + + SysFreeString(*p); + *p = NULL; + return S_OK; + } + url.dwHostNameLength = 1; hres = get_url_components(This, &url); if(FAILED(hres)) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 18749938658..e599cf2b96b 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1184,8 +1184,11 @@ async_test("script_load", function() { });
sync_test("location", function() { + var v = document.documentMode; document.body.innerHTML = '<a name="testanchor">test</a>';
+ ok(location.host === "winetest.example.org" + (v < 10 ? ":80" : ""), "location.host = " + location.host); + ok(location.hash === "", "initial location.hash = " + location.hash); location.hash = "TestAnchor"; ok(location.hash === "#TestAnchor", "location.hash after set to TestAnchor = " + location.hash);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Despite what MSDN says it appears that EmulateIE10 and EmulateIE11 don't care about DOCTYPE validity at all (same as IE=10 and IE=11).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/mutation.c | 53 +++++++++++++++++++++++++++--------- dlls/mshtml/tests/dom.c | 22 +++++++++++++++ 3 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b98671188be..978e4df22db 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1105,6 +1105,7 @@ struct HTMLDocumentNode {
nsIDOMDocument *dom_document; nsIDOMHTMLDocument *html_document; + unsigned int emulate_mode : 1; unsigned int content_ready : 1; unsigned int unload_sent : 1;
diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 3c1a25646db..c5ce26b97bb 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -414,19 +414,28 @@ DWORD get_compat_mode_version(compat_mode_t compat_mode) */ compat_mode_t lock_document_mode(HTMLDocumentNode *doc) { - TRACE("%p: %d\n", doc, doc->document_mode); - if(!doc->document_mode_locked) { doc->document_mode_locked = TRUE;
+ if(doc->emulate_mode && doc->document_mode < COMPAT_MODE_IE10) { + nsIDOMDocumentType *nsdoctype; + + if(NS_SUCCEEDED(nsIDOMDocument_GetDoctype(doc->dom_document, &nsdoctype)) && nsdoctype) + nsIDOMDocumentType_Release(nsdoctype); + else + doc->document_mode = COMPAT_MODE_QUIRKS; + } + if(doc->html_document) nsIDOMHTMLDocument_SetIECompatMode(doc->html_document, get_compat_mode_version(doc->document_mode)); }
+ TRACE("%p: %d\n", doc, doc->document_mode); + return doc->document_mode; }
-static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode, BOOL lock) +static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode, BOOL emulate_mode, BOOL lock) { compat_mode_t max_compat_mode;
@@ -447,6 +456,7 @@ static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode }
doc->document_mode = document_mode; + doc->emulate_mode = emulate_mode; if(lock) lock_document_mode(doc); } @@ -491,9 +501,11 @@ const WCHAR *parse_compat_version(const WCHAR *version_string, compat_mode_t *r)
static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r) { + static const WCHAR emulateIEW[] = {'E','m','u','l','a','t','e','I','E'}; static const WCHAR ie_eqW[] = {'I','E','='}; static const WCHAR edgeW[] = {'e','d','g','e'}; compat_mode_t mode = COMPAT_MODE_INVALID; + BOOL emulate_mode = FALSE;
TRACE("%s\n", debugstr_w(p));
@@ -502,21 +514,31 @@ static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r) p += 3;
do { + BOOL is_emulate = FALSE; + while(iswspace(*p)) p++; if(!wcsnicmp(p, edgeW, ARRAY_SIZE(edgeW))) { p += ARRAY_SIZE(edgeW); if(is_ua_compatible_delimiter(*p)) mode = COMPAT_MODE_IE11; break; - }else if(!(p = parse_compat_version(p, r))) - break; - if(mode < *r) + }else { + if(!wcsnicmp(p, emulateIEW, ARRAY_SIZE(emulateIEW))) { + p += ARRAY_SIZE(emulateIEW); + is_emulate = TRUE; + } + if(!(p = parse_compat_version(p, r))) + break; + } + if(mode < *r) { mode = *r; + emulate_mode = is_emulate; + } while(iswspace(*p)) p++; } while(*p++ == ',');
*r = mode; - return mode != COMPAT_MODE_INVALID; + return emulate_mode; }
void process_document_response_headers(HTMLDocumentNode *doc, IBinding *binding) @@ -542,9 +564,13 @@ void process_document_response_headers(HTMLDocumentNode *doc, IBinding *binding) TRACE("size %lu\n", size);
header = strdupAtoW(buf); - if(header && parse_ua_compatible(header, &document_mode)) { - TRACE("setting document mode %d\n", document_mode); - set_document_mode(doc, document_mode, FALSE); + if(header) { + BOOL emulate_mode = parse_ua_compatible(header, &document_mode); + + if(document_mode != COMPAT_MODE_INVALID) { + TRACE("setting document mode %d\n", document_mode); + set_document_mode(doc, document_mode, emulate_mode, FALSE); + } } free(header); } @@ -573,8 +599,9 @@ static void process_meta_element(HTMLDocumentNode *doc, nsIDOMHTMLMetaElement *m
if(!wcsicmp(http_equiv, L"x-ua-compatible")) { compat_mode_t document_mode; - if(parse_ua_compatible(content, &document_mode)) - set_document_mode(doc, document_mode, TRUE); + BOOL emulate_mode = parse_ua_compatible(content, &document_mode); + if(document_mode != COMPAT_MODE_INVALID) + set_document_mode(doc, document_mode, emulate_mode, TRUE); else FIXME("Unsupported document mode %s\n", debugstr_w(content)); } @@ -907,7 +934,7 @@ static void NSAPI nsDocumentObserver_BindToDocument(nsIDocumentObserver *iface, mode = COMPAT_MODE_IE11; }
- set_document_mode(This, mode, FALSE); + set_document_mode(This, mode, FALSE, FALSE); nsIDOMDocumentType_Release(nsdoctype); } } diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 8383f167cdd..0ff11a74d01 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11836,6 +11836,10 @@ static void test_quirks_mode(void) " <meta http-equiv="x-ua-compatible" content="IE=%s" />" "</head><body></body></html>", tests[i].str); run_domtest(buf, test_document_mode); + sprintf(buf, "<html><head>" + " <meta http-equiv="x-ua-compatible" content="IE=%s" />" + "</head><body></body></html>", tests[i].str); + run_domtest(buf, test_document_mode); }
expected_document_mode = 8; @@ -11848,6 +11852,24 @@ static void test_quirks_mode(void) " <body>" " </body>" "</html>", test_document_mode); + + for(i = 7; i <= 11; i++) { + char buf[128]; + expected_document_mode = i; + sprintf(buf, "<!DOCTYPE html>\n<html><head>" + " <meta http-equiv="x-ua-compatible" content="IE=EmulateIE%u" />" + "</head><body></body></html>", i); + run_domtest(buf, test_document_mode); + expected_document_mode = i < 10 ? 5 : i; + sprintf(buf, "<html><head>" + " <meta http-equiv="x-ua-compatible" content="IE=EmulateIE%u" />" + "</head><body></body></html>", i); + run_domtest(buf, test_document_mode); + sprintf(buf, "<html><head>" + " <meta http-equiv="x-ua-compatible" content="IE=eMulaTeie%u" />" + "</head><body></body></html>", i); + run_domtest(buf, test_document_mode); + } }
static void test_document_mode_lock(void)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Note that native still sends a synchronous readyState notification during SuperNavigate (which we don't yet).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 3 +- dlls/mshtml/mutation.c | 9 ++++ dlls/mshtml/task.c | 11 +++-- dlls/mshtml/tests/events.c | 93 +++++++++++++++++++++++++++++++++++- dlls/mshtml/xmlhttprequest.c | 2 +- 5 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 978e4df22db..cd693fd33dd 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1470,11 +1470,12 @@ typedef struct { struct list *pending_xhr_events_tail; struct wine_rb_tree session_storage_map; void *blocking_xhr; + unsigned tasks_locked; } thread_data_t;
thread_data_t *get_thread_data(BOOL); HWND get_thread_hwnd(void); -void unblock_tasks_and_timers(thread_data_t*); +void unblock_tasks_and_timers(thread_data_t*,BOOL); int session_storage_map_cmp(const void*,const struct wine_rb_entry*); void destroy_session_storage(thread_data_t*);
diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index c5ce26b97bb..a9bec58f544 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -272,8 +272,14 @@ static void call_explorer_69(HTMLDocumentObj *doc)
static void parse_complete(HTMLDocumentObj *doc) { + thread_data_t *thread_data; + TRACE("(%p)\n", doc);
+ if(!(thread_data = get_thread_data(TRUE))) + return; + thread_data->tasks_locked++; + if(doc->nscontainer->usermode == EDITMODE) init_editor(doc->doc_node);
@@ -287,6 +293,9 @@ static void parse_complete(HTMLDocumentObj *doc) IDocObjectService_FireNavigateComplete2(doc->doc_object_service, &doc->window->base.IHTMLWindow2_iface, 0);
/* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */ + + if(!--thread_data->tasks_locked) + unblock_tasks_and_timers(thread_data, TRUE); }
static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISupports *arg2) diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index 49f76d101a9..711b9336b3e 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -310,7 +310,7 @@ static LRESULT process_timer(void) thread_data = get_thread_data(FALSE); assert(thread_data != NULL);
- if(list_empty(&thread_data->timer_list) || thread_data->blocking_xhr) { + if(list_empty(&thread_data->timer_list) || thread_data->tasks_locked || thread_data->blocking_xhr) { KillTimer(thread_data->thread_hwnd, TIMER_ID); return 0; } @@ -345,7 +345,7 @@ static LRESULT process_timer(void) call_timer_disp(disp, timer_type);
IDispatch_Release(disp); - }while(!list_empty(&thread_data->timer_list) && !thread_data->blocking_xhr); + }while(!list_empty(&thread_data->timer_list) && !thread_data->tasks_locked && !thread_data->blocking_xhr);
KillTimer(thread_data->thread_hwnd, TIMER_ID); return 0; @@ -364,6 +364,9 @@ static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa while(1) { struct list *head = list_head(&thread_data->task_list);
+ if(thread_data->tasks_locked) + break; + if(head) { task_t *task = LIST_ENTRY(head, task_t, entry); list_remove(&task->entry); @@ -479,9 +482,9 @@ ULONGLONG get_time_stamp(void) return (((ULONGLONG)time.dwHighDateTime << 32) + time.dwLowDateTime) / 10000 - time_epoch; }
-void unblock_tasks_and_timers(thread_data_t *thread_data) +void unblock_tasks_and_timers(thread_data_t *thread_data, BOOL include_task_list) { - if(!list_empty(&thread_data->event_task_list)) + if(!list_empty(&thread_data->event_task_list) || (include_task_list && !list_empty(&thread_data->task_list))) PostMessageW(thread_data->thread_hwnd, WM_PROCESSTASK, 0, 0);
if(!thread_data->blocking_xhr && !list_empty(&thread_data->timer_list)) { diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 2cf63f06dd3..55d0fa62672 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -133,6 +133,7 @@ static IOleDocumentView *view; static BOOL is_ie9plus; static int document_mode; static unsigned in_fire_event; +static DWORD main_thread_id;
typedef struct { LONG x; @@ -6196,6 +6197,7 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) }
static IHTMLDocument2 *notif_doc; +static unsigned in_nav_notif_test, nav_notif_test_depth; static BOOL doc_complete;
static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, @@ -6222,9 +6224,14 @@ static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID) { - if(dispID == DISPID_READYSTATE){ + HRESULT hres; + + ok(GetCurrentThreadId() == main_thread_id, "OnChanged called on different thread\n"); + + if(dispID == DISPID_READYSTATE) { BSTR state; - HRESULT hres; + + ok(nav_notif_test_depth < 2, "nav_notif_test_depth = %u\n", nav_notif_test_depth);
hres = IHTMLDocument2_get_readyState(notif_doc, &state); ok(hres == S_OK, "get_readyState failed: %08lx\n", hres); @@ -6235,6 +6242,44 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D SysFreeString(state); }
+ if(dispID == 1005) { + IHTMLPrivateWindow *priv_window; + IHTMLWindow2 *window; + BSTR bstr, bstr2; + VARIANT v; + + ok(!nav_notif_test_depth, "nav_notif_test_depth = %u\n", nav_notif_test_depth); + + if(in_nav_notif_test != 1) + return S_OK; + in_nav_notif_test++; + nav_notif_test_depth++; + + hres = IHTMLDocument2_get_parentWindow(notif_doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + ok(window != NULL, "window == NULL\n"); + + V_VT(&v) = VT_EMPTY; + bstr = SysAllocString(L"about:blank"); + 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 == S_OK, "SuperNavigate failed: %08lx\n", hres); + IHTMLPrivateWindow_Release(priv_window); + IHTMLWindow2_Release(window); + SysFreeString(bstr2); + SysFreeString(bstr); + + ok(nav_notif_test_depth == 1, "nav_notif_test_depth = %u\n", nav_notif_test_depth); + pump_msgs(NULL); + pump_msgs(NULL); + pump_msgs(NULL); + ok(nav_notif_test_depth == 1, "nav_notif_test_depth = %u\n", nav_notif_test_depth); + ok(!doc_complete, "doc_complete = TRUE\n"); + nav_notif_test_depth--; + } + return S_OK; }
@@ -7445,6 +7490,48 @@ static void test_sync_xhr_events(const char *doc_str) IHTMLDocument2_Release(doc[1]); }
+static void test_navigation_during_notif(void) +{ + IPersistMoniker *persist; + IHTMLDocument2 *doc; + IMoniker *mon; + HRESULT hres; + BSTR url; + MSG msg; + + if(!(doc = create_document())) + return; + + notif_doc = doc; + doc_complete = FALSE; + set_client_site(doc, TRUE); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + url = SysAllocString(L"about:setting"); + hres = CreateURLMoniker(NULL, url, &mon); + SysFreeString(url); + ok(hres == S_OK, "CreateUrlMoniker failed: %08lx\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist); + ok(hres == S_OK, "Could not get IPersistMoniker iface: %08lx\n", hres); + + hres = IPersistMoniker_Load(persist, FALSE, mon, NULL, 0); + ok(hres == S_OK, "Load failed: %08lx\n", hres); + IPersistMoniker_Release(persist); + IMoniker_Release(mon); + + in_nav_notif_test = 1; + while(in_nav_notif_test != 2 && !doc_complete && GetMessageA(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + ok(!nav_notif_test_depth, "nav_notif_test_depth = %u\n", nav_notif_test_depth); + in_nav_notif_test = 0; + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); +} + static BOOL check_ie(void) { IHTMLDocument2 *doc; @@ -7475,6 +7562,7 @@ static BOOL check_ie(void) START_TEST(events) { CoInitialize(NULL); + main_thread_id = GetCurrentThreadId();
if(check_ie()) { container_hwnd = create_container_window(); @@ -7516,6 +7604,7 @@ START_TEST(events) test_storage_events(empty_doc_ie9_str); test_sync_xhr_events(empty_doc_ie9_str); } + test_navigation_during_notif();
/* Test this last since it doesn't close the view properly. */ test_document_close(); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index fffc9fab51b..f7eff984d87 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -306,7 +306,7 @@ static nsresult sync_xhr_send(HTMLXMLHttpRequest *xhr, nsIVariant *nsbody) window->base.outer_window->readystate_locked--;
if(!--window->blocking_depth) - unblock_tasks_and_timers(thread_data); + unblock_tasks_and_timers(thread_data, FALSE);
/* Process any pending events now since they were part of the blocked send() above */ synthesize_pending_events(xhr);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
events.c already has it.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c index e6acf5ae5b1..88831bc66c1 100644 --- a/dlls/mshtml/tests/script.c +++ b/dlls/mshtml/tests/script.c @@ -4289,7 +4289,7 @@ static void report_data(ProtocolHandler *This) ok(hres == S_OK, "ReportData failed: %08lx\n", hres);
hres = IInternetProtocolSink_ReportResult(This->sink, S_OK, 0, NULL); - ok(hres == S_OK, "ReportResult failed: %08lx\n", hres); + ok(hres == S_OK || broken(hres == 0x80ef0001), "ReportResult failed: %08lx\n", hres); }
typedef struct js_stream_t {
Jacek Caban (@jacek) commented about dlls/mshtml/mutation.c:
if(!wcsicmp(http_equiv, L"x-ua-compatible")) { compat_mode_t document_mode;
if(parse_ua_compatible(content, &document_mode))
set_document_mode(doc, document_mode, TRUE);
BOOL emulate_mode = parse_ua_compatible(content, &document_mode);
if(document_mode != COMPAT_MODE_INVALID)
`document_mode` will be uninitialized if `parse_ua_compatible` uses early return. Using return value for emulation mode looks weird here, I'd suggest to swap those and return document mode instead.