-- v2: mshtml: Implement performance.timing.msFirstPaint. mshtml: Implement performance.timing.loadEventStart & loadEventEnd. mshtml: Get rid of useless window check. mshtml: Implement performance.timing.domContentLoadedEventStart & End. mshtml: Implement performance.timing.domComplete. mshtml: Implement performance.timing.domInteractive. mshtml: Implement performance.timing.domLoading. mshtml: Implement performance.timing.responseStart & responseEnd. mshtml: Implement the remaining pre-response performance.timing props. mshtml: Implement performance.timing.unloadEventStart & unloadEventEnd. mshtml: Implement performance.timing.redirectStart. mshtml: Implement performance.timing.navigationStart. mshtml: Store link to the inner window in HTMLPerformance.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
And likewise from the window, so we know when to detach it.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Needed by performance.timing (and in future patches as well). --- dlls/mshtml/htmlwindow.c | 17 +++++++++-------- dlls/mshtml/mshtml_private.h | 7 +++++-- dlls/mshtml/omnavigator.c | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index baaedb6b6d4..1d3c71d83bf 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -308,6 +308,10 @@ static void release_inner_window(HTMLInnerWindow *This) IHTMLStorage_Release(This->local_storage); }
+ if(This->performance_obj && This->performance_obj != NO_PERFORMANCE_OBJ) + detach_performance(This->performance_obj); + VariantClear(&This->performance); + if(This->mon) IMoniker_Release(This->mon);
@@ -2414,9 +2418,9 @@ static HRESULT WINAPI HTMLWindow7_put_performance(IHTMLWindow7 *iface, VARIANT v
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
- if(!This->performance_initialized) { + if(!This->performance_obj) { V_VT(&This->performance) = VT_EMPTY; - This->performance_initialized = TRUE; + This->performance_obj = NO_PERFORMANCE_OBJ; }
return VariantCopy(&This->performance, &v); @@ -2429,16 +2433,13 @@ static HRESULT WINAPI HTMLWindow7_get_performance(IHTMLWindow7 *iface, VARIANT *
TRACE("(%p)->(%p)\n", This, p);
- if(!This->performance_initialized) { - IHTMLPerformance *performance; - - hres = create_performance(dispex_compat_mode(&This->event_target.dispex), &performance); + if(!This->performance_obj) { + hres = create_performance(This, &This->performance_obj); if(FAILED(hres)) return hres;
V_VT(&This->performance) = VT_DISPATCH; - V_DISPATCH(&This->performance) = (IDispatch*)performance; - This->performance_initialized = TRUE; + V_DISPATCH(&This->performance) = (IDispatch*)This->performance_obj; }
V_VT(p) = VT_NULL; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d9e2d93d220..e8dd0997639 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -577,7 +577,7 @@ struct HTMLInnerWindow { IHTMLStorage *session_storage; IHTMLStorage *local_storage;
- BOOL performance_initialized; + IHTMLPerformance *performance_obj; VARIANT performance;
unsigned parser_callback_cnt; @@ -596,6 +596,8 @@ struct HTMLInnerWindow { struct list bindings; };
+#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) + typedef enum { UNKNOWN_USERMODE, BROWSEMODE, @@ -966,7 +968,8 @@ HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFact HRESULT HTMLLocation_Create(HTMLInnerWindow*,HTMLLocation**) DECLSPEC_HIDDEN; HRESULT create_navigator(compat_mode_t,IOmNavigator**) DECLSPEC_HIDDEN; HRESULT create_html_screen(compat_mode_t,IHTMLScreen**) DECLSPEC_HIDDEN; -HRESULT create_performance(compat_mode_t,IHTMLPerformance**) DECLSPEC_HIDDEN; +HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**) DECLSPEC_HIDDEN; +void detach_performance(IHTMLPerformance*) DECLSPEC_HIDDEN; HRESULT create_history(HTMLInnerWindow*,OmHistory**) DECLSPEC_HIDDEN; HRESULT create_namespace_collection(compat_mode_t,IHTMLNamespaceCollection**) DECLSPEC_HIDDEN; HRESULT create_dom_implementation(HTMLDocumentNode*,IHTMLDOMImplementation**) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index db48cc6213b..f25cce2c105 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -2023,6 +2023,7 @@ typedef struct {
IHTMLPerformanceNavigation *navigation; IHTMLPerformanceTiming *timing; + HTMLInnerWindow *window; } HTMLPerformance;
static inline HTMLPerformance *impl_from_IHTMLPerformance(IHTMLPerformance *iface) @@ -2070,6 +2071,8 @@ static ULONG WINAPI HTMLPerformance_Release(IHTMLPerformance *iface) TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) { + if(This->window) + This->window->performance_obj = NO_PERFORMANCE_OBJ; if(This->timing) IHTMLPerformanceTiming_Release(This->timing); if(This->navigation) @@ -2208,7 +2211,7 @@ static dispex_static_data_t HTMLPerformance_dispex = { HTMLPerformance_iface_tids };
-HRESULT create_performance(compat_mode_t compat_mode, IHTMLPerformance **ret) +HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) { HTMLPerformance *performance;
@@ -2218,14 +2221,21 @@ HRESULT create_performance(compat_mode_t compat_mode, IHTMLPerformance **ret)
performance->IHTMLPerformance_iface.lpVtbl = &HTMLPerformanceVtbl; performance->ref = 1; + performance->window = window;
init_dispatch(&performance->dispex, (IUnknown*)&performance->IHTMLPerformance_iface, - &HTMLPerformance_dispex, compat_mode); + &HTMLPerformance_dispex, dispex_compat_mode(&window->event_target.dispex));
*ret = &performance->IHTMLPerformance_iface; return S_OK; }
+void detach_performance(IHTMLPerformance *iface) +{ + HTMLPerformance *performance = impl_from_IHTMLPerformance(iface); + performance->window = NULL; +} + typedef struct { DispatchEx dispex; IHTMLNamespaceCollection IHTMLNamespaceCollection_iface;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/navigate.c | 4 +++- dlls/mshtml/omnavigator.c | 12 ++++++++++-- dlls/mshtml/tests/documentmode.js | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e8dd0997639..77a23362415 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -594,6 +594,8 @@ struct HTMLInnerWindow { IMoniker *mon; nsChannelBSC *bscallback; struct list bindings; + + ULONGLONG navigation_start_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 5825e0f27c0..79c88ae31fc 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1357,8 +1357,10 @@ static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) { nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
- if(This->is_doc_channel) + if(This->is_doc_channel) { This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE; + This->bsc.window->navigation_start_time = get_time_stamp(); + }
return S_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index f25cce2c105..34514115030 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1502,6 +1502,7 @@ typedef struct { IHTMLPerformanceTiming IHTMLPerformanceTiming_iface;
LONG ref; + HTMLInnerWindow *window; } HTMLPerformanceTiming;
static inline HTMLPerformanceTiming *impl_from_IHTMLPerformanceTiming(IHTMLPerformanceTiming *iface) @@ -1549,6 +1550,7 @@ static ULONG WINAPI HTMLPerformanceTiming_Release(IHTMLPerformanceTiming *iface) TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) { + IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); release_dispex(&This->dispex); heap_free(This); } @@ -1597,9 +1599,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformance { 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->window->navigation_start_time; return S_OK; }
@@ -2154,12 +2156,18 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP if(!This->timing) { HTMLPerformanceTiming *timing;
+ if(!This->window) + return E_UNEXPECTED; + timing = heap_alloc_zero(sizeof(*timing)); if(!timing) return E_OUTOFMEMORY;
timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; timing->ref = 1; + timing->window = This->window; + IHTMLWindow2_AddRef(&timing->window->base.IHTMLWindow2_iface); + init_dispatch(&timing->dispex, (IUnknown*)&timing->IHTMLPerformanceTiming_iface, &HTMLPerformanceTiming_dispex, dispex_compat_mode(&This->dispex));
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 33d60f7e835..f83597d305a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -19,6 +19,8 @@ var compat_version; var tests = [];
+ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); + var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false; window.onbeforeunload = function() { ok(false, "beforeunload fired"); };
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/navigate.c | 2 ++ dlls/mshtml/omnavigator.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 1 + 4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 77a23362415..4bf8fb65624 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -596,6 +596,7 @@ struct HTMLInnerWindow { struct list bindings;
ULONGLONG navigation_start_time; + ULONGLONG redirect_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 79c88ae31fc..06e3b1e9544 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1717,6 +1717,8 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t This->nschannel->content_type = heap_strdupWtoA(status_text); break; case BINDSTATUS_REDIRECTING: + if(This->is_doc_channel && !This->bsc.window->redirect_time) + This->bsc.window->redirect_time = get_time_stamp(); return handle_redirect(This, status_text); case BINDSTATUS_BEGINDOWNLOADDATA: { IWinInetHttpInfo *http_info; diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 34514115030..f2afa1a9611 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1629,9 +1629,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectStart(IHTMLPerformanceTi { 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->window->redirect_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index f83597d305a..f0a91fea545 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,6 +20,7 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.redirectStart === 0, "redirectStart != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 3 +++ dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 9 ++++++++- dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 2 ++ 5 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 1d3c71d83bf..dcf21460b8d 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -4116,6 +4116,9 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow return hres; }
+ /* Initial empty doc does not have unload events or timings */ + window->base.inner_window->doc->unload_sent = TRUE; + if(parent) { IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 4bf8fb65624..90aba4e9236 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -596,6 +596,8 @@ struct HTMLInnerWindow { struct list bindings;
ULONGLONG navigation_start_time; + ULONGLONG unload_event_start_time; + ULONGLONG unload_event_end_time; ULONGLONG redirect_time; };
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 0248737b012..f2f17bc180a 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -383,8 +383,8 @@ static nsresult NSAPI handle_beforeunload(nsIDOMEventListener *iface, nsIDOMEven static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) { nsEventListener *This = impl_from_nsIDOMEventListener(iface); + HTMLInnerWindow *window, *pending_window; HTMLDocumentNode *doc = This->This->doc; - HTMLInnerWindow *window; DOMEvent *event; HRESULT hres;
@@ -392,12 +392,19 @@ static nsresult NSAPI handle_unload(nsIDOMEventListener *iface, nsIDOMEvent *nse return NS_OK; doc->unload_sent = TRUE;
+ pending_window = window->base.outer_window->pending_window; + if(pending_window) + pending_window->unload_event_start_time = get_time_stamp(); + hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), &event); if(SUCCEEDED(hres)) { dispatch_event(&window->event_target, event); IDOMEvent_Release(&event->IDOMEvent_iface); }
+ if(pending_window) + pending_window->unload_event_end_time = get_time_stamp(); + return NS_OK; }
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index f2afa1a9611..d6464ae8630 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1609,9 +1609,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventStart(IHTMLPerformanc { 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->window->unload_event_start_time; return S_OK; }
@@ -1619,9 +1619,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventEnd(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->window->unload_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index f0a91fea545..a9c2b36ceee 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,6 +20,8 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); +ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
var pageshow_fired = false, pagehide_fired = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 3 ++ dlls/mshtml/navigate.c | 12 +++++++ dlls/mshtml/omnavigator.c | 52 ++++++++++++++++++++++--------- dlls/mshtml/tests/documentmode.js | 7 +++++ 4 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 90aba4e9236..59439823817 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -599,6 +599,9 @@ struct HTMLInnerWindow { ULONGLONG unload_event_start_time; ULONGLONG unload_event_end_time; ULONGLONG redirect_time; + ULONGLONG dns_lookup_time; + ULONGLONG connect_time; + ULONGLONG request_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 06e3b1e9544..6ca2fbe1dcb 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1720,6 +1720,18 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t if(This->is_doc_channel && !This->bsc.window->redirect_time) This->bsc.window->redirect_time = get_time_stamp(); return handle_redirect(This, status_text); + case BINDSTATUS_FINDINGRESOURCE: + if(This->is_doc_channel && !This->bsc.window->dns_lookup_time) + This->bsc.window->dns_lookup_time = get_time_stamp(); + break; + case BINDSTATUS_CONNECTING: + if(This->is_doc_channel) + This->bsc.window->connect_time = get_time_stamp(); + break; + case BINDSTATUS_SENDINGREQUEST: + if(This->is_doc_channel) + This->bsc.window->request_time = get_time_stamp(); + break; case BINDSTATUS_BEGINDOWNLOADDATA: { IWinInetHttpInfo *http_info; DWORD status, size = sizeof(DWORD); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index d6464ae8630..5b3f54c2d05 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1595,6 +1595,24 @@ static HRESULT WINAPI HTMLPerformanceTiming_Invoke(IHTMLPerformanceTiming *iface
#define TIMING_FAKE_TIMESTAMP 0xdeadbeef
+static ULONGLONG get_fetch_time(HTMLPerformanceTiming *This) +{ + /* If there's no prior doc unloaded and no redirects, fetch time == navigationStart time */ + if(!This->window->unload_event_end_time && !This->window->redirect_time) + return This->window->navigation_start_time; + + if(This->window->dns_lookup_time) + return This->window->dns_lookup_time; + if(This->window->connect_time) + return This->window->connect_time; + if(This->window->request_time) + return This->window->request_time; + if(This->window->unload_event_end_time) + return This->window->unload_event_end_time; + + return This->window->redirect_time; +} + static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformanceTiming *iface, ULONGLONG *p) { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface); @@ -1639,9 +1657,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectEnd(IHTMLPerformanceTimi { 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->window->redirect_time ? get_fetch_time(This) : 0; return S_OK; }
@@ -1649,9 +1667,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_fetchStart(IHTMLPerformanceTimin { 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 = get_fetch_time(This); return S_OK; }
@@ -1659,9 +1677,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupStart(IHTMLPerforman { 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->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1669,9 +1687,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupEnd(IHTMLPerformance { 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->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1679,9 +1698,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectStart(IHTMLPerformanceTim { 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->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1689,9 +1709,11 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectEnd(IHTMLPerformanceTimin { 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->window->request_time ? This->window->request_time : + This->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1699,9 +1721,11 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_requestStart(IHTMLPerformanceTim { 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->window->request_time ? This->window->request_time : + This->window->connect_time ? This->window->connect_time : + This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index a9c2b36ceee..e933ea0ff54 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -20,9 +20,16 @@ var compat_version; var tests = [];
ok(performance.timing.navigationStart > 0, "navigationStart <= 0"); +ok(performance.timing.fetchStart == performance.timing.navigationStart, "fetchStart != navigationStart"); +ok(performance.timing.domainLookupStart >= performance.timing.fetchStart, "domainLookupStart < fetchStart"); +ok(performance.timing.domainLookupEnd >= performance.timing.domainLookupStart, "domainLookupEnd < domainLookupStart"); +ok(performance.timing.connectStart >= performance.timing.domainLookupEnd, "connectStart < domainLookupEnd"); +ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd < connectStart"); +ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); +ok(performance.timing.redirectEnd === 0, "redirectEnd != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/navigate.c | 23 ++++++++++++++++------- dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 59439823817..61b22306d43 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -602,6 +602,8 @@ struct HTMLInnerWindow { ULONGLONG dns_lookup_time; ULONGLONG connect_time; ULONGLONG request_time; + ULONGLONG response_start_time; + ULONGLONG response_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 6ca2fbe1dcb..c5a9cfd1263 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1107,6 +1107,9 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) if(!This->response_processed) { IWinInetHttpInfo *wininet_info;
+ if(This->is_doc_channel) + This->bsc.window->response_start_time = get_time_stamp(); + This->response_processed = TRUE; if(This->bsc.binding) { hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&wininet_info); @@ -1522,13 +1525,16 @@ static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) { nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
- if(result != E_ABORT && This->is_doc_channel && This->bsc.window) { - if(FAILED(result)) - handle_navigation_error(This, result); - else if(This->nschannel) { - result = async_stop_request(This); - if(SUCCEEDED(result)) - return S_OK; + if(This->is_doc_channel && This->bsc.window) { + This->bsc.window->response_end_time = get_time_stamp(); + if(result != E_ABORT) { + if(FAILED(result)) + handle_navigation_error(This, result); + else if(This->nschannel) { + result = async_stop_request(This); + if(SUCCEEDED(result)) + return S_OK; + } } }
@@ -1786,6 +1792,9 @@ static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code, char *str; HRESULT hres;
+ if(This->is_doc_channel) + This->bsc.window->response_start_time = get_time_stamp(); + This->response_processed = TRUE; This->nschannel->response_status = response_code;
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 5b3f54c2d05..65a31fa41db 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1733,9 +1733,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseStart(IHTMLPerformanceTi { 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->window->response_start_time; return S_OK; }
@@ -1743,9 +1743,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseEnd(IHTMLPerformanceTimi { 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->window->response_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index e933ea0ff54..881a08e9a54 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -26,6 +26,8 @@ ok(performance.timing.domainLookupEnd >= performance.timing.domainLookupStart, " ok(performance.timing.connectStart >= performance.timing.domainLookupEnd, "connectStart < domainLookupEnd"); ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd < connectStart"); ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); +ok(performance.timing.responseStart >= performance.timing.requestStart, "responseStart < requestStart"); +ok(performance.timing.responseEnd >= performance.timing.responseStart, "responseEnd < responseStart"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 5 +++-- dlls/mshtml/tests/documentmode.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 65a31fa41db..4c55a391e95 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1753,9 +1753,10 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domLoading(IHTMLPerformanceTimin { 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; + /* Make sure this is after responseEnd, when the Gecko parser starts */ + *p = This->window->response_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 881a08e9a54..c09f10ae54a 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -28,6 +28,7 @@ ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd"); 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.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
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 61b22306d43..e63db0ec480 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -604,6 +604,7 @@ struct HTMLInnerWindow { ULONGLONG request_time; ULONGLONG response_start_time; ULONGLONG response_end_time; + ULONGLONG dom_interactive_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 7166d74cf0c..f3472354fe5 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->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 4c55a391e95..d99764d0f2d 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1764,9 +1764,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->window->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..d6bf26b11dd 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 = !wcscmp(prop, L"domInteractive") || !wcscmp(prop, L"domComplete"); + 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 || is_lang_english()) + 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);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/nsevents.c | 1 + dlls/mshtml/omnavigator.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 2 ++ dlls/mshtml/tests/htmldoc.c | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e63db0ec480..bbf79f8ed4b 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -605,6 +605,7 @@ struct HTMLInnerWindow { ULONGLONG response_start_time; ULONGLONG response_end_time; ULONGLONG dom_interactive_time; + ULONGLONG dom_complete_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index f2f17bc180a..6d29f26394d 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -319,6 +319,7 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event if(doc_obj) handle_docobj_load(doc_obj);
+ doc->window->dom_complete_time = get_time_stamp(); set_ready_state(doc->outer_window, READYSTATE_COMPLETE);
if(doc_obj) { diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index d99764d0f2d..bf4e56eaf24 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1794,9 +1794,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domComplete(IHTMLPerformanceTimi { 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->window->dom_complete_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 2c6a800d8cf..72311d5903b 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -30,6 +30,7 @@ ok(performance.timing.responseStart >= performance.timing.requestStart, "respons 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.domComplete === 0, "domComplete != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -78,6 +79,7 @@ if(window.addEventListener) {
sync_test("performance timing", function() { ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); + ok(performance.timing.domComplete >= performance.timing.domInteractive, "domComplete < domInteractive"); });
sync_test("page transition events", function() { diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index d6bf26b11dd..b42f497d0db 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -2986,6 +2986,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(nCmdexecopt == 0, "nCmdexecopts=%08lx\n", nCmdexecopt); ok(pvaOut == NULL, "pvaOut=%p\n", pvaOut); ok(pvaIn == NULL, "pvaIn=%p\n", pvaIn); + test_performance_timing(doc_unk, L"domComplete"); readystate_set_loading = FALSE; readystate_set_interactive = FALSE; load_state = LD_COMPLETE; @@ -3133,6 +3134,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID ok(pvaOut == NULL, "pvaOut != NULL\n");
test_readyState(NULL); + test_performance_timing(doc_unk, L"domComplete"); return E_NOTIMPL;
case 105: @@ -3195,6 +3197,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID CHECK_EXPECT(Exec_MSHTML_PARSECOMPLETE); ok(pvaIn == NULL, "pvaIn != NULL\n"); ok(pvaOut == NULL, "pvaOut != NULL\n"); + test_performance_timing(doc_unk, L"domComplete"); return S_OK; default: ok(0, "unexpected command %ld\n", nCmdID);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlevent.c | 2 +- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 43 +++++++++++++++++++++++++------ dlls/mshtml/omnavigator.c | 8 +++--- dlls/mshtml/tests/documentmode.js | 6 ++++- 5 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 01a385130b1..fec280d9a70 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -117,7 +117,7 @@ typedef struct { /* Keep these sorted case sensitively */ static const event_info_t event_info[] = { {L"DOMContentLoaded", EVENT_TYPE_EVENT, 0, - EVENT_DEFAULTLISTENER | EVENT_BUBBLES | EVENT_CANCELABLE}, + EVENT_BUBBLES | EVENT_CANCELABLE}, {L"abort", EVENT_TYPE_EVENT, DISPID_EVMETH_ONABORT, EVENT_BIND_TO_TARGET}, {L"animationend", EVENT_TYPE_EVENT, DISPID_EVPROP_ONANIMATIONEND, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index bbf79f8ed4b..b8adbf359b6 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -606,6 +606,8 @@ struct HTMLInnerWindow { ULONGLONG response_end_time; ULONGLONG dom_interactive_time; ULONGLONG dom_complete_time; + ULONGLONG dom_content_loaded_event_start_time; + ULONGLONG dom_content_loaded_event_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 6d29f26394d..606b04c3e50 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -56,6 +56,7 @@ typedef struct { static nsresult NSAPI handle_blur(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_focus(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_keypress(nsIDOMEventListener*,nsIDOMEvent*); +static nsresult NSAPI handle_dom_content_loaded(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_pageshow(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_pagehide(nsIDOMEventListener*,nsIDOMEvent*); static nsresult NSAPI handle_load(nsIDOMEventListener*,nsIDOMEvent*); @@ -72,14 +73,15 @@ static const struct { enum doc_event_listener_flags flags; nsIDOMEventListenerVtbl vtbl; } doc_event_listeners[] = { - { EVENTID_BLUR, 0, EVENTLISTENER_VTBL(handle_blur) }, - { EVENTID_FOCUS, 0, EVENTLISTENER_VTBL(handle_focus) }, - { EVENTID_KEYPRESS, BUBBLES, EVENTLISTENER_VTBL(handle_keypress) }, - { EVENTID_PAGESHOW, OVERRIDE, EVENTLISTENER_VTBL(handle_pageshow), }, - { EVENTID_PAGEHIDE, OVERRIDE, EVENTLISTENER_VTBL(handle_pagehide), }, - { EVENTID_LOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_load), }, - { EVENTID_BEFOREUNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_beforeunload), }, - { EVENTID_UNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_unload) }, + { EVENTID_BLUR, 0, EVENTLISTENER_VTBL(handle_blur) }, + { EVENTID_FOCUS, 0, EVENTLISTENER_VTBL(handle_focus) }, + { EVENTID_KEYPRESS, BUBBLES, EVENTLISTENER_VTBL(handle_keypress) }, + { EVENTID_DOMCONTENTLOADED, OVERRIDE, EVENTLISTENER_VTBL(handle_dom_content_loaded) }, + { EVENTID_PAGESHOW, OVERRIDE, EVENTLISTENER_VTBL(handle_pageshow) }, + { EVENTID_PAGEHIDE, OVERRIDE, EVENTLISTENER_VTBL(handle_pagehide) }, + { EVENTID_LOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_load) }, + { EVENTID_BEFOREUNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_beforeunload) }, + { EVENTID_UNLOAD, OVERRIDE, EVENTLISTENER_VTBL(handle_unload) }, };
struct nsDocumentEventListener { @@ -216,6 +218,31 @@ static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface, return NS_OK; }
+static nsresult NSAPI handle_dom_content_loaded(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) +{ + nsEventListener *This = impl_from_nsIDOMEventListener(iface); + HTMLDocumentNode *doc = This->This->doc; + DOMEvent *event; + HRESULT hres; + + if(!doc) + return NS_OK; + + if(doc->window) + doc->window->dom_content_loaded_event_start_time = get_time_stamp(); + + hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&doc->node.event_target.dispex), &event); + if(SUCCEEDED(hres)) { + dispatch_event(&doc->node.event_target, event); + IDOMEvent_Release(&event->IDOMEvent_iface); + } + + if(doc->window) + doc->window->dom_content_loaded_event_end_time = get_time_stamp(); + + return NS_OK; +} + static nsresult NSAPI handle_pageshow(nsIDOMEventListener *iface, nsIDOMEvent *nsevent) { nsEventListener *This = impl_from_nsIDOMEventListener(iface); diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index bf4e56eaf24..43ccd08c1ef 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1774,9 +1774,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventStart(IHTML { 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->window->dom_content_loaded_event_start_time; return S_OK; }
@@ -1784,9 +1784,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventEnd(IHTMLPe { 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->window->dom_content_loaded_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 72311d5903b..237ac224cbb 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -31,6 +31,8 @@ ok(performance.timing.responseEnd >= performance.timing.responseStart, "response ok(performance.timing.domLoading >= performance.timing.responseEnd, "domLoading < responseEnd"); ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.domComplete === 0, "domComplete != 0"); +ok(performance.timing.domContentLoadedEventStart === 0, "domContentLoadedEventStart != 0"); +ok(performance.timing.domContentLoadedEventEnd === 0, "domContentLoadedEventEnd != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -79,7 +81,9 @@ if(window.addEventListener) {
sync_test("performance timing", function() { ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading"); - ok(performance.timing.domComplete >= performance.timing.domInteractive, "domComplete < domInteractive"); + ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive"); + ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart"); + ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd"); });
sync_test("page transition events", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
connect_scripts at the top of the function already uses the window unconditionally, so if it was NULL it would crash there anyway. --- dlls/mshtml/nsevents.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 606b04c3e50..f2f8910d5d6 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -373,14 +373,10 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event WARN("no dom_document\n"); }
- if(doc->window) { - hres = create_event_from_nsevent(event, dispex_compat_mode(&doc->node.event_target.dispex), &load_event); - if(SUCCEEDED(hres)) { - dispatch_event(&doc->window->event_target, load_event); - IDOMEvent_Release(&load_event->IDOMEvent_iface); - } - }else { - WARN("no window\n"); + hres = create_event_from_nsevent(event, dispex_compat_mode(&doc->node.event_target.dispex), &load_event); + if(SUCCEEDED(hres)) { + dispatch_event(&doc->window->event_target, load_event); + IDOMEvent_Release(&load_event->IDOMEvent_iface); }
IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsevents.c | 4 ++++ dlls/mshtml/omnavigator.c | 8 ++++---- dlls/mshtml/tests/documentmode.js | 5 +++++ 4 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b8adbf359b6..76ddb80f317 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -608,6 +608,8 @@ struct HTMLInnerWindow { ULONGLONG dom_complete_time; ULONGLONG dom_content_loaded_event_start_time; ULONGLONG dom_content_loaded_event_end_time; + ULONGLONG load_event_start_time; + ULONGLONG load_event_end_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index f2f8910d5d6..d63fcde6feb 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -363,6 +363,8 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event IDocObjectService_FireDocumentComplete(doc_obj->doc_object_service, &doc->outer_window->base.IHTMLWindow2_iface, 0);
+ doc->window->load_event_start_time = get_time_stamp(); + if(doc->dom_document) { hres = create_document_event(doc, EVENTID_LOAD, &load_event); if(SUCCEEDED(hres)) { @@ -379,6 +381,8 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event IDOMEvent_Release(&load_event->IDOMEvent_iface); }
+ doc->window->load_event_end_time = get_time_stamp(); + IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface); return NS_OK; } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 43ccd08c1ef..db53958f258 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1804,9 +1804,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventStart(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->window->load_event_start_time; return S_OK; }
@@ -1814,9 +1814,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventEnd(IHTMLPerformanceTim { 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->window->load_event_end_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 237ac224cbb..30d4a790261 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -33,6 +33,8 @@ ok(performance.timing.domInteractive === 0, "domInteractive != 0"); ok(performance.timing.domComplete === 0, "domComplete != 0"); ok(performance.timing.domContentLoadedEventStart === 0, "domContentLoadedEventStart != 0"); ok(performance.timing.domContentLoadedEventEnd === 0, "domContentLoadedEventEnd != 0"); +ok(performance.timing.loadEventStart === 0, "loadEventStart != 0"); +ok(performance.timing.loadEventEnd === 0, "loadEventEnd != 0"); ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); @@ -59,6 +61,7 @@ if(window.addEventListener) { ok(r === "[object PageTransitionEvent]", "pageshow toString = " + r); ok("persisted" in e, "'persisted' not in pageshow event"); ok(document.readyState === "complete", "pageshow readyState = " + document.readyState); + ok(performance.timing.loadEventEnd > 0, "loadEventEnd <= 0 in pageshow handler"); }, true);
window.addEventListener("pagehide", function(e) { @@ -84,6 +87,8 @@ sync_test("performance timing", function() { ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive"); ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart"); ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd"); + ok(performance.timing.loadEventStart >= performance.timing.domComplete, "loadEventStart < domComplete"); + ok(performance.timing.loadEventEnd >= performance.timing.loadEventStart, "loadEventEnd < loadEventStart"); });
sync_test("page transition events", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/omnavigator.c | 6 ++---- dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/view.c | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 76ddb80f317..5fe503a730d 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -610,6 +610,7 @@ struct HTMLInnerWindow { ULONGLONG dom_content_loaded_event_end_time; ULONGLONG load_event_start_time; ULONGLONG load_event_end_time; + ULONGLONG first_paint_time; };
#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1)) diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index db53958f258..fd35af28f44 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1593,8 +1593,6 @@ static HRESULT WINAPI HTMLPerformanceTiming_Invoke(IHTMLPerformanceTiming *iface pDispParams, pVarResult, pExcepInfo, puArgErr); }
-#define TIMING_FAKE_TIMESTAMP 0xdeadbeef - static ULONGLONG get_fetch_time(HTMLPerformanceTiming *This) { /* If there's no prior doc unloaded and no redirects, fetch time == navigationStart time */ @@ -1824,9 +1822,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_msFirstPaint(IHTMLPerformanceTim { 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->window->first_paint_time; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 30d4a790261..157a7337c04 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -39,6 +39,7 @@ ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0"); ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0"); ok(performance.timing.redirectStart === 0, "redirectStart != 0"); ok(performance.timing.redirectEnd === 0, "redirectEnd != 0"); +ok(performance.timing.msFirstPaint === 0, "msFirstPaint != 0");
var pageshow_fired = false, pagehide_fired = false; document.doc_unload_events_called = false; diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 063f7afab9d..deb640fd8e3 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -50,6 +50,9 @@ static void paint_document(HTMLDocumentObj *This) RECT rect; HDC hdc;
+ if(This->window && This->window->base.inner_window && !This->window->base.inner_window->first_paint_time) + This->window->base.inner_window->first_paint_time = get_time_stamp(); + GetClientRect(This->hwnd, &rect);
hdc = BeginPaint(This->hwnd, &ps);
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=126503
Your paranoid android.
=== w10pro64_en_AE_u8 (64 bit report) ===
mshtml: htmldoc.c:351: Test failed: expected Exec_SETTITLE htmldoc.c:3022: Test failed: unexpected call Exec_SETTITLE
=== w10pro64_zh_CN (64 bit report) ===
mshtml: htmldoc.c:351: Test failed: expected Exec_SETTITLE htmldoc.c:3022: Test failed: unexpected call Exec_SETTITLE
=== debian11b (64 bit WoW report) ===
mshtml: htmllocation: Timeout
On Sat Nov 19 19:56:44 2022 +0000, **** wrote:
Marvin replied on the mailing list:
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=126479 Your paranoid android. === w10pro64_ar (64 bit report) === mshtml: htmldoc.c:351: Test failed: expected Exec_SETTITLE htmldoc.c:3019: Test failed: unexpected call Exec_SETTITLE === w10pro64_ja (64 bit report) === mshtml: htmldoc.c:1121: Test failed: L"domInteractive" is 0 === debian11 (32 bit report) === d3d9: stateblock: Timeout visual: Timeout d3dcompiler_43: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout d3dcompiler_46: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout d3dcompiler_47: asm: Timeout blob: Timeout hlsl_d3d11: Timeout hlsl_d3d9: Timeout reflection: Timeout d3drm: d3drm: Timeout vector: Timeout d3dx10_34: d3dx10: Timeout d3dx10_35: d3dx10: Timeout d3dx10_36: d3dx10: Timeout d3dx10_37: d3dx10: Timeout d3dx10_38: d3dx10: Timeout d3dx10_39: d3dx10: Timeout d3dx10_40: d3dx10: Timeout d3dx10_41: d3dx10: Timeout d3dx10_42: d3dx10: Timeout d3dx10_43: d3dx10: Timeout d3dx11_42: d3dx11: Timeout d3dx11_43: d3dx11: Timeout d3dx9_36: asm: Timeout core: Timeout effect: Timeout line: Timeout Report validation errors: math: Timeout === debian11 (build log) === WineRunWineTest.pl:error: The task timed out
Well I changed the tests a bit, but it still didn't solve it, although it's less hacky. So I'll just skip this test in this particular case here.
Also I check for NULL window to prevent crash since it can be detached. (unlikely to happen in practice but…)
Jacek Caban (@jacek) commented about dlls/mshtml/tests/htmldoc.c:
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 || is_lang_english())
The difference is most likely not related to the language, so this check doesn't make sense.
Jacek Caban (@jacek) commented about dlls/mshtml/mshtml_private.h:
struct list bindings;
};
+#define NO_PERFORMANCE_OBJ ((IHTMLPerformance*)IntToPtr(-1))
You could just use NULL.
Jacek Caban (@jacek) commented about dlls/mshtml/omnavigator.c:
if(!This->timing) { HTMLPerformanceTiming *timing;
if(!This->window)
return E_UNEXPECTED;
timing = heap_alloc_zero(sizeof(*timing)); if(!timing) return E_OUTOFMEMORY; timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; timing->ref = 1;
timing->window = This->window;
IHTMLWindow2_AddRef(&timing->window->base.IHTMLWindow2_iface);
This is crating a circular reference.
On Mon Nov 21 13:42:43 2022 +0000, Jacek Caban wrote:
You could just use NULL.
We can't, because we can store an arbitrary variant in its place, and we still have to keep link to the obj in that case (so we can detach it, when needed). NULL would obtain another, new, performance object.
The previous code used `performance_initialized` for this, but I wanted to condense the fields for it, otherwise we'll have 3 fields just for this which seems less than ideal, so I used a sentinel value (-1) for the obj itself.
On Mon Nov 21 14:45:36 2022 +0000, Gabriel Ivăncescu wrote:
We can't, because we can store an arbitrary variant in its place, and we still have to keep link to the obj in that case (so we can detach it, when needed). NULL would obtain another, new, performance object. The previous code used `performance_initialized` for this, but I wanted to condense the fields for it, otherwise we'll have 3 fields just for this which seems less than ideal, so I used a sentinel value (-1) for the obj itself.
You could, for example, have separated reference to performance_obj instead of sharing it with VARIANT, so it's kept alive until window is destroyed even if performance property is changed. Depending on how you solve circular reference problem, you may need it anyway.
On Mon Nov 21 15:47:02 2022 +0000, Jacek Caban wrote:
You could, for example, have separated reference to performance_obj instead of sharing it with VARIANT, so it's kept alive until window is destroyed even if performance property is changed. Depending on how you solve circular reference problem, you may need it anyway.
Yeah, I went with a different approach right now, without storing any refs to the window or doing any detach shenanigans. Create the performance timing on inner window creation, and always keep it alive from the window, so the window just sets the props on it directly.
Only thing "special" is that the dispex is not initialized right away, but only when the performance obj is obtained, due to compat mode having to be deferred (can't do it at window creation).
But I think this is far simpler than having to do two detach stuff and more complicated logic, it's also a lot less code in each getter (no check for NULL window), and works even if the window is "detached" while timing is still up.