/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ ChromeUtils.defineESModuleGetters(this, { DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs", }); /** * Checks that the "finalize" method allows the callback to be GC'd. */ add_task(async function test_finalize_after_arm() { let count = 0; let callback = () => { ++count; }; let callbackWeakRef = Cu.getWeakReference(callback); let deferredTask = new DeferredTask( callback, /* delayMs */ 600_000, // long timeout, we are not going to wait for it. /* idleTimeoutMs */ undefined // no deadline. ); // Clear callback reference, so that we are not the ones keeping it alive. callback = null; Cu.forceGC(); ok(callbackWeakRef.get(), "Callback not GC'd yet"); deferredTask.arm(); equal(count, 0, "callback not called yet"); await deferredTask.finalize(); equal(count, 1, "callback force called by finalize"); Cu.forceGC(); ok(!callbackWeakRef.get(), "Callback GC'd after finalize"); // Make sure to reference deferredTask so that there is still a strong // reference to deferredTask, which prevents deferredTask from trivially // being collected. Assert.throws( () => deferredTask.finalize(), /The object has been already finalized/, "finalize() cannot be called twice" ); }); add_task(async function test_gc_without_arm_or_finalize() { let count = 0; let callback = () => { ++count; }; let callbackWeakRef = Cu.getWeakReference(callback); let deferredTask = new DeferredTask( callback, /* delayMs */ 600_000, // long timeout, we are not going to wait for it. /* idleTimeoutMs */ undefined // no deadline. ); // Clear callback reference, so that we are not the ones keeping it alive. callback = null; let deferredTaskWeakRef = Cu.getWeakReference(deferredTask); deferredTask = null; Cu.forceGC(); ok(!deferredTaskWeakRef.get(), "DeferredTask can be GC'd when not armed"); ok(!callbackWeakRef.get(), "Callback GC'd when DeferredTask is GC'd"); equal(count, 0, "callback was never called"); });