diff options
Diffstat (limited to 'js/xpconnect/tests/unit/test_onGarbageCollection-04.js')
-rw-r--r-- | js/xpconnect/tests/unit/test_onGarbageCollection-04.js | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/js/xpconnect/tests/unit/test_onGarbageCollection-04.js b/js/xpconnect/tests/unit/test_onGarbageCollection-04.js new file mode 100644 index 0000000000..72e6d32284 --- /dev/null +++ b/js/xpconnect/tests/unit/test_onGarbageCollection-04.js @@ -0,0 +1,72 @@ +// Test that the onGarbageCollection reentrancy guard is on a per Debugger +// basis. That is if our first Debugger is observing our second Debugger's +// compartment, and this second Debugger triggers a GC inside its +// onGarbageCollection hook, the first Debugger's onGarbageCollection hook is +// still called. +// +// This is the scenario we are setting up: top level debugging the `debuggeree` +// global, which is debugging the `debuggee` global. Then, we trigger the +// following events: +// +// debuggee gc +// | +// V +// debuggeree's onGarbageCollection +// | +// V +// debuggeree gc +// | +// V +// top level onGarbageCollection +// +// Note that the top level's onGarbageCollection hook should be fired, at the +// same time that we are preventing reentrancy into debuggeree's +// onGarbageCollection hook. + +Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true); +registerCleanupFunction(() => { + Services.prefs.clearUserPref("security.allow_eval_with_system_principal"); +}); + +function run_test() { + do_test_pending(); + + const debuggeree = newGlobal(); + const debuggee = debuggeree.debuggee = newGlobal(); + + debuggeree.eval( + ` + var dbg = new Debugger(this.debuggee); + var fired = 0; + dbg.memory.onGarbageCollection = _ => { + fired++; + gc(this); + }; + ` + ); + + const dbg = new Debugger(debuggeree); + let fired = 0; + dbg.memory.onGarbageCollection = _ => { + fired++; + }; + + debuggee.eval(`gc(this)`); + + // Let first onGarbageCollection runnable get run. + executeSoon(() => { + + // Let second onGarbageCollection runnable get run. + executeSoon(() => { + + // Even though we request GC'ing a single zone, we can't rely on that + // behavior and both zones could have been scheduled for gc for both + // gc(this) calls. + ok(debuggeree.fired >= 1); + ok(fired >= 1); + + debuggeree.dbg.removeAllDebuggees(); + do_test_finished(); + }); + }); +} |