| 2194 | } |
| 2195 | |
| 2196 | void ObjectInstance::toggle_down() { |
| 2197 | debug_lifecycle("Toggle notify DOWN"); |
| 2198 | |
| 2199 | // Change to weak ref so the wrapper-wrappee pair can be collected by the GC |
| 2200 | if (wrapper_is_rooted()) { |
| 2201 | debug_lifecycle("Unrooting wrapper"); |
| 2202 | GjsContextPrivate* gjs = GjsContextPrivate::from_current_context(); |
| 2203 | switch_to_unrooted(gjs->context()); |
| 2204 | |
| 2205 | /* During a GC, the collector asks each object which other objects that |
| 2206 | * it wants to hold on to so if there's an entire section of the heap |
| 2207 | * graph that's not connected to anything else, and not reachable from |
| 2208 | * the root set, then it can be trashed all at once. |
| 2209 | * |
| 2210 | * GObjects, however, don't work like that, there's only a reference |
| 2211 | * count but no notion of who owns the reference so, a JS object that's |
| 2212 | * wrapping a GObject is unconditionally held alive as long as the |
| 2213 | * GObject has >1 references. |
| 2214 | * |
| 2215 | * Since we cannot know how many more wrapped GObjects are going be |
| 2216 | * marked for garbage collection after the owner is destroyed, always |
| 2217 | * queue a garbage collection when a toggle reference goes down. |
| 2218 | */ |
| 2219 | if (!gjs->destroying()) |
| 2220 | gjs->schedule_gc(); |
| 2221 | } |
| 2222 | } |
| 2223 | |
| 2224 | void ObjectInstance::toggle_up() { |
| 2225 | if (G_UNLIKELY(!m_ptr || m_gobj_disposed || m_gobj_finalized)) { |
no test coverage detected