From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 12 ++++++++- dlls/mshtml/htmlwindow.c | 52 ++++++++++++++++++++++++++++++------ dlls/mshtml/mshtml_private.h | 13 +++------ 3 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 53198840170..c7e497014bf 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,16 @@ BOOL dispex_query_interface_no_cc(DispatchEx *This, REFIID riid, void **ppv) return TRUE; }
+LONG dispex_ref_decr(DispatchEx *dispex) +{ + LONG ref = ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp); + + if(!ref && dispex->info->desc->vtbl->last_release) + dispex->info->desc->vtbl->last_release(dispex); + + 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..e3e13b41907 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 void HTMLWindow_last_release(DispatchEx *dispex) +{ + HTMLInnerWindow *This = impl_from_DispatchEx(dispex); + remove_target_tasks(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, + .last_release = HTMLWindow_last_release, .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..361da1644f5 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*);
+ /* Called on the last release, when the refcount reaches 0 */ + void (*last_release)(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; };