Module: wine Branch: master Commit: ac7a3de155a94235b91a1578858765309983943b URL: https://gitlab.winehq.org/wine/wine/-/commit/ac7a3de155a94235b91a15788587653...
Author: Gabriel Ivăncescu gabrielopcode@gmail.com Date: Tue Nov 22 18:26:22 2022 +0200
mshtml: Implement performance.timing.domInteractive.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
---
dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/mutation.c | 2 + dlls/mshtml/omnavigator.c | 4 +- dlls/mshtml/tests/documentmode.js | 5 +++ dlls/mshtml/tests/htmldoc.c | 84 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 96042e60ff8..7d50a3b962f 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -518,6 +518,7 @@ typedef struct { ULONGLONG request_time; ULONGLONG response_start_time; ULONGLONG response_end_time; + ULONGLONG dom_interactive_time; } HTMLPerformanceTiming;
typedef struct nsChannelBSC nsChannelBSC; diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 7166d74cf0c..a311c2a0ba8 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -305,6 +305,8 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo }
bind_event_scripts(This); + + This->window->performance_timing->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE); return NS_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index b0f74881f9a..a8832792359 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1756,9 +1756,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domInteractive(IHTMLPerformanceT { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface);
- FIXME("(%p)->(%p) returning fake value\n", This, p); + TRACE("(%p)->(%p)\n", This, p);
- *p = TIMING_FAKE_TIMESTAMP; + *p = This->dom_interactive_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index c09f10ae54a..2c6a800d8cf 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -29,6 +29,7 @@ ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestSta ok(performance.timing.responseStart >= performance.timing.requestStart, "responseStart < requestStart"); ok(performance.timing.responseEnd >= performance.timing.responseStart, "responseEnd < responseStart"); ok(performance.timing.domLoading >= performance.timing.responseEnd, "domLoading < responseEnd"); +ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -75,6 +76,10 @@ if(window.addEventListener) { document.attachEvent("onunload", function() { ok(false, "unload fired on document"); }); }
+sync_test("performance timing", function() { + ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); +}); + sync_test("page transition events", function() { if(document.documentMode < 11) ok(pageshow_fired === false, "pageshow fired"); diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index 49c0ddfe5c4..c530452f50b 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -450,6 +450,85 @@ static void _test_current_url(unsigned line, IUnknown *unk, const WCHAR *exurl) IHTMLDocument2_Release(doc); }
+#define test_performance_timing(a,b) _test_performance_timing(__LINE__,a,b) +static void _test_performance_timing(unsigned line, IUnknown *unk, const WCHAR *prop) +{ + BOOL expect_non_zero = FALSE; + DISPPARAMS dp = { 0 }; + IHTMLWindow2 *window; + IHTMLDocument2 *doc; + IDispatchEx *dispex; + DISPID dispid; + HRESULT hres; + VARIANT var; + BSTR bstr; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&doc); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08lx\n", hres); + + hres = IHTMLDocument2_get_readyState(doc, &bstr); + ok_(__FILE__,line)(hres == S_OK, "get_readyState failed: %08lx\n", hres); + if(!wcscmp(bstr, L"interactive")) + expect_non_zero = !wcscmp(prop, L"domInteractive"); + else if(!wcscmp(bstr, L"complete")) + expect_non_zero = TRUE; + SysFreeString(bstr); + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok_(__FILE__,line)(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + IHTMLDocument2_Release(doc); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + IHTMLWindow2_Release(window); + + bstr = SysAllocString(L"performance"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(performance) failed: %08lx\n", hres); + SysFreeString(bstr); + + V_VT(&var) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(performance) failed: %08lx\n", hres); + ok_(__FILE__,line)(V_VT(&var) == VT_DISPATCH, "V_VT(performance) = %d\n", V_VT(&var)); + ok_(__FILE__,line)(V_DISPATCH(&var) != NULL, "V_DISPATCH(performance) = NULL\n"); + IDispatchEx_Release(dispex); + + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + VariantClear(&var); + + bstr = SysAllocString(L"timing"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(timing) failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(timing) failed: %08lx\n", hres); + ok_(__FILE__,line)(V_VT(&var) == VT_DISPATCH, "V_VT(timing) = %d\n", V_VT(&var)); + ok_(__FILE__,line)(V_DISPATCH(&var) != NULL, "V_DISPATCH(timing) = NULL\n"); + IDispatchEx_Release(dispex); + + hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDispatchEx, (void**)&dispex); + ok_(__FILE__,line)(hres == S_OK, "QueryInterface(IID_IDispatchEx) failed: %08lx\n", hres); + VariantClear(&var); + + bstr = SysAllocString(prop); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &dispid); + ok_(__FILE__,line)(hres == S_OK, "GetDispID(%s) failed: %08lx\n", wine_dbgstr_w(prop), hres); + SysFreeString(bstr); + + hres = IDispatchEx_InvokeEx(dispex, dispid, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok_(__FILE__,line)(hres == S_OK, "InvokeEx(%s) failed: %08lx\n", wine_dbgstr_w(prop), hres); + ok_(__FILE__,line)(V_VT(&var) == VT_UI8, "V_VT(%s) = %d\n", wine_dbgstr_w(prop), V_VT(&var)); + IDispatchEx_Release(dispex); + + if(expect_non_zero) + ok_(__FILE__,line)(V_UI8(&var) != 0, "%s is 0\n", wine_dbgstr_w(prop)); + else + ok_(__FILE__,line)(V_UI8(&var) == 0, "%s is not 0\n", wine_dbgstr_w(prop)); +} + static BSTR get_mime_type_display_name(const WCHAR *content_type) { WCHAR buffer[128], ext[128], *str, *progid; @@ -1039,6 +1118,10 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D if(!editmode) test_readyState(NULL); readystate_set_interactive = (load_state != LD_INTERACTIVE); + + /* w10pro64_ja has it set to zero despite readyState being interactive, for whatever reason */ + if(!is_mhtml) + test_performance_timing(doc_unk, L"domInteractive"); return S_OK; case 1012: CHECK_EXPECT2(OnChanged_1012); @@ -3574,6 +3657,7 @@ static HRESULT WINAPI DocObjectService_FireNavigateComplete2( { CHECK_EXPECT(FireNavigateComplete2); test_readyState(NULL); + test_performance_timing(doc_unk, L"domInteractive");
if(loading_hash) ok(dwFlags == 0x10 || broken(!dwFlags), "dwFlags = %lx, expected 0x10\n", dwFlags);