exports["test listeners are GC-ed"] = function(assert, done) { let receivedFromWeak = []; let receivedFromStrong = []; let loader = Loader(module); let events = loader.require('sdk/system/events'); let type = 'test-listeners-are-garbage-collected'; function handler(event) { receivedFromStrong.push(event); } function weakHandler(event) { receivedFromWeak.push(event); } events.on(type, handler, true); events.on(type, weakHandler); events.emit(type, { data: 1 }); assert.equal(receivedFromStrong.length, 1, "strong listener invoked"); assert.equal(receivedFromWeak.length, 1, "weak listener invoked"); handler = weakHandler = null; Cu.schedulePreciseGC(function() { events.emit(type, { data: 2 }); assert.equal(receivedFromWeak.length, 1, "weak listener was GC-ed"); assert.equal(receivedFromStrong.length, 2, "strong listener was invoked"); loader.unload(); done(); }); };
return function() { if (++count < 5) { Cu.schedulePreciseGC(genGCCallback()); } else { resolve(); } }
exports.testGCdHiddenSidebarsOnUnload = function(assert, done) { const loader = Loader(module); const { Sidebar } = loader.require('sdk/ui/sidebar'); const window = getMostRecentBrowserWindow(); let testName = 'testGCdHiddenSidebarsOnUnload'; let url = 'data:text/html;charset=utf-8,'+testName; assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing'); // IMPORTANT: make no reference to the sidebar instance, so it is GC'd Sidebar({ id: testName, title: testName, url: url }); let menuitemID = makeID(testName); assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found'); Cu.schedulePreciseGC(function() { assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found after gc'); loader.unload(); assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed'); done(); }); }
exports.gc = function (panel) { Cu.schedulePreciseGC( function () { panel.port.emit('schedulePreciseGC', ''); } ); };
function gc() { let { promise, resolve } = defer(); Cu.forceGC(); memory.gc(); Cu.schedulePreciseGC(_ => resolve()); return promise; }
exports["test weak observers are GC-ed on unload"] = (assert, end) => { const topic = Date.now().toString(32); const loader = Loader(module); const { Observer, observe, subscribe, unsubscribe } = loader.require("sdk/core/observer"); const { isWeak, WeakReference } = loader.require("sdk/core/reference"); const MyObserver = Class({ extends: Observer, initialize: function(observe) { this.observe = observe; } }); observe.define(MyObserver, (x, ...rest) => x.observe(...rest)); const MyWeakObserver = Class({ extends: MyObserver, implements: [WeakReference] }); let xs = []; let ys = []; let x = new MyObserver((subject, topic, data) => { xs.push(subject.wrappedJSObject, topic, data); }); let y = new MyWeakObserver((subject, topic, data) => { ys.push(subject.wrappedJSObject, topic, data); }); subscribe(x, topic); subscribe(y, topic); notifyObservers(message({ foo: 1 }), topic, null); x = null; y = null; loader.unload(); Cu.schedulePreciseGC(() => { notifyObservers(message({ bar: 2 }), topic, ":)"); assert.deepEqual(xs, [{ foo: 1 }, topic, null, { bar: 2 }, topic, ":)"], "non week observer is kept"); assert.deepEqual(ys, [{ foo: 1 }, topic, null], "week observer was GC-ed"); end(); }); };
return new Promise(resolve => { Cu.forceGC(); Cu.forceCC(); let count = 0; function genGCCallback() { Cu.forceCC(); return function() { if (++count < 5) { Cu.schedulePreciseGC(genGCCallback()); } else { resolve(); } } } Cu.schedulePreciseGC(genGCCallback()); });
sidebar.show().then(function() { sidebar = null; assert.equal(isSidebarShowing(window), true, 'the sidebar is showing'); let menuitemID = makeID(testName); assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found'); Cu.schedulePreciseGC(function() { loader.unload(); assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing after unload'); assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed'); done(); }) }, assert.fail).then(null, assert.fail);
yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
onActivate: function onActivate(tab) { tab.removeListener('activate', onActivate); let { activeWindow } = browserWindows; // set window state button.state(activeWindow, { label: 'Window label', icon: './window-icon.png' }); // set previous active tab state button.state(mainTab, { label: 'Tab label', icon: './tab-icon.png', }); // set current active tab state button.state(tab, { icon: './another-tab-icon.png', disabled: true }); // check the states Cu.schedulePreciseGC(() => { let state; assert.equal(button.label, 'my button', 'global label unchanged'); assert.equal(button.icon, './icon.png', 'global icon unchanged'); assert.equal(button.disabled, false, 'global disabled unchanged'); state = button.state(mainTab); assert.equal(state.label, 'Tab label', 'previous tab label updated'); assert.equal(state.icon, './tab-icon.png', 'previous tab icon updated'); assert.equal(state.disabled, false, 'previous tab disabled unchanged'); state = button.state(tab); assert.equal(state.label, 'Window label', 'active tab inherited from window state'); assert.equal(state.icon, './another-tab-icon.png', 'active tab icon updated'); assert.equal(state.disabled, true, 'active disabled updated'); // change the global state button.icon = './good-icon.png'; // delete the tab state button.state(tab, null); assert.equal(button.icon, './good-icon.png', 'global icon updated'); assert.equal(button.state(mainTab).icon, './tab-icon.png', 'previous tab icon unchanged'); assert.equal(button.state(tab).icon, './window-icon.png', 'tab icon inherited from window'); // delete the window state button.state(activeWindow, null); assert.equal(button.state(tab).icon, './good-icon.png', 'tab icon inherited from global'); // check the node properties state = button.state(tabs.activeTab); assert.equal(node.getAttribute('label'), state.label, 'node label is correct'); assert.equal(node.getAttribute('tooltiptext'), state.label, 'node tooltip is correct'); assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)), 'node image is correct'); assert.equal(node.hasAttribute('disabled'), state.disabled, 'disabled is correct'); tabs.once('activate', () => { // This is made in order to avoid to check the node before it // is updated, need a better check setTimeout(() => { let state = button.state(mainTab); assert.equal(node.getAttribute('label'), state.label, 'node label is correct'); assert.equal(node.getAttribute('tooltiptext'), state.label, 'node tooltip is correct'); assert.equal(node.getAttribute('image'), data.url(state.icon.substr(2)), 'node image is correct'); assert.equal(node.hasAttribute('disabled'), state.disabled, 'disabled is correct'); tab.close(() => { loader.unload(); done(); }); }, 500); }); mainTab.activate(); }); }