-- v2: mshtml: Implement Cycle Collection for XMLHttpRequest. mshtml: Implement Cycle Collection for HTMLPerformanceTiming. mshtml: Move PerformanceTiming related fields to the window. mshtml: Move HTMLPerformanceNavigation related fields to the window. mshtml: Implement Cycle Collection for inner windows. mshtml: Get rid of NULL checks for the dispex vtbl. mshtml: Implement Cycle Collection for outer windows. mshtml: Implement Cycle Collection for HTMLLocation. mshtml: Separate the HTMLLocation from the outer window.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmllocation.c | 50 +++++++++++++++++++++++++----------- dlls/mshtml/htmlwindow.c | 32 +++++++++++++++-------- dlls/mshtml/mshtml_private.h | 8 ++++-- 3 files changed, 62 insertions(+), 28 deletions(-)
diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 02f503969db..35446c57bd3 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -36,19 +36,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
-static inline HTMLOuterWindow *get_window(HTMLLocation *This) -{ - return CONTAINING_RECORD(This, HTMLOuterWindow, location); -} - static IUri *get_uri(HTMLLocation *This) { - return get_window(This)->uri; + return This->window->uri; }
static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url) { - const WCHAR *doc_url = get_window(This)->url ? get_window(This)->url : L"about:blank"; + const WCHAR *doc_url = This->window->url ? This->window->url : L"about:blank";
if(!InternetCrackUrlW(doc_url, 0, 0, url)) { FIXME("InternetCrackUrlW failed: 0x%08lx\n", GetLastError()); @@ -93,13 +88,27 @@ static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID r static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - return IHTMLWindow2_AddRef(&get_window(This)->base.IHTMLWindow2_iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; }
static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - return IHTMLWindow2_Release(&get_window(This)->base.IHTMLWindow2_iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); + release_dispex(&This->dispex); + free(This); + } + + return ref; }
static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo) @@ -139,7 +148,7 @@ static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
TRACE("(%p)->(%s)\n", This, debugstr_w(v));
- return navigate_url(get_window(This), v, get_uri(This), BINDING_NAVIGATED); + return navigate_url(This->window, v, get_uri(This), BINDING_NAVIGATED); }
static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p) @@ -500,7 +509,7 @@ static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v) memcpy(hash + 1, v, size - sizeof(WCHAR)); }
- hres = navigate_url(get_window(This), hash, get_uri(This), BINDING_NAVIGATED); + hres = navigate_url(This->window, hash, get_uri(This), BINDING_NAVIGATED);
if(hash != v) free(hash); @@ -544,12 +553,12 @@ static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL fla TRACE("(%p)->(%x)\n", This, flag);
/* reload is supposed to fail if called from a script with different origin, but IE doesn't care */ - if(!is_main_content_window(get_window(This))) { + if(!is_main_content_window(This->window)) { FIXME("Unsupported on iframe\n"); return E_NOTIMPL; }
- return reload_page(get_window(This)); + return reload_page(This->window); }
static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr) @@ -558,7 +567,7 @@ static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
- return navigate_url(get_window(This), bstr, get_uri(This), BINDING_NAVIGATED | BINDING_REPLACE); + return navigate_url(This->window, bstr, get_uri(This), BINDING_NAVIGATED | BINDING_REPLACE); }
static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr) @@ -618,10 +627,21 @@ static dispex_static_data_t HTMLLocation_dispex = { HTMLLocation_iface_tids };
-void HTMLLocation_Init(HTMLLocation *location) +HRESULT create_location(HTMLOuterWindow *window, HTMLLocation **ret) { + HTMLLocation *location; + + if(!(location = calloc(1, sizeof(*location)))) + return E_OUTOFMEMORY; + location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl; + location->ref = 1; + location->window = window; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
init_dispatch(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex, COMPAT_MODE_QUIRKS); + + *ret = location; + return S_OK; } diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index c1a258651cf..7c40ca83188 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -62,13 +62,17 @@ HTMLOuterWindow *mozwindow_to_window(const mozIDOMWindowProxy *mozwindow) return entry ? WINE_RB_ENTRY_VALUE(entry, HTMLOuterWindow, entry) : NULL; }
-static void get_location(HTMLOuterWindow *This, HTMLLocation **ret) +static HRESULT get_location(HTMLOuterWindow *This, HTMLLocation **ret) { - if(!This->location.dispex.outer) - HTMLLocation_Init(&This->location); + if(!This->location) { + HRESULT hres = create_location(This, &This->location); + if(FAILED(hres)) + return hres; + }
- IHTMLLocation_AddRef(&This->location.IHTMLLocation_iface); - *ret = &This->location; + IHTMLLocation_AddRef(&This->location->IHTMLLocation_iface); + *ret = This->location; + return S_OK; }
void get_top_window(HTMLOuterWindow *window, HTMLOuterWindow **ret) @@ -122,8 +126,8 @@ static void detach_inner_window(HTMLInnerWindow *window) if(doc) detach_document_node(doc);
- if(outer_window && outer_window->location.dispex.outer) - dispex_props_unlink(&outer_window->location.dispex); + if(outer_window && outer_window->location) + dispex_props_unlink(&outer_window->location->dispex);
abort_window_bindings(window); remove_target_tasks(window->task_magic); @@ -283,8 +287,8 @@ static void release_outer_window(HTMLOuterWindow *This) if(This->base.inner_window) detach_inner_window(This->base.inner_window);
- if(This->location.dispex.outer) - release_dispex(&This->location.dispex); + if(This->location) + IHTMLLocation_Release(&This->location->IHTMLLocation_iface);
if(This->frame_element) This->frame_element->content_window = NULL; @@ -779,10 +783,14 @@ static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocatio { HTMLWindow *This = impl_from_IHTMLWindow2(iface); HTMLLocation *location; + HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
- get_location(This->outer_window, &location); + hres = get_location(This->outer_window, &location); + if(FAILED(hres)) + return hres; + *p = &location->IHTMLLocation_iface; return S_OK; } @@ -4080,7 +4088,9 @@ static HRESULT IHTMLWindow2_location_hook(DispatchEx *dispex, WORD flags, DISPPA
TRACE("forwarding to location.href\n");
- get_location(This->base.outer_window, &location); + hres = get_location(This->base.outer_window, &location); + if(FAILED(hres)) + return hres;
hres = IDispatchEx_InvokeEx(&location->dispex.IDispatchEx_iface, DISPID_VALUE, 0, flags, dp, res, ei, caller); IHTMLLocation_Release(&location->IHTMLLocation_iface); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 5d117d70e29..757bc0feb79 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -521,6 +521,10 @@ typedef struct { struct HTMLLocation { DispatchEx dispex; IHTMLLocation IHTMLLocation_iface; + + LONG ref; + + HTMLOuterWindow *window; };
typedef struct { @@ -599,7 +603,7 @@ struct HTMLOuterWindow { BOOL readystate_pending;
HTMLInnerWindow *pending_window; - HTMLLocation location; + HTMLLocation *location; IMoniker *mon; IUri *uri; IUri *uri_nofrag; @@ -1013,7 +1017,7 @@ void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**); HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**); HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,HTMLXMLHttpRequestFactory**); -void HTMLLocation_Init(HTMLLocation*); +HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(compat_mode_t,IOmNavigator**); HRESULT create_html_screen(compat_mode_t,IHTMLScreen**); HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmllocation.c | 49 ++++++++++++++++++++++++++++-------- dlls/mshtml/mshtml_private.h | 2 -- 2 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/dlls/mshtml/htmllocation.c b/dlls/mshtml/htmllocation.c index 35446c57bd3..5941c383db4 100644 --- a/dlls/mshtml/htmllocation.c +++ b/dlls/mshtml/htmllocation.c @@ -73,7 +73,7 @@ static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID r *ppv = NULL; FIXME("(%p)->(IID_IMarshal %p)\n", This, ppv); return E_NOINTERFACE; - }else if(dispex_query_interface_no_cc(&This->dispex, riid, ppv)) { + }else if(dispex_query_interface(&This->dispex, riid, ppv)) { return *ppv ? S_OK : E_NOINTERFACE; }else { *ppv = NULL; @@ -88,7 +88,7 @@ static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID r static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - LONG ref = InterlockedIncrement(&This->ref); + LONG ref = dispex_ref_incr(&This->dispex);
TRACE("(%p) ref=%ld\n", This, ref);
@@ -98,16 +98,10 @@ static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface) static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface) { HTMLLocation *This = impl_from_IHTMLLocation(iface); - LONG ref = InterlockedDecrement(&This->ref); + LONG ref = dispex_ref_decr(&This->dispex);
TRACE("(%p) ref=%ld\n", This, ref);
- if(!ref) { - IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface); - release_dispex(&This->dispex); - free(This); - } - return ref; }
@@ -616,13 +610,47 @@ static const IHTMLLocationVtbl HTMLLocationVtbl = { HTMLLocation_toString };
+static inline HTMLLocation *impl_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLLocation, dispex); +} + +static void HTMLLocation_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + HTMLLocation *This = impl_from_DispatchEx(dispex); + if(This->window) + note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); +} + +static void HTMLLocation_unlink(DispatchEx *dispex) +{ + HTMLLocation *This = impl_from_DispatchEx(dispex); + if(This->window) { + HTMLOuterWindow *window = This->window; + This->window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + } +} + +static void HTMLLocation_destructor(DispatchEx *dispex) +{ + HTMLLocation *This = impl_from_DispatchEx(dispex); + free(This); +} + +static const dispex_static_data_vtbl_t HTMLLocation_dispex_vtbl = { + .destructor = HTMLLocation_destructor, + .traverse = HTMLLocation_traverse, + .unlink = HTMLLocation_unlink +}; + static const tid_t HTMLLocation_iface_tids[] = { IHTMLLocation_tid, 0 }; static dispex_static_data_t HTMLLocation_dispex = { "Location", - NULL, + &HTMLLocation_dispex_vtbl, DispHTMLLocation_tid, HTMLLocation_iface_tids }; @@ -635,7 +663,6 @@ HRESULT create_location(HTMLOuterWindow *window, HTMLLocation **ret) return E_OUTOFMEMORY;
location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl; - location->ref = 1; location->window = window; IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 757bc0feb79..05203c53897 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -522,8 +522,6 @@ struct HTMLLocation { DispatchEx dispex; IHTMLLocation IHTMLLocation_iface;
- LONG ref; - HTMLOuterWindow *window; };
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 129 ++++++++++++++++++++++++----------- dlls/mshtml/mshtml_private.h | 2 + dlls/mshtml/nsembed.c | 1 + 3 files changed, 93 insertions(+), 39 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 7c40ca83188..5619eb6e7c9 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -45,6 +45,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+static ExternalCycleCollectionParticipant outer_window_ccp; + static int window_map_compare(const void *key, const struct wine_rb_entry *entry) { HTMLOuterWindow *window = WINE_RB_ENTRY_VALUE(entry, HTMLOuterWindow, entry); @@ -255,62 +257,37 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri if(hres != S_FALSE) return hres;
- return EventTarget_QI_no_cc(&This->base.inner_window->event_target, riid, ppv); + if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) { + *ppv = &outer_window_ccp; + return S_OK; + }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) { + *ppv = &This->base.IHTMLWindow2_iface; + return S_OK; + }else { + return EventTarget_QI_no_cc(&This->base.inner_window->event_target, riid, ppv); + } }
static ULONG WINAPI outer_window_AddRef(IHTMLWindow2 *iface) { HTMLOuterWindow *This = HTMLOuterWindow_from_IHTMLWindow2(iface); - LONG ref = InterlockedIncrement(&This->base.ref); + LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->base.IHTMLWindow2_iface);
TRACE("(%p) ref=%ld\n", This, ref);
return ref; }
-static void release_outer_window(HTMLOuterWindow *This) -{ - if(This->browser) { - list_remove(&This->browser_entry); - This->browser = NULL; - } - - if(This->pending_window) { - abort_window_bindings(This->pending_window); - This->pending_window->base.outer_window = NULL; - IHTMLWindow2_Release(&This->pending_window->base.IHTMLWindow2_iface); - } - - remove_target_tasks(This->task_magic); - set_current_mon(This, NULL, 0); - set_current_uri(This, NULL); - if(This->base.inner_window) - detach_inner_window(This->base.inner_window); - - if(This->location) - IHTMLLocation_Release(&This->location->IHTMLLocation_iface); - - if(This->frame_element) - This->frame_element->content_window = NULL; - - if(This->nswindow) - nsIDOMWindow_Release(This->nswindow); - if(This->window_proxy) - mozIDOMWindowProxy_Release(This->window_proxy); - - wine_rb_remove(&window_map, &This->entry); - free(This); -} - static ULONG WINAPI outer_window_Release(IHTMLWindow2 *iface) { HTMLOuterWindow *This = HTMLOuterWindow_from_IHTMLWindow2(iface); - LONG ref = InterlockedDecrement(&This->base.ref); + LONG task_magic = This->task_magic; + LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->base.IHTMLWindow2_iface, &outer_window_ccp);
TRACE("(%p) ref=%ld\n", This, ref);
if(!ref) - release_outer_window(This); + remove_target_tasks(task_magic);
return ref; } @@ -4198,6 +4175,79 @@ static dispex_static_data_t HTMLWindow_dispex = { HTMLWindow_init_dispex_info };
+static nsresult NSAPI outer_window_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) +{ + HTMLOuterWindow *window = HTMLOuterWindow_from_IHTMLWindow2(p); + + describe_cc_node(&window->ccref, "OuterWindow", cb); + + if(window->pending_window) + note_cc_edge((nsISupports*)&window->pending_window->base.IHTMLWindow2_iface, "pending_window", cb); + if(window->base.inner_window) + note_cc_edge((nsISupports*)&window->base.inner_window->base.IHTMLWindow2_iface, "inner_window", cb); + if(window->location) + note_cc_edge((nsISupports*)&window->location->IHTMLLocation_iface, "location", cb); + if(window->nswindow) + note_cc_edge((nsISupports*)window->nswindow, "nswindow", cb); + if(window->window_proxy) + note_cc_edge((nsISupports*)window->window_proxy, "window_proxy", cb); + return NS_OK; +} + +static nsresult NSAPI outer_window_unlink(void *p) +{ + HTMLOuterWindow *window = HTMLOuterWindow_from_IHTMLWindow2(p); + + if(window->browser) { + list_remove(&window->browser_entry); + window->browser = NULL; + } + if(window->pending_window) { + HTMLInnerWindow *pending_window = window->pending_window; + abort_window_bindings(pending_window); + pending_window->base.outer_window = NULL; + window->pending_window = NULL; + IHTMLWindow2_Release(&pending_window->base.IHTMLWindow2_iface); + } + + set_current_mon(window, NULL, 0); + set_current_uri(window, NULL); + if(window->base.inner_window) + detach_inner_window(window->base.inner_window); + if(window->location) { + HTMLLocation *location = window->location; + window->location = NULL; + IHTMLLocation_Release(&location->IHTMLLocation_iface); + } + if(window->frame_element) { + window->frame_element->content_window = NULL; + window->frame_element = NULL; + } + unlink_ref(&window->nswindow); + if(window->window_proxy) { + unlink_ref(&window->window_proxy); + wine_rb_remove(&window_map, &window->entry); + } + return NS_OK; +} + +static void NSAPI outer_window_delete_cycle_collectable(void *p) +{ + HTMLOuterWindow *window = HTMLOuterWindow_from_IHTMLWindow2(p); + outer_window_unlink(p); + free(window); +} + +void init_window_cc(void) +{ + static const CCObjCallback ccp_callback = { + outer_window_traverse, + outer_window_unlink, + outer_window_delete_cycle_collectable + }; + ccp_init(&outer_window_ccp, &ccp_callback); +} + static void *alloc_window(size_t size) { HTMLWindow *window; @@ -4219,7 +4269,6 @@ static void *alloc_window(size_t size) window->IProvideMultipleClassInfo_iface.lpVtbl = &ProvideMultipleClassInfoVtbl; window->IWineHTMLWindowPrivate_iface.lpVtbl = &WineHTMLWindowPrivateVtbl; window->IWineHTMLWindowCompatPrivate_iface.lpVtbl = &WineHTMLWindowCompatPrivateVtbl; - window->ref = 1;
return window; } @@ -4248,6 +4297,7 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon, window->base.outer_window = outer_window; window->base.inner_window = window;
+ window->base.ref = 1; EventTarget_Init(&window->event_target, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex, COMPAT_MODE_NONE);
@@ -4278,6 +4328,7 @@ HRESULT create_outer_window(GeckoBrowser *browser, mozIDOMWindowProxy *mozwindow window->base.inner_window = NULL; window->browser = browser; list_add_head(&browser->outer_windows, &window->browser_entry); + ccref_init(&window->ccref, 1);
mozIDOMWindowProxy_AddRef(mozwindow); window->window_proxy = mozwindow; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 05203c53897..d19baffd820 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -586,6 +586,7 @@ struct HTMLWindow { struct HTMLOuterWindow { HTMLWindow base;
+ nsCycleCollectingAutoRefCnt ccref; LONG task_magic;
nsIDOMWindow *nswindow; @@ -1078,6 +1079,7 @@ void set_viewer_zoom(GeckoBrowser*,float); float get_viewer_zoom(GeckoBrowser*);
void init_dispex_cc(void); +void init_window_cc(void);
HRESULT nsuri_to_url(LPCWSTR,BOOL,BSTR*);
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index d2053235c03..1b31e4f7159 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -597,6 +597,7 @@ static BOOL init_xpcom(const PRUnichar *gre_path) }
init_dispex_cc(); + init_window_cc();
return TRUE; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 23 +++++++++++------------ dlls/mshtml/htmlevent.c | 10 +++++----- 2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 33e01e8a81c..24c6be82f3d 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -639,7 +639,7 @@ static inline dispex_dynamic_data_t *get_dynamic_data(DispatchEx *This) if(!This->dynamic_data) return NULL;
- if(This->info->desc->vtbl && This->info->desc->vtbl->populate_props) + if(This->info->desc->vtbl->populate_props) This->info->desc->vtbl->populate_props(This);
return This->dynamic_data; @@ -736,7 +736,7 @@ static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS { HRESULT hres;
- if(This->info->desc->vtbl && This->info->desc->vtbl->value) + if(This->info->desc->vtbl->value) return This->info->desc->vtbl->value(This, lcid, flags, params, res, ei, caller);
switch(flags) { @@ -1054,7 +1054,7 @@ static HRESULT get_builtin_id(DispatchEx *This, BSTR name, DWORD grfdex, DISPID min = n+1; }
- if(This->info->desc->vtbl && This->info->desc->vtbl->get_dispid) { + if(This->info->desc->vtbl->get_dispid) { HRESULT hres;
hres = This->info->desc->vtbl->get_dispid(This, name, grfdex, ret); @@ -1706,7 +1706,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
switch(get_dispid_type(id)) { case DISPEXPROP_CUSTOM: - if(!This->info->desc->vtbl || !This->info->desc->vtbl->invoke) + if(!This->info->desc->vtbl->invoke) return DISP_E_MEMBERNOTFOUND; return This->info->desc->vtbl->invoke(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
@@ -1759,7 +1759,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc case DISPEXPROP_BUILTIN: if(wFlags == DISPATCH_CONSTRUCT) { if(id == DISPID_VALUE) { - if(This->info->desc->vtbl && This->info->desc->vtbl->value) { + if(This->info->desc->vtbl->value) { return This->info->desc->vtbl->value(This, lcid, wFlags, pdp, pvarRes, pei, pspCaller); } FIXME("DISPATCH_CONSTRUCT flag but missing value function\n"); @@ -1801,7 +1801,7 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID
TRACE("(%p)->(%lx)\n", This, id);
- if(is_custom_dispid(id) && This->info->desc->vtbl && This->info->desc->vtbl->delete) + if(is_custom_dispid(id) && This->info->desc->vtbl->delete) return This->info->desc->vtbl->delete(This, id);
if(dispex_compat_mode(This) < COMPAT_MODE_IE8) { @@ -1844,7 +1844,7 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS return E_OUTOFMEMORY;
if(is_custom_dispid(id)) { - if(This->info->desc->vtbl && This->info->desc->vtbl->get_name) + if(This->info->desc->vtbl->get_name) return This->info->desc->vtbl->get_name(This, id, pbstrName); return DISP_E_MEMBERNOTFOUND; } @@ -1928,7 +1928,7 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, id = DISPID_STARTENUM; }
- if(This->info->desc->vtbl && This->info->desc->vtbl->next_dispid) { + if(This->info->desc->vtbl->next_dispid) { hres = This->info->desc->vtbl->next_dispid(This, id, pid); if(hres != S_FALSE) return hres; @@ -2107,7 +2107,7 @@ void release_dispex(DispatchEx *This) { dynamic_prop_t *prop;
- if(This->info->desc->vtbl && This->info->desc->vtbl->unlink) + if(This->info->desc->vtbl->unlink) This->info->desc->vtbl->unlink(This);
if(!This->dynamic_data) @@ -2137,8 +2137,7 @@ void release_dispex(DispatchEx *This) free(This->dynamic_data);
destructor: - if(This->info->desc->vtbl) - This->info->desc->vtbl->destructor(This); + This->info->desc->vtbl->destructor(This); }
void init_dispatch(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *data, compat_mode_t compat_mode) @@ -2150,7 +2149,7 @@ void init_dispatch(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *da dispex->dynamic_data = NULL; ccref_init(&dispex->ccref, 1);
- if(data->vtbl && data->vtbl->get_compat_mode) { + if(data->vtbl->get_compat_mode) { /* delayed init */ if(!data->delayed_init_info) { EnterCriticalSection(&cs_dispex_static_data); diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 13fa4e5b505..f38998f0d20 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -3730,7 +3730,7 @@ static void call_event_handlers(EventTarget *event_target, DOMEvent *event, disp free(listeners);
if(event->phase != DEP_CAPTURING_PHASE && event_info[event->event_id].dispid - && (vtbl = dispex_get_vtbl(&event_target->dispex)) && vtbl->get_cp_container) + && (vtbl = dispex_get_vtbl(&event_target->dispex))->get_cp_container) cp_container = vtbl->get_cp_container(&event_target->dispex); if(cp_container) { if(cp_container->cps) { @@ -3823,7 +3823,7 @@ static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event,
target_chain[chain_cnt++] = iter;
- if(!(vtbl = dispex_get_vtbl(&iter->dispex)) || !vtbl->get_parent_event_target) + if(!(vtbl = dispex_get_vtbl(&iter->dispex))->get_parent_event_target) break; iter = vtbl->get_parent_event_target(&iter->dispex); } while(iter); @@ -3835,7 +3835,7 @@ static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event, }
target_vtbl = dispex_get_vtbl(&event_target->dispex); - if(target_vtbl && target_vtbl->set_current_event) + if(target_vtbl->set_current_event) prev_event = target_vtbl->set_current_event(&event_target->dispex, event->event_obj);
if(event->target) @@ -3862,7 +3862,7 @@ static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event, if(r) *r = variant_bool(!event->prevent_default);
- if(target_vtbl && target_vtbl->set_current_event) { + if(target_vtbl->set_current_event) { IHTMLEventObj *prev = target_vtbl->set_current_event(&event_target->dispex, prev_event); if(prev) IHTMLEventObj_Release(prev); @@ -3875,7 +3875,7 @@ static HRESULT dispatch_event_object(EventTarget *event_target, DOMEvent *event, BOOL prevent_default = event->prevent_default; for(i = 0; !prevent_default && i < chain_cnt; i++) { vtbl = dispex_get_vtbl(&target_chain[i]->dispex); - if(!vtbl || !vtbl->handle_event_default) + if(!vtbl->handle_event_default) continue; hres = vtbl->handle_event_default(&event_target->dispex, event->event_id, event->nsevent, &prevent_default);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 19 ++++++++++++- dlls/mshtml/htmlwindow.c | 52 ++++++++++++++++++++++++++++++------ dlls/mshtml/mshtml_private.h | 13 +++------ 3 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 24c6be82f3d..820f72ad9e0 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define MAX_ARGS 16
-ExternalCycleCollectionParticipant dispex_ccp; +static ExternalCycleCollectionParticipant dispex_ccp;
static CRITICAL_SECTION cs_dispex_static_data; static CRITICAL_SECTION_DEBUG cs_dispex_static_data_dbg = @@ -2016,6 +2016,23 @@ BOOL dispex_query_interface_no_cc(DispatchEx *This, REFIID riid, void **ppv) return TRUE; }
+LONG dispex_ref_decr(DispatchEx *dispex) +{ + BOOL has_task_magic = FALSE; + LONG task_magic, ref; + + if(dispex->info->desc->vtbl->get_task_magic) { + task_magic = dispex->info->desc->vtbl->get_task_magic(dispex); + has_task_magic = TRUE; + } + + ref = ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp); + if(!ref && has_task_magic) + remove_target_tasks(task_magic); + + return ref; +} + static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) { DispatchEx *This = impl_from_IDispatchEx(p); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 5619eb6e7c9..68593a1ac5c 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -220,13 +220,13 @@ static HRESULT WINAPI HTMLWindow2_QueryInterface(IHTMLWindow2 *iface, REFIID rii if(hres != S_FALSE) return hres;
- return EventTarget_QI_no_cc(&This->event_target, riid, ppv); + return EventTarget_QI(&This->event_target, riid, ppv); }
static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface) { HTMLInnerWindow *This = HTMLInnerWindow_from_IHTMLWindow2(iface); - LONG ref = InterlockedIncrement(&This->base.ref); + LONG ref = dispex_ref_incr(&This->event_target.dispex);
TRACE("(%p) ref=%ld\n", This, ref);
@@ -236,13 +236,10 @@ static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface) static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface) { HTMLInnerWindow *This = HTMLInnerWindow_from_IHTMLWindow2(iface); - LONG ref = InterlockedDecrement(&This->base.ref); + LONG ref = dispex_ref_decr(&This->event_target.dispex);
TRACE("(%p) ref=%ld\n", This, ref);
- if(!ref) - release_dispex(&This->event_target.dispex); - return ref; }
@@ -264,7 +261,7 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri *ppv = &This->base.IHTMLWindow2_iface; return S_OK; }else { - return EventTarget_QI_no_cc(&This->base.inner_window->event_target, riid, ppv); + return EventTarget_QI(&This->base.inner_window->event_target, riid, ppv); } }
@@ -3827,6 +3824,38 @@ static inline HTMLInnerWindow *impl_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLInnerWindow, event_target.dispex); }
+static void HTMLWindow_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + HTMLInnerWindow *This = impl_from_DispatchEx(dispex); + HTMLOuterWindow *child; + + LIST_FOR_EACH_ENTRY(child, &This->children, HTMLOuterWindow, sibling_entry) + note_cc_edge((nsISupports*)&child->base.IHTMLWindow2_iface, "child", cb); + if(This->doc) + note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "doc", cb); + if(This->console) + note_cc_edge((nsISupports*)This->console, "console", cb); + if(This->image_factory) + note_cc_edge((nsISupports*)&This->image_factory->IHTMLImageElementFactory_iface, "image_factory", cb); + if(This->option_factory) + note_cc_edge((nsISupports*)&This->option_factory->IHTMLOptionElementFactory_iface, "option_factory", cb); + if(This->xhr_factory) + note_cc_edge((nsISupports*)&This->xhr_factory->IHTMLXMLHttpRequestFactory_iface, "xhr_factory", cb); + if(This->mutation_observer_ctor) + note_cc_edge((nsISupports*)This->mutation_observer_ctor, "mutation_observer_ctor", cb); + if(This->screen) + note_cc_edge((nsISupports*)This->screen, "screen", cb); + if(This->history) + note_cc_edge((nsISupports*)&This->history->IOmHistory_iface, "history", cb); + if(This->navigator) + note_cc_edge((nsISupports*)This->navigator, "navigator", cb); + if(This->session_storage) + note_cc_edge((nsISupports*)This->session_storage, "session_storage", cb); + if(This->local_storage) + note_cc_edge((nsISupports*)This->local_storage, "local_storage", cb); + traverse_variant(&This->performance, "performance", cb); +} + static void HTMLWindow_unlink(DispatchEx *dispex) { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); @@ -3905,6 +3934,12 @@ static void HTMLWindow_destructor(DispatchEx *dispex) free(This); }
+static LONG HTMLWindow_get_task_magic(DispatchEx *dispex) +{ + HTMLInnerWindow *This = impl_from_DispatchEx(dispex); + return This->task_magic; +} + static HRESULT HTMLWindow_get_name(DispatchEx *dispex, DISPID id, BSTR *name) { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); @@ -4151,7 +4186,9 @@ static IHTMLEventObj *HTMLWindow_set_current_event(DispatchEx *dispex, IHTMLEven static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { { .destructor = HTMLWindow_destructor, + .traverse = HTMLWindow_traverse, .unlink = HTMLWindow_unlink, + .get_task_magic = HTMLWindow_get_task_magic, .get_name = HTMLWindow_get_name, .invoke = HTMLWindow_invoke, .next_dispid = HTMLWindow_next_dispid, @@ -4297,7 +4334,6 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon, window->base.outer_window = outer_window; window->base.inner_window = window;
- window->base.ref = 1; EventTarget_Init(&window->event_target, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex, COMPAT_MODE_NONE);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d19baffd820..3432bf5a2b1 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -358,6 +358,9 @@ typedef struct { void (*traverse)(DispatchEx*,nsCycleCollectionTraversalCallback*); void (*unlink)(DispatchEx*);
+ /* Only used by objects that have a task_magic */ + LONG (*get_task_magic)(DispatchEx*); + /* Called when the object wants to handle DISPID_VALUE invocations */ HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
@@ -427,17 +430,11 @@ extern void (__cdecl *ccp_init)(ExternalCycleCollectionParticipant*,const CCObjC extern void (__cdecl *describe_cc_node)(nsCycleCollectingAutoRefCnt*,const char*,nsCycleCollectionTraversalCallback*); extern void (__cdecl *note_cc_edge)(nsISupports*,const char*,nsCycleCollectionTraversalCallback*);
-extern ExternalCycleCollectionParticipant dispex_ccp; - static inline LONG dispex_ref_incr(DispatchEx *dispex) { return ccref_incr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface); } - -static inline LONG dispex_ref_decr(DispatchEx *dispex) -{ - return ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp); -} +extern LONG dispex_ref_decr(DispatchEx*);
void init_dispatch(DispatchEx*,IUnknown*,dispex_static_data_t*,compat_mode_t); void release_dispex(DispatchEx*); @@ -577,8 +574,6 @@ struct HTMLWindow { IWineHTMLWindowPrivate IWineHTMLWindowPrivate_iface; IWineHTMLWindowCompatPrivate IWineHTMLWindowCompatPrivate_iface;
- LONG ref; - HTMLInnerWindow *inner_window; HTMLOuterWindow *outer_window; };
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 6 +++--- dlls/mshtml/navigate.c | 6 +++--- dlls/mshtml/omnavigator.c | 30 +++++++++++++++++++----------- 3 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 3432bf5a2b1..7b8b514316e 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -535,9 +535,6 @@ typedef struct {
LONG ref;
- ULONG navigation_type; - ULONG redirect_count; - ULONGLONG navigation_start_time; ULONGLONG unload_event_start_time; ULONGLONG unload_event_end_time; @@ -647,6 +644,9 @@ struct HTMLInnerWindow { IDispatch *mutation_observer_ctor; nsChannelBSC *bscallback; struct list bindings; + + ULONG navigation_type; + ULONG redirect_count; };
typedef enum { diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index 3583fb91069..b13570f3ca3 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1351,9 +1351,9 @@ static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) DWORD flags = This->bsc.window->base.outer_window->load_flags;
if(flags & BINDING_FROMHIST) - This->bsc.window->performance_timing->navigation_type = 2; /* TYPE_BACK_FORWARD */ + This->bsc.window->navigation_type = 2; /* TYPE_BACK_FORWARD */ if(flags & BINDING_REFRESH) - This->bsc.window->performance_timing->navigation_type = 1; /* TYPE_RELOAD */ + This->bsc.window->navigation_type = 1; /* TYPE_RELOAD */
This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE; This->bsc.window->performance_timing->navigation_start_time = get_time_stamp(); @@ -1726,7 +1726,7 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t break; case BINDSTATUS_REDIRECTING: if(This->is_doc_channel) { - This->bsc.window->performance_timing->redirect_count++; + This->bsc.window->redirect_count++; if(!This->bsc.window->performance_timing->redirect_time) This->bsc.window->performance_timing->redirect_time = get_time_stamp(); } diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 9713e9c0b80..286d7ec7f73 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1977,7 +1977,7 @@ typedef struct { DispatchEx dispex; IHTMLPerformanceNavigation IHTMLPerformanceNavigation_iface;
- HTMLPerformanceTiming *timing; + HTMLInnerWindow *window; } HTMLPerformanceNavigation;
static inline HTMLPerformanceNavigation *impl_from_IHTMLPerformanceNavigation(IHTMLPerformanceNavigation *iface) @@ -2068,7 +2068,7 @@ static HRESULT WINAPI HTMLPerformanceNavigation_get_type(IHTMLPerformanceNavigat
TRACE("(%p)->(%p)\n", This, p);
- *p = This->timing->navigation_type; + *p = This->window->navigation_type; return S_OK; }
@@ -2078,7 +2078,7 @@ static HRESULT WINAPI HTMLPerformanceNavigation_get_redirectCount(IHTMLPerforman
TRACE("(%p)->(%p)\n", This, p);
- *p = This->timing->redirect_count; + *p = This->window->redirect_count; return S_OK; }
@@ -2120,17 +2120,17 @@ static inline HTMLPerformanceNavigation *HTMLPerformanceNavigation_from_Dispatch static void HTMLPerformanceNavigation_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) { HTMLPerformanceNavigation *This = HTMLPerformanceNavigation_from_DispatchEx(dispex); - if(This->timing) - note_cc_edge((nsISupports*)&This->timing->IHTMLPerformanceTiming_iface, "timing", cb); + if(This->window) + note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); }
static void HTMLPerformanceNavigation_unlink(DispatchEx *dispex) { HTMLPerformanceNavigation *This = HTMLPerformanceNavigation_from_DispatchEx(dispex); - if(This->timing) { - HTMLPerformanceTiming *timing = This->timing; - This->timing = NULL; - IHTMLPerformanceTiming_Release(&timing->IHTMLPerformanceTiming_iface); + if(This->window) { + HTMLInnerWindow *window = This->window; + This->window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); } }
@@ -2161,6 +2161,7 @@ typedef struct { DispatchEx dispex; IHTMLPerformance IHTMLPerformance_iface;
+ HTMLInnerWindow *window; IHTMLPerformanceNavigation *navigation; HTMLPerformanceTiming *timing; } HTMLPerformance; @@ -2262,8 +2263,8 @@ static HRESULT WINAPI HTMLPerformance_get_navigation(IHTMLPerformance *iface, return E_OUTOFMEMORY;
navigation->IHTMLPerformanceNavigation_iface.lpVtbl = &HTMLPerformanceNavigationVtbl; - navigation->timing = This->timing; - IHTMLPerformanceTiming_AddRef(&This->timing->IHTMLPerformanceTiming_iface); + navigation->window = This->window; + IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
init_dispatch(&navigation->dispex, (IUnknown*)&navigation->IHTMLPerformanceNavigation_iface, &HTMLPerformanceNavigation_dispex, dispex_compat_mode(&This->dispex)); @@ -2332,6 +2333,11 @@ static void HTMLPerformance_traverse(DispatchEx *dispex, nsCycleCollectionTraver static void HTMLPerformance_unlink(DispatchEx *dispex) { HTMLPerformance *This = HTMLPerformance_from_DispatchEx(dispex); + if(This->window) { + HTMLInnerWindow *window = This->window; + This->window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + } unlink_ref(&This->navigation); if(This->timing) { HTMLPerformanceTiming *timing = This->timing; @@ -2373,6 +2379,8 @@ HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) return E_OUTOFMEMORY;
performance->IHTMLPerformance_iface.lpVtbl = &HTMLPerformanceVtbl; + performance->window = window; + IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface);
init_dispatch(&performance->dispex, (IUnknown*)&performance->IHTMLPerformance_iface, &HTMLPerformance_dispex, compat_mode);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 8 -- dlls/mshtml/mshtml_private.h | 43 ++++------ dlls/mshtml/mutation.c | 2 +- dlls/mshtml/navigate.c | 20 ++--- dlls/mshtml/nsevents.c | 25 +++--- dlls/mshtml/omnavigator.c | 155 ++++++++++++++++++----------------- dlls/mshtml/view.c | 4 +- 7 files changed, 123 insertions(+), 134 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 68593a1ac5c..d7588e53d92 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3913,7 +3913,6 @@ static void HTMLWindow_unlink(DispatchEx *dispex) This->local_storage = NULL; IHTMLStorage_Release(local_storage); } - IHTMLPerformanceTiming_Release(&This->performance_timing->IHTMLPerformanceTiming_iface); unlink_variant(&This->performance); }
@@ -4313,19 +4312,12 @@ static void *alloc_window(size_t size) static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon, HTMLInnerWindow **ret) { HTMLInnerWindow *window; - HRESULT hres;
window = alloc_window(sizeof(HTMLInnerWindow)); if(!window) return E_OUTOFMEMORY; window->base.IHTMLWindow2_iface.lpVtbl = &HTMLWindow2Vtbl;
- hres = create_performance_timing(&window->performance_timing); - if(FAILED(hres)) { - free(window); - return hres; - } - list_init(&window->children); list_init(&window->script_hosts); list_init(&window->bindings); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 7b8b514316e..8f6375b9ee0 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -529,30 +529,6 @@ typedef struct { HTMLInnerWindow *window; } OmHistory;
-typedef struct { - DispatchEx dispex; - IHTMLPerformanceTiming IHTMLPerformanceTiming_iface; - - LONG ref; - - ULONGLONG navigation_start_time; - ULONGLONG unload_event_start_time; - ULONGLONG unload_event_end_time; - ULONGLONG redirect_time; - ULONGLONG dns_lookup_time; - ULONGLONG connect_time; - ULONGLONG request_time; - ULONGLONG response_start_time; - 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; - ULONGLONG load_event_start_time; - ULONGLONG load_event_end_time; - ULONGLONG first_paint_time; -} HTMLPerformanceTiming; - typedef struct nsChannelBSC nsChannelBSC;
struct HTMLWindow { @@ -628,7 +604,6 @@ struct HTMLInnerWindow {
BOOL performance_initialized; VARIANT performance; - HTMLPerformanceTiming *performance_timing;
unsigned blocking_depth; unsigned parser_callback_cnt; @@ -647,6 +622,23 @@ struct HTMLInnerWindow {
ULONG navigation_type; ULONG redirect_count; + + ULONGLONG navigation_start_time; + ULONGLONG unload_event_start_time; + ULONGLONG unload_event_end_time; + ULONGLONG redirect_time; + ULONGLONG dns_lookup_time; + ULONGLONG connect_time; + ULONGLONG request_time; + ULONGLONG response_start_time; + 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; + ULONGLONG load_event_start_time; + ULONGLONG load_event_end_time; + ULONGLONG first_paint_time; };
typedef enum { @@ -1015,7 +1007,6 @@ HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(compat_mode_t,IOmNavigator**); HRESULT create_html_screen(compat_mode_t,IHTMLScreen**); HRESULT create_performance(HTMLInnerWindow*,IHTMLPerformance**); -HRESULT create_performance_timing(HTMLPerformanceTiming**); HRESULT create_history(HTMLInnerWindow*,OmHistory**); HRESULT create_namespace_collection(compat_mode_t,IHTMLNamespaceCollection**); HRESULT create_dom_implementation(HTMLDocumentNode*,IHTMLDOMImplementation**); diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 1abb2d88839..7c93d27d829 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -313,7 +313,7 @@ static nsresult run_end_load(HTMLDocumentNode *This, nsISupports *arg1, nsISuppo bind_event_scripts(This);
if(This->window == window) { - window->performance_timing->dom_interactive_time = get_time_stamp(); + window->dom_interactive_time = get_time_stamp(); set_ready_state(This->outer_window, READYSTATE_INTERACTIVE); } IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index b13570f3ca3..8172abd8040 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1095,7 +1095,7 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) IWinInetHttpInfo *wininet_info;
if(This->is_doc_channel) - This->bsc.window->performance_timing->response_start_time = get_time_stamp(); + This->bsc.window->response_start_time = get_time_stamp();
This->response_processed = TRUE; if(This->bsc.binding) { @@ -1356,7 +1356,7 @@ static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) This->bsc.window->navigation_type = 1; /* TYPE_RELOAD */
This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE; - This->bsc.window->performance_timing->navigation_start_time = get_time_stamp(); + This->bsc.window->navigation_start_time = get_time_stamp(); }
return S_OK; @@ -1524,7 +1524,7 @@ static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
if(This->is_doc_channel && This->bsc.window) { - This->bsc.window->performance_timing->response_end_time = get_time_stamp(); + This->bsc.window->response_end_time = get_time_stamp(); if(result != E_ABORT) { if(FAILED(result)) handle_navigation_error(This, result); @@ -1727,21 +1727,21 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG progress, ULONG t case BINDSTATUS_REDIRECTING: if(This->is_doc_channel) { This->bsc.window->redirect_count++; - if(!This->bsc.window->performance_timing->redirect_time) - This->bsc.window->performance_timing->redirect_time = get_time_stamp(); + if(!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->performance_timing->dns_lookup_time) - This->bsc.window->performance_timing->dns_lookup_time = get_time_stamp(); + 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->performance_timing->connect_time = get_time_stamp(); + This->bsc.window->connect_time = get_time_stamp(); break; case BINDSTATUS_SENDINGREQUEST: if(This->is_doc_channel) - This->bsc.window->performance_timing->request_time = get_time_stamp(); + This->bsc.window->request_time = get_time_stamp(); break; case BINDSTATUS_BEGINDOWNLOADDATA: { IWinInetHttpInfo *http_info; @@ -1798,7 +1798,7 @@ static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code, HRESULT hres;
if(This->is_doc_channel) - This->bsc.window->performance_timing->response_start_time = get_time_stamp(); + This->bsc.window->response_start_time = get_time_stamp();
This->response_processed = TRUE; This->nschannel->response_status = response_code; diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 76a3f4ab4c6..78a54c83955 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -238,7 +238,7 @@ static nsresult handle_dom_content_loaded(HTMLDocumentNode *doc, nsIDOMEvent *ns HRESULT hres;
if(doc->window) - doc->window->performance_timing->dom_content_loaded_event_start_time = get_time_stamp(); + 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)) { @@ -247,7 +247,7 @@ static nsresult handle_dom_content_loaded(HTMLDocumentNode *doc, nsIDOMEvent *ns }
if(doc->window) - doc->window->performance_timing->dom_content_loaded_event_end_time = get_time_stamp(); + doc->window->dom_content_loaded_event_end_time = get_time_stamp();
return NS_OK; } @@ -345,7 +345,7 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event) if(doc_obj) handle_docobj_load(doc_obj);
- doc->window->performance_timing->dom_complete_time = get_time_stamp(); + doc->window->dom_complete_time = get_time_stamp(); set_ready_state(doc->outer_window, READYSTATE_COMPLETE);
if(doc_obj) { @@ -363,7 +363,7 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event) IUnknown_Release(doc_obj->outer_unk); }
- doc->window->performance_timing->load_event_start_time = get_time_stamp(); + doc->window->load_event_start_time = get_time_stamp();
if(doc->dom_document) { hres = create_document_event(doc, EVENTID_LOAD, &load_event); @@ -381,7 +381,7 @@ static nsresult handle_load(HTMLDocumentNode *doc, nsIDOMEvent *event) IDOMEvent_Release(&load_event->IDOMEvent_iface); }
- doc->window->performance_timing->load_event_end_time = get_time_stamp(); + doc->window->load_event_end_time = get_time_stamp(); return NS_OK; }
@@ -406,8 +406,7 @@ static nsresult handle_beforeunload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent)
static nsresult handle_unload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent) { - HTMLPerformanceTiming *timing = NULL; - HTMLInnerWindow *window; + HTMLInnerWindow *window, *pending_window; DOMEvent *event; HRESULT hres;
@@ -415,11 +414,9 @@ static nsresult handle_unload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent) return NS_OK; doc->unload_sent = TRUE;
- if(window->base.outer_window->pending_window) - timing = window->base.outer_window->pending_window->performance_timing; - - if(timing) - timing->unload_event_start_time = get_time_stamp(); + 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)) { @@ -427,8 +424,8 @@ static nsresult handle_unload(HTMLDocumentNode *doc, nsIDOMEvent *nsevent) IDOMEvent_Release(&event->IDOMEvent_iface); }
- if(timing) - timing->unload_event_end_time = get_time_stamp(); + 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 286d7ec7f73..865de247fd9 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1558,6 +1558,14 @@ HRESULT create_navigator(compat_mode_t compat_mode, IOmNavigator **navigator) return S_OK; }
+typedef struct { + DispatchEx dispex; + IHTMLPerformanceTiming IHTMLPerformanceTiming_iface; + + LONG ref; + HTMLInnerWindow *window; +} HTMLPerformanceTiming; + static inline HTMLPerformanceTiming *impl_from_IHTMLPerformanceTiming(IHTMLPerformanceTiming *iface) { return CONTAINING_RECORD(iface, HTMLPerformanceTiming, IHTMLPerformanceTiming_iface); @@ -1602,12 +1610,8 @@ static ULONG WINAPI HTMLPerformanceTiming_Release(IHTMLPerformanceTiming *iface)
TRACE("(%p) ref=%ld\n", This, ref);
- if(!ref) { - if(This->dispex.outer) - release_dispex(&This->dispex); - else - free(This); - } + if(!ref) + release_dispex(&This->dispex);
return ref; } @@ -1649,20 +1653,22 @@ static HRESULT WINAPI HTMLPerformanceTiming_Invoke(IHTMLPerformanceTiming *iface
static ULONGLONG get_fetch_time(HTMLPerformanceTiming *This) { + HTMLInnerWindow *window = This->window; + /* If there's no prior doc unloaded and no redirects, fetch time == navigationStart time */ - if(!This->unload_event_end_time && !This->redirect_time) - return This->navigation_start_time; + if(!window->unload_event_end_time && !window->redirect_time) + return window->navigation_start_time;
- if(This->dns_lookup_time) - return This->dns_lookup_time; - if(This->connect_time) - return This->connect_time; - if(This->request_time) - return This->request_time; - if(This->unload_event_end_time) - return This->unload_event_end_time; + if(window->dns_lookup_time) + return window->dns_lookup_time; + if(window->connect_time) + return window->connect_time; + if(window->request_time) + return window->request_time; + if(window->unload_event_end_time) + return window->unload_event_end_time;
- return This->redirect_time; + return window->redirect_time; }
static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformanceTiming *iface, ULONGLONG *p) @@ -1671,7 +1677,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_navigationStart(IHTMLPerformance
TRACE("(%p)->(%p)\n", This, p);
- *p = This->navigation_start_time; + *p = This->window->navigation_start_time; return S_OK; }
@@ -1681,7 +1687,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventStart(IHTMLPerformanc
TRACE("(%p)->(%p)\n", This, p);
- *p = This->unload_event_start_time; + *p = This->window->unload_event_start_time; return S_OK; }
@@ -1691,7 +1697,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_unloadEventEnd(IHTMLPerformanceT
TRACE("(%p)->(%p)\n", This, p);
- *p = This->unload_event_end_time; + *p = This->window->unload_event_end_time; return S_OK; }
@@ -1701,7 +1707,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectStart(IHTMLPerformanceTi
TRACE("(%p)->(%p)\n", This, p);
- *p = This->redirect_time; + *p = This->window->redirect_time; return S_OK; }
@@ -1711,7 +1717,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_redirectEnd(IHTMLPerformanceTimi
TRACE("(%p)->(%p)\n", This, p);
- *p = This->redirect_time ? get_fetch_time(This) : 0; + *p = This->window->redirect_time ? get_fetch_time(This) : 0; return S_OK; }
@@ -1731,7 +1737,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupStart(IHTMLPerforman
TRACE("(%p)->(%p)\n", This, p);
- *p = This->dns_lookup_time ? This->dns_lookup_time : get_fetch_time(This); + *p = This->window->dns_lookup_time ? This->window->dns_lookup_time : get_fetch_time(This); return S_OK; }
@@ -1741,8 +1747,8 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domainLookupEnd(IHTMLPerformance
TRACE("(%p)->(%p)\n", This, p);
- *p = This->connect_time ? This->connect_time : - This->dns_lookup_time ? This->dns_lookup_time : get_fetch_time(This); + *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; }
@@ -1752,8 +1758,8 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectStart(IHTMLPerformanceTim
TRACE("(%p)->(%p)\n", This, p);
- *p = This->connect_time ? This->connect_time : - This->dns_lookup_time ? This->dns_lookup_time : get_fetch_time(This); + *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; }
@@ -1763,9 +1769,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_connectEnd(IHTMLPerformanceTimin
TRACE("(%p)->(%p)\n", This, p);
- *p = This->request_time ? This->request_time : - This->connect_time ? This->connect_time : - This->dns_lookup_time ? This->dns_lookup_time : get_fetch_time(This); + *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; }
@@ -1775,9 +1781,9 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_requestStart(IHTMLPerformanceTim
TRACE("(%p)->(%p)\n", This, p);
- *p = This->request_time ? This->request_time : - This->connect_time ? This->connect_time : - This->dns_lookup_time ? This->dns_lookup_time : get_fetch_time(This); + *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; }
@@ -1787,7 +1793,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseStart(IHTMLPerformanceTi
TRACE("(%p)->(%p)\n", This, p);
- *p = This->response_start_time; + *p = This->window->response_start_time; return S_OK; }
@@ -1797,7 +1803,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_responseEnd(IHTMLPerformanceTimi
TRACE("(%p)->(%p)\n", This, p);
- *p = This->response_end_time; + *p = This->window->response_end_time; return S_OK; }
@@ -1808,7 +1814,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domLoading(IHTMLPerformanceTimin TRACE("(%p)->(%p)\n", This, p);
/* Make sure this is after responseEnd, when the Gecko parser starts */ - *p = This->response_end_time; + *p = This->window->response_end_time; return S_OK; }
@@ -1818,7 +1824,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domInteractive(IHTMLPerformanceT
TRACE("(%p)->(%p)\n", This, p);
- *p = This->dom_interactive_time; + *p = This->window->dom_interactive_time; return S_OK; }
@@ -1828,7 +1834,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventStart(IHTML
TRACE("(%p)->(%p)\n", This, p);
- *p = This->dom_content_loaded_event_start_time; + *p = This->window->dom_content_loaded_event_start_time; return S_OK; }
@@ -1838,7 +1844,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domContentLoadedEventEnd(IHTMLPe
TRACE("(%p)->(%p)\n", This, p);
- *p = This->dom_content_loaded_event_end_time; + *p = This->window->dom_content_loaded_event_end_time; return S_OK; }
@@ -1848,7 +1854,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_domComplete(IHTMLPerformanceTimi
TRACE("(%p)->(%p)\n", This, p);
- *p = This->dom_complete_time; + *p = This->window->dom_complete_time; return S_OK; }
@@ -1858,7 +1864,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventStart(IHTMLPerformanceT
TRACE("(%p)->(%p)\n", This, p);
- *p = This->load_event_start_time; + *p = This->window->load_event_start_time; return S_OK; }
@@ -1868,7 +1874,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_loadEventEnd(IHTMLPerformanceTim
TRACE("(%p)->(%p)\n", This, p);
- *p = This->load_event_end_time; + *p = This->window->load_event_end_time; return S_OK; }
@@ -1878,7 +1884,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_get_msFirstPaint(IHTMLPerformanceTim
TRACE("(%p)->(%p)\n", This, p);
- *p = This->first_paint_time; + *p = This->window->first_paint_time; return S_OK; }
@@ -1936,6 +1942,16 @@ static inline HTMLPerformanceTiming *HTMLPerformanceTiming_from_DispatchEx(Dispa return CONTAINING_RECORD(iface, HTMLPerformanceTiming, dispex); }
+static void HTMLPerformanceTiming_unlink(DispatchEx *dispex) +{ + HTMLPerformanceTiming *This = HTMLPerformanceTiming_from_DispatchEx(dispex); + if(This->window) { + HTMLInnerWindow *window = This->window; + This->window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + } +} + static void HTMLPerformanceTiming_destructor(DispatchEx *dispex) { HTMLPerformanceTiming *This = HTMLPerformanceTiming_from_DispatchEx(dispex); @@ -1944,6 +1960,7 @@ static void HTMLPerformanceTiming_destructor(DispatchEx *dispex)
static const dispex_static_data_vtbl_t HTMLPerformanceTiming_dispex_vtbl = { .destructor = HTMLPerformanceTiming_destructor, + .unlink = HTMLPerformanceTiming_unlink };
static const tid_t HTMLPerformanceTiming_iface_tids[] = { @@ -1957,22 +1974,6 @@ static dispex_static_data_t HTMLPerformanceTiming_dispex = { HTMLPerformanceTiming_iface_tids };
-HRESULT create_performance_timing(HTMLPerformanceTiming **ret) -{ - HTMLPerformanceTiming *timing; - - timing = calloc(1, sizeof(*timing)); - if(!timing) - return E_OUTOFMEMORY; - - timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; - timing->ref = 1; - - /* Defer initializing the dispex until it's actually needed (for compat mode) */ - *ret = timing; - return S_OK; -} - typedef struct { DispatchEx dispex; IHTMLPerformanceNavigation IHTMLPerformanceNavigation_iface; @@ -2163,7 +2164,7 @@ typedef struct {
HTMLInnerWindow *window; IHTMLPerformanceNavigation *navigation; - HTMLPerformanceTiming *timing; + IHTMLPerformanceTiming *timing; } HTMLPerformance;
static inline HTMLPerformance *impl_from_IHTMLPerformance(IHTMLPerformance *iface) @@ -2282,7 +2283,25 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP
TRACE("(%p)->(%p)\n", This, p);
- IHTMLPerformanceTiming_AddRef(*p = &This->timing->IHTMLPerformanceTiming_iface); + if(!This->timing) { + HTMLPerformanceTiming *timing; + + timing = calloc(1, sizeof(*timing)); + if(!timing) + return E_OUTOFMEMORY; + + timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; + timing->ref = 1; + timing->window = This->window; + IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface); + + init_dispatch(&timing->dispex, (IUnknown*)&timing->IHTMLPerformanceTiming_iface, + &HTMLPerformanceTiming_dispex, dispex_compat_mode(&This->dispex)); + + This->timing = &timing->IHTMLPerformanceTiming_iface; + } + + IHTMLPerformanceTiming_AddRef(*p = This->timing); return S_OK; }
@@ -2327,7 +2346,7 @@ static void HTMLPerformance_traverse(DispatchEx *dispex, nsCycleCollectionTraver if(This->navigation) note_cc_edge((nsISupports*)This->navigation, "navigation", cb); if(This->timing) - note_cc_edge((nsISupports*)&This->timing->IHTMLPerformanceTiming_iface, "timing", cb); + note_cc_edge((nsISupports*)This->timing, "timing", cb); }
static void HTMLPerformance_unlink(DispatchEx *dispex) @@ -2339,11 +2358,7 @@ static void HTMLPerformance_unlink(DispatchEx *dispex) IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); } unlink_ref(&This->navigation); - if(This->timing) { - HTMLPerformanceTiming *timing = This->timing; - This->timing = NULL; - IHTMLPerformanceTiming_Release(&timing->IHTMLPerformanceTiming_iface); - } + unlink_ref(&This->timing); }
static void HTMLPerformance_destructor(DispatchEx *dispex) @@ -2385,12 +2400,6 @@ HRESULT create_performance(HTMLInnerWindow *window, IHTMLPerformance **ret) init_dispatch(&performance->dispex, (IUnknown*)&performance->IHTMLPerformance_iface, &HTMLPerformance_dispex, compat_mode);
- performance->timing = window->performance_timing; - IHTMLPerformanceTiming_AddRef(&performance->timing->IHTMLPerformanceTiming_iface); - - init_dispatch(&performance->timing->dispex, (IUnknown*)&performance->timing->IHTMLPerformanceTiming_iface, - &HTMLPerformanceTiming_dispex, compat_mode); - *ret = &performance->IHTMLPerformance_iface; return S_OK; } diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index 43ebc5284f5..fe7448ec0cf 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -50,8 +50,8 @@ static void paint_document(HTMLDocumentObj *This) RECT rect; HDC hdc;
- if(This->window && This->window->base.inner_window && !This->window->base.inner_window->performance_timing->first_paint_time) - This->window->base.inner_window->performance_timing->first_paint_time = get_time_stamp(); + 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);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/omnavigator.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 865de247fd9..d931cee55a2 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -1562,7 +1562,6 @@ typedef struct { DispatchEx dispex; IHTMLPerformanceTiming IHTMLPerformanceTiming_iface;
- LONG ref; HTMLInnerWindow *window; } HTMLPerformanceTiming;
@@ -1581,7 +1580,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_QueryInterface(IHTMLPerformanceTimin *ppv = &This->IHTMLPerformanceTiming_iface; }else if(IsEqualGUID(&IID_IHTMLPerformanceTiming, riid)) { *ppv = &This->IHTMLPerformanceTiming_iface; - }else if(dispex_query_interface_no_cc(&This->dispex, riid, ppv)) { + }else if(dispex_query_interface(&This->dispex, riid, ppv)) { return *ppv ? S_OK : E_NOINTERFACE; }else { WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid)); @@ -1596,7 +1595,7 @@ static HRESULT WINAPI HTMLPerformanceTiming_QueryInterface(IHTMLPerformanceTimin static ULONG WINAPI HTMLPerformanceTiming_AddRef(IHTMLPerformanceTiming *iface) { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface); - LONG ref = InterlockedIncrement(&This->ref); + LONG ref = dispex_ref_incr(&This->dispex);
TRACE("(%p) ref=%ld\n", This, ref);
@@ -1606,13 +1605,10 @@ static ULONG WINAPI HTMLPerformanceTiming_AddRef(IHTMLPerformanceTiming *iface) static ULONG WINAPI HTMLPerformanceTiming_Release(IHTMLPerformanceTiming *iface) { HTMLPerformanceTiming *This = impl_from_IHTMLPerformanceTiming(iface); - LONG ref = InterlockedDecrement(&This->ref); + LONG ref = dispex_ref_decr(&This->dispex);
TRACE("(%p) ref=%ld\n", This, ref);
- if(!ref) - release_dispex(&This->dispex); - return ref; }
@@ -1942,6 +1938,13 @@ static inline HTMLPerformanceTiming *HTMLPerformanceTiming_from_DispatchEx(Dispa return CONTAINING_RECORD(iface, HTMLPerformanceTiming, dispex); }
+static void HTMLPerformanceTiming_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + HTMLPerformanceTiming *This = HTMLPerformanceTiming_from_DispatchEx(dispex); + if(This->window) + note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); +} + static void HTMLPerformanceTiming_unlink(DispatchEx *dispex) { HTMLPerformanceTiming *This = HTMLPerformanceTiming_from_DispatchEx(dispex); @@ -1960,6 +1963,7 @@ static void HTMLPerformanceTiming_destructor(DispatchEx *dispex)
static const dispex_static_data_vtbl_t HTMLPerformanceTiming_dispex_vtbl = { .destructor = HTMLPerformanceTiming_destructor, + .traverse = HTMLPerformanceTiming_traverse, .unlink = HTMLPerformanceTiming_unlink };
@@ -2291,7 +2295,6 @@ static HRESULT WINAPI HTMLPerformance_get_timing(IHTMLPerformance *iface, IHTMLP return E_OUTOFMEMORY;
timing->IHTMLPerformanceTiming_iface.lpVtbl = &HTMLPerformanceTimingVtbl; - timing->ref = 1; timing->window = This->window; IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 57 ++++++++++-------------------------- dlls/mshtml/htmlevent.c | 21 ------------- dlls/mshtml/mshtml_private.h | 3 -- dlls/mshtml/xmlhttprequest.c | 33 ++++++++++++++------- 4 files changed, 38 insertions(+), 76 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 820f72ad9e0..4dd9ed30d6f 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1994,28 +1994,6 @@ BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv) return TRUE; }
-BOOL dispex_query_interface_no_cc(DispatchEx *This, REFIID riid, void **ppv) -{ - if(IsEqualGUID(&IID_IDispatch, riid)) - *ppv = &This->IDispatchEx_iface; - else if(IsEqualGUID(&IID_IDispatchEx, riid)) - *ppv = &This->IDispatchEx_iface; - else if(IsEqualGUID(&IID_IDispatchJS, riid)) - *ppv = NULL; - else if(IsEqualGUID(&IID_UndocumentedScriptIface, riid)) - *ppv = NULL; - else if(IsEqualGUID(&IID_IMarshal, riid)) - *ppv = NULL; - else if(IsEqualGUID(&IID_IManagedObject, riid)) - *ppv = NULL; - else - return FALSE; - - if(*ppv) - IUnknown_AddRef((IUnknown*)*ppv); - return TRUE; -} - LONG dispex_ref_decr(DispatchEx *dispex) { BOOL has_task_magic = FALSE; @@ -2102,26 +2080,6 @@ static nsresult NSAPI dispex_unlink(void *p) static void NSAPI dispex_delete_cycle_collectable(void *p) { DispatchEx *This = impl_from_IDispatchEx(p); - release_dispex(This); -} - -void init_dispex_cc(void) -{ - static const CCObjCallback dispex_ccp_callback = { - dispex_traverse, - dispex_unlink, - dispex_delete_cycle_collectable - }; - ccp_init(&dispex_ccp, &dispex_ccp_callback); -} - -const void *dispex_get_vtbl(DispatchEx *dispex) -{ - return dispex->info->desc->vtbl; -} - -void release_dispex(DispatchEx *This) -{ dynamic_prop_t *prop;
if(This->info->desc->vtbl->unlink) @@ -2157,6 +2115,21 @@ destructor: This->info->desc->vtbl->destructor(This); }
+void init_dispex_cc(void) +{ + static const CCObjCallback dispex_ccp_callback = { + dispex_traverse, + dispex_unlink, + dispex_delete_cycle_collectable + }; + ccp_init(&dispex_ccp, &dispex_ccp_callback); +} + +const void *dispex_get_vtbl(DispatchEx *dispex) +{ + return dispex->info->desc->vtbl; +} + void init_dispatch(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *data, compat_mode_t compat_mode) { assert(compat_mode < COMPAT_MODE_CNT); diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index f38998f0d20..59cb44a6475 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -4560,27 +4560,6 @@ HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv) return E_NOINTERFACE; }
-HRESULT EventTarget_QI_no_cc(EventTarget *event_target, REFIID riid, void **ppv) -{ - if(IsEqualGUID(riid, &IID_IEventTarget)) { - if(use_event_quirks(event_target)) { - WARN("IEventTarget queried, but not supported by in document mode\n"); - *ppv = NULL; - return E_NOINTERFACE; - } - IEventTarget_AddRef(&event_target->IEventTarget_iface); - *ppv = &event_target->IEventTarget_iface; - return S_OK; - } - - if(dispex_query_interface_no_cc(&event_target->dispex, riid, ppv)) - return *ppv ? S_OK : E_NOINTERFACE; - - WARN("(%p)->(%s %p)\n", event_target, debugstr_mshtml_guid(riid), ppv); - *ppv = NULL; - return E_NOINTERFACE; -} - void EventTarget_init_dispex_info(dispex_data_t *dispex_info, compat_mode_t compat_mode) { static const dispex_hook_t IEventTarget_hooks[] = { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 8f6375b9ee0..697c16b1070 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -437,9 +437,7 @@ static inline LONG dispex_ref_incr(DispatchEx *dispex) extern LONG dispex_ref_decr(DispatchEx*);
void init_dispatch(DispatchEx*,IUnknown*,dispex_static_data_t*,compat_mode_t); -void release_dispex(DispatchEx*); BOOL dispex_query_interface(DispatchEx*,REFIID,void**); -BOOL dispex_query_interface_no_cc(DispatchEx*,REFIID,void**); void dispex_props_unlink(DispatchEx*); HRESULT change_type(VARIANT*,VARIANT*,VARTYPE,IServiceProvider*); HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**); @@ -1209,7 +1207,6 @@ void HTMLElement_Init(HTMLElement*,HTMLDocumentNode*,nsIDOMElement*,dispex_stati
void EventTarget_Init(EventTarget*,IUnknown*,dispex_static_data_t*,compat_mode_t); HRESULT EventTarget_QI(EventTarget*,REFIID,void**); -HRESULT EventTarget_QI_no_cc(EventTarget*,REFIID,void**); void EventTarget_init_dispex_info(dispex_data_t*,compat_mode_t);
HRESULT HTMLDOMNode_QI(HTMLDOMNode*,REFIID,void**); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index 07c141b10bd..e9115dc9af8 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -136,7 +136,6 @@ struct HTMLXMLHttpRequest { IHTMLXMLHttpRequest2 IHTMLXMLHttpRequest2_iface; IWineXMLHttpRequestPrivate IWineXMLHttpRequestPrivate_iface; IProvideClassInfo2 IProvideClassInfo2_iface; - LONG ref; LONG task_magic; LONG ready_state; response_type_t response_type; @@ -526,7 +525,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *ifa }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) { *ppv = &This->IProvideClassInfo2_iface; }else { - return EventTarget_QI_no_cc(&This->event_target, riid, ppv); + return EventTarget_QI(&This->event_target, riid, ppv); }
IUnknown_AddRef((IUnknown*)*ppv); @@ -536,7 +535,7 @@ static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *ifa static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - LONG ref = InterlockedIncrement(&This->ref); + LONG ref = dispex_ref_incr(&This->event_target.dispex);
TRACE("(%p) ref=%ld\n", This, ref);
@@ -546,13 +545,10 @@ static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface) static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface) { HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface); - LONG ref = InterlockedDecrement(&This->ref); + LONG ref = dispex_ref_decr(&This->event_target.dispex);
TRACE("(%p) ref=%ld\n", This, ref);
- if(!ref) - release_dispex(&This->event_target.dispex); - return ref; }
@@ -1521,10 +1517,20 @@ static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface) return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex); }
+static void HTMLXMLHttpRequest_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); + if(This->window) + note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); + if(This->pending_progress_event) + note_cc_edge((nsISupports*)&This->pending_progress_event->IDOMEvent_iface, "pending_progress_event", cb); + if(This->nsxhr) + note_cc_edge((nsISupports*)This->nsxhr, "nsxhr", cb); +} + static void HTMLXMLHttpRequest_unlink(DispatchEx *dispex) { HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); - remove_target_tasks(This->task_magic); if(This->event_listener) { XMLHttpReqEventListener *event_listener = This->event_listener; This->event_listener = NULL; @@ -1550,6 +1556,12 @@ static void HTMLXMLHttpRequest_destructor(DispatchEx *dispex) free(This); }
+static LONG HTMLXMLHttpRequest_get_task_magic(DispatchEx *dispex) +{ + HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); + return This->task_magic; +} + static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex) { HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex); @@ -1595,7 +1607,9 @@ static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode static const event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { { .destructor = HTMLXMLHttpRequest_destructor, - .unlink = HTMLXMLHttpRequest_unlink + .traverse = HTMLXMLHttpRequest_traverse, + .unlink = HTMLXMLHttpRequest_unlink, + .get_task_magic = HTMLXMLHttpRequest_get_task_magic }, .get_gecko_target = HTMLXMLHttpRequest_get_gecko_target, .bind_event = HTMLXMLHttpRequest_bind_event @@ -1736,7 +1750,6 @@ static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactor ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl; EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface, &HTMLXMLHttpRequest_dispex, This->window->doc->document_mode); - ret->ref = 1;
/* Always register the handlers because we need them to track state */ event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
On Mon Aug 28 13:16:27 2023 +0000, Jacek Caban wrote:
See Gecko sources for how it handles extra shouldDelete parameter.
So it does indeed look like it won't immediately free without the CC being shut down. However, I've been pondering some designs here, and I think the last_release one is over-engineered for our use cases; we only really need it for task_magic and only for two objects (the outer window doesn't use the dispex), so it seems like too much overhead and complexity for no reason.
Since we already have to introduce a new vtbl method, instead of having to deal with shouldDelete later or ccref_stabilize_for_deletion and so on (I also get rid of release_dispex btw), I figured a much simpler method is to just have something like get_task_magic.
I pushed new version using that. It's far simpler and still generic for every object, and avoids issues with gecko internals.
Well, except for outer window, because that one doesn't use the dispex and has its own mechanism, but that's the case anyway even with last_release.