Jacek Caban (@jacek) commented about dlls/mshtml/dispex.c:
+ return iface->lpVtbl == &JSDispatchHostVtbl ? impl_from_IWineJSDispatchHost(iface) : NULL; +} + +static struct cc_native_obj WINAPI cc_participant_api_canonicalize(IUnknown *obj) +{ + struct cc_native_obj cc_obj = { .obj = obj, .participant = NULL }; + DispatchEx *dispex = NULL; + IUnknown *unk; + + /* These QI do not AddRef, so they are scan-safe */ + if(IUnknown_QueryInterface(obj, &IID_nsCycleCollectionISupports, (void**)&unk) != S_OK) + return cc_obj; + + /* We can't QI here because we can't touch the refcount and that would add a ref, so inspect vtbl directly */ + if(!(dispex = unsafe_impl_from_IWineJSDispatchHost((IWineJSDispatchHost*)unk))) { + HTMLOuterWindow *outer_window = unsafe_HTMLOuterWindow_from_IHTMLWindow2((IHTMLWindow2*)unk); This is not great... Could we use the same mechanism as Gecko does and have separate participants for them? They could then just perform a safe cast and call some common implementation on that.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10045#note_149715