diff --git a/gfx/layers/apz/test/mochitest/apz_test_utils.js b/gfx/layers/apz/test/mochitest/apz_test_utils.js index a329c94adc72..b9bf8221fe82 100644 --- a/gfx/layers/apz/test/mochitest/apz_test_utils.js +++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js @@ -378,7 +378,7 @@ async function waitUntilApzStable() { // it must be totally self-contained to be shipped over to the parent process. /* eslint-env mozilla/frame-script */ function parentProcessFlush() { - addMessageListener("apz-flush", function() { + function apzFlush() { const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); var topWin = Services.wm.getMostRecentWindow("navigator:browser"); if (!topWin) { @@ -409,13 +409,23 @@ async function waitUntilApzStable() { // Flush APZ repaints, but wait until all the pending paints have been // sent. flushRepaint(); - }); + } + function cleanup() { + removeMessageListener("apz-flush", apzFlush); + removeMessageListener("cleanup", cleanup); + } + addMessageListener("apz-flush", apzFlush); + addMessageListener("cleanup", cleanup); } // This is the first time waitUntilApzStable is being called, do initialization if (typeof waitUntilApzStable.chromeHelper == "undefined") { waitUntilApzStable.chromeHelper = SpecialPowers.loadChromeScript(parentProcessFlush); - ApzCleanup.register(() => { waitUntilApzStable.chromeHelper.destroy(); }); + ApzCleanup.register(() => { + waitUntilApzStable.chromeHelper.sendSyncMessage("cleanup", null); + waitUntilApzStable.chromeHelper.destroy(); + delete waitUntilApzStable.chromeHelper; + }); } // Actually trigger the parent-process flush and wait for it to finish diff --git a/testing/specialpowers/content/SpecialPowersObserverAPI.js b/testing/specialpowers/content/SpecialPowersObserverAPI.js index 8c591aeca719..44179f3d84e4 100644 --- a/testing/specialpowers/content/SpecialPowersObserverAPI.js +++ b/testing/specialpowers/content/SpecialPowersObserverAPI.js @@ -466,7 +466,7 @@ SpecialPowersObserverAPI.prototype = { } // Setup a chrome sandbox that has access to sendAsyncMessage - // and addMessageListener in order to communicate with + // and {add,remove}MessageListener in order to communicate with // the mochitest. let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); let sandboxOptions = Object.assign({wantGlobalProperties: ["ChromeUtils"]}, @@ -481,6 +481,14 @@ SpecialPowersObserverAPI.prototype = { sb.addMessageListener = (name, listener) => { this._chromeScriptListeners.push({ id, name, listener }); }; + sb.removeMessageListener = (name, listener) => { + let index = this._chromeScriptListeners.findIndex(function(obj) { + return obj.id == id && obj.name == name && obj.listener == listener; + }); + if (index >= 0) { + this._chromeScriptListeners.splice(index, 1); + } + }; sb.browserElement = aMessage.target; // Also expose assertion functions