`ccref_is_0` is not great, esp. with modifications to each task handler that can't be easily moved out of them.
Did you try porting `NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE` and do it the way cycle collector developers intended it to be used? This feels like the cleanest solution to me so far and it seems straightforward. On Wine side, dispex_ref_decr could probably look like:
``` cpp_bool should_delete; LONG ref = ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, &should_delete); if(!ref) { if(dispex->info->vtbl->last_release) { ccref_incr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface); dispex->info->vtbl->last_release(dispex); ccref_decr(&dispex->ccref, (nsISupports*)&dispex->IDispatchEx_iface, NULL); } if(should_delete) { ccref_stabilize_for_deletion(&dispex->ccref); release_dispex(dispex); } } ```
Then, inside `last_release`, we could safely use This pointer without any hacks.
Reading closer Gecko code, it seems that should_delete is only important during XPCOM shutdown (`NS_ShutdownXPCOM`). Since we never shutdown XPCOM properly (because it can't be re-initialized and we don't know if we will need it again), maybe we could even get away without it. I'm not sure, it would need a better look at Gecko code to be sure. (Still, we will probably want to handle it given how easy it is, but perhaps we can live without it for the first iteration).