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);
#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,22 @@ 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);
/* 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)
{
DispatchEx *This = impl_from_IDispatchEx(p);
......
......@@ -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);
......
......@@ -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;
};
......
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