mshtml: how an object is released?

Open forum for end-user questions about Wine. Before asking questions, check out the Wiki as a first step.
Forum Rules
Locked
vzeroall
Newbie
Newbie
Posts: 2
Joined: Thu Dec 05, 2024 3:35 am

mshtml: how an object is released?

Post by vzeroall »

I try to understand how an HTMLDocumentNode object is get released?

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);
The create_document_node() function calloc(3)'s new HTMLDocumentNode, assigns its vtbls, etc. But the 'node' field of new HTMLDocumentNode object remains zeroed-out. To initialize that field the create_document_node() function (just like other functions) calls the HTMLDOMNode_Init() function. The latter assigns vtbls and initializes node's ccref calling the init_event_target():

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);
}
The ccref_init() function is a stuff from xul.dll (wine/wine-gecko), and above (inside the init_dispatch_from_desc()) it effectively moves 4 (100b) into the "reference counter and flag".

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)
And after that the HTMLWindow2_Release() gets the following code, therefore:

Code: Select all

static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
{
    return IWineJSDispatchHost_Release(&(dispex).IWineJSDispatchHost_iface);
}
Thus, eventually the HTMLWindow2_Release() will call the DispatchEx_Release() function. The latter just ccref_decr()'s the reference counter of the object. There is no explicit free(3) there.

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);
}
The Release() callback function applied to IHTMLDOMNode::Release() also ccref_decr()'s the counter (on the node object):

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;
}
No free(3) again.

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.
vzeroall
Newbie
Newbie
Posts: 2
Joined: Thu Dec 05, 2024 3:35 am

Re: mshtml: how an object is released?

Post by vzeroall »

I found out, that Wine's objects are now mostly removed with help of xul.dll's garbage-cycle collector implementation. Wine code registers callback functions which are called by CC (for example when the reference counter has became zero), and Wine then free(3)'s an object.
Locked