I understand how it is created (read: calloc(3)'ed):
The create_outer_window() function creates an "inner" "pending" window (window->pending_window) and calls the update_window_doc() function which creates an HTMLDocumentNode object and stores it within the "pending" window:
Code: Select all
hres = create_document_node(nsdoc, outer_window->browser, window, window, parent_mode, &window->doc);
Code: Select all
/* dlls/mshtml/htmlevent.c */
void init_event_target(EventTarget *event_target, dispex_static_data_t *dispex_data, HTMLInnerWindow *script_global)
{
...
init_dispatch(&event_target->dispex, dispex_data, script_global, compat_mode);
...
}
/* dlls/mshtml/dispex.c */
static void init_dispatch_from_desc(DispatchEx *dispex, dispex_data_t *info, HTMLInnerWindow *script_global, DispatchEx *prototype)
{
dispex->IWineJSDispatchHost_iface.lpVtbl = &JSDispatchHostVtbl;
...
ccref_init(&dispex->ccref, 1);
...
}
void init_dispatch(DispatchEx *dispex, dispex_static_data_t *data, HTMLInnerWindow *script_global, compat_mode_t compat_mode)
{
...
init_dispatch_from_desc(dispex, info, script_global, prototype);
}
So, now we have new HTMLDocumentNode object with initialized HTMLDOMNode inside.
My question is: how it is free(3)'d?
An "inner" window has vtbl where the Release() function is assigned to HTMLWindow2_Release().
Wine 9.x uses macro DISPEX_IDISPATCH_IMPL to define members of an IDispatch implementation. For the "inner" window it declares functions like this:
Code: Select all
DISPEX_IDISPATCH_IMPL(HTMLWindow2, IHTMLWindow2,
impl_from_IHTMLWindow2(iface)->inner_window->event_target.dispex)
Code: Select all
static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
{
return IWineJSDispatchHost_Release(&(dispex).IWineJSDispatchHost_iface);
}
Wine 8.x defines the HTMLWindow2_Release() "explicitly". For an "inner" window it calls the release_inner_window() function which contains the following code:
Code: Select all
if(This->doc) {
This->doc->window = NULL;
IHTMLDOMNode_Release(&This->doc->node.IHTMLDOMNode_iface);
}
Code: Select all
static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
{
HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface, &node_ccp);
TRACE("(%p) ref=%ld\n", This, ref);
return ref;
}
Do I understand correctly that an object (an "inner" window in Wine 9.x or node in Wine 8.x) is removed by xul.dll? Somehow... Somehow using xul.dll's garbage collector, or something. I had actually searched for "clearing code" there, but I failed.