Commit 6dc7c3cd authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Implement Cycle Collection for inner windows.

parent 1c4a15cc
...@@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); ...@@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define MAX_ARGS 16 #define MAX_ARGS 16
ExternalCycleCollectionParticipant dispex_ccp; static ExternalCycleCollectionParticipant dispex_ccp;
static CRITICAL_SECTION cs_dispex_static_data; static CRITICAL_SECTION cs_dispex_static_data;
static CRITICAL_SECTION_DEBUG cs_dispex_static_data_dbg = static CRITICAL_SECTION_DEBUG cs_dispex_static_data_dbg =
...@@ -2016,6 +2016,22 @@ BOOL dispex_query_interface_no_cc(DispatchEx *This, REFIID riid, void **ppv) ...@@ -2016,6 +2016,22 @@ BOOL dispex_query_interface_no_cc(DispatchEx *This, REFIID riid, void **ppv)
return TRUE; return TRUE;
} }
LONG dispex_ref_decr(DispatchEx *dispex)
{
LONG ref = ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp);
/* Gecko ccref may not free the object immediatelly when ref count reaches 0, so we need
* an extra care for objects that need an immediate clean up. See
* NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE for details. */
if(!ref && dispex->info->desc->vtbl->last_release) {
ccref_incr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface);
dispex->info->desc->vtbl->last_release(dispex);
ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp);
}
return ref;
}
static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) static nsresult NSAPI dispex_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
{ {
DispatchEx *This = impl_from_IDispatchEx(p); DispatchEx *This = impl_from_IDispatchEx(p);
......
...@@ -220,13 +220,13 @@ static HRESULT WINAPI HTMLWindow2_QueryInterface(IHTMLWindow2 *iface, REFIID rii ...@@ -220,13 +220,13 @@ static HRESULT WINAPI HTMLWindow2_QueryInterface(IHTMLWindow2 *iface, REFIID rii
if(hres != S_FALSE) if(hres != S_FALSE)
return hres; 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) static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface)
{ {
HTMLInnerWindow *This = HTMLInnerWindow_from_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); TRACE("(%p) ref=%ld\n", This, ref);
...@@ -236,13 +236,10 @@ static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface) ...@@ -236,13 +236,10 @@ static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface)
static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface) static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
{ {
HTMLInnerWindow *This = HTMLInnerWindow_from_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); TRACE("(%p) ref=%ld\n", This, ref);
if(!ref)
release_dispex(&This->event_target.dispex);
return ref; return ref;
} }
...@@ -264,7 +261,7 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri ...@@ -264,7 +261,7 @@ static HRESULT WINAPI outer_window_QueryInterface(IHTMLWindow2 *iface, REFIID ri
*ppv = &This->base.IHTMLWindow2_iface; *ppv = &This->base.IHTMLWindow2_iface;
return S_OK; return S_OK;
}else { }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) ...@@ -3827,6 +3824,38 @@ static inline HTMLInnerWindow *impl_from_DispatchEx(DispatchEx *iface)
return CONTAINING_RECORD(iface, HTMLInnerWindow, event_target.dispex); 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) static void HTMLWindow_unlink(DispatchEx *dispex)
{ {
HTMLInnerWindow *This = impl_from_DispatchEx(dispex); HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
...@@ -3905,6 +3934,12 @@ static void HTMLWindow_destructor(DispatchEx *dispex) ...@@ -3905,6 +3934,12 @@ static void HTMLWindow_destructor(DispatchEx *dispex)
free(This); 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) static HRESULT HTMLWindow_get_name(DispatchEx *dispex, DISPID id, BSTR *name)
{ {
HTMLInnerWindow *This = impl_from_DispatchEx(dispex); HTMLInnerWindow *This = impl_from_DispatchEx(dispex);
...@@ -4151,7 +4186,9 @@ static IHTMLEventObj *HTMLWindow_set_current_event(DispatchEx *dispex, IHTMLEven ...@@ -4151,7 +4186,9 @@ static IHTMLEventObj *HTMLWindow_set_current_event(DispatchEx *dispex, IHTMLEven
static const event_target_vtbl_t HTMLWindow_event_target_vtbl = { static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
{ {
.destructor = HTMLWindow_destructor, .destructor = HTMLWindow_destructor,
.traverse = HTMLWindow_traverse,
.unlink = HTMLWindow_unlink, .unlink = HTMLWindow_unlink,
.last_release = HTMLWindow_last_release,
.get_name = HTMLWindow_get_name, .get_name = HTMLWindow_get_name,
.invoke = HTMLWindow_invoke, .invoke = HTMLWindow_invoke,
.next_dispid = HTMLWindow_next_dispid, .next_dispid = HTMLWindow_next_dispid,
...@@ -4297,7 +4334,6 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon, ...@@ -4297,7 +4334,6 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, IMoniker *mon,
window->base.outer_window = outer_window; window->base.outer_window = outer_window;
window->base.inner_window = window; window->base.inner_window = window;
window->base.ref = 1;
EventTarget_Init(&window->event_target, (IUnknown*)&window->base.IHTMLWindow2_iface, EventTarget_Init(&window->event_target, (IUnknown*)&window->base.IHTMLWindow2_iface,
&HTMLWindow_dispex, COMPAT_MODE_NONE); &HTMLWindow_dispex, COMPAT_MODE_NONE);
......
...@@ -358,6 +358,9 @@ typedef struct { ...@@ -358,6 +358,9 @@ typedef struct {
void (*traverse)(DispatchEx*,nsCycleCollectionTraversalCallback*); void (*traverse)(DispatchEx*,nsCycleCollectionTraversalCallback*);
void (*unlink)(DispatchEx*); 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 */ /* Called when the object wants to handle DISPID_VALUE invocations */
HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
...@@ -427,17 +430,11 @@ extern void (__cdecl *ccp_init)(ExternalCycleCollectionParticipant*,const CCObjC ...@@ -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 *describe_cc_node)(nsCycleCollectingAutoRefCnt*,const char*,nsCycleCollectionTraversalCallback*);
extern void (__cdecl *note_cc_edge)(nsISupports*,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) static inline LONG dispex_ref_incr(DispatchEx *dispex)
{ {
return ccref_incr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface); return ccref_incr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface);
} }
extern LONG dispex_ref_decr(DispatchEx*);
static inline LONG dispex_ref_decr(DispatchEx *dispex)
{
return ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &dispex_ccp);
}
void init_dispatch(DispatchEx*,IUnknown*,dispex_static_data_t*,compat_mode_t); void init_dispatch(DispatchEx*,IUnknown*,dispex_static_data_t*,compat_mode_t);
void release_dispex(DispatchEx*); void release_dispex(DispatchEx*);
...@@ -577,8 +574,6 @@ struct HTMLWindow { ...@@ -577,8 +574,6 @@ struct HTMLWindow {
IWineHTMLWindowPrivate IWineHTMLWindowPrivate_iface; IWineHTMLWindowPrivate IWineHTMLWindowPrivate_iface;
IWineHTMLWindowCompatPrivate IWineHTMLWindowCompatPrivate_iface; IWineHTMLWindowCompatPrivate IWineHTMLWindowCompatPrivate_iface;
LONG ref;
HTMLInnerWindow *inner_window; HTMLInnerWindow *inner_window;
HTMLOuterWindow *outer_window; HTMLOuterWindow *outer_window;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment