[FIX] web: stop leaking event listeners on EventBus in QUnit suite
In odoo/odoo#120893, the mail team changed their test utils so that they would always start all services. This can cause issues because services do not have any built-in destruction/cleanup mechanism, as in a production application they are only supposed to be started once. Some services add event listeners on global objects, in particular, the tour service adds an event listener on the tour registry which is global. If this event listener is not cleaned up, every time the tour service is started, a reference to the environment in which this tour service is being started is leaked. Since the environment contains all started services, it is typically a pretty heavy object, especially since in this context, all services are started instead of a select subset. This commit fixes that by patching the EventBus class to automatically remove event listeners that were added on an event bus after the test, in a similar fashion to what we do for some global objects like window or the document's body. closes odoo/odoo#130373 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import { loadLanguages } from "@web/core/l10n/translation";
|
||||
transitionConfig.disabled = true;
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { App, whenReady } from "@odoo/owl";
|
||||
import { App, EventBus, whenReady } from "@odoo/owl";
|
||||
import { currencies } from "@web/core/currency";
|
||||
import "./helpers/session";
|
||||
|
||||
@@ -352,27 +352,38 @@ function patchAssets() {
|
||||
});
|
||||
}
|
||||
|
||||
function patchEventBus() {
|
||||
patchWithCleanup(EventBus.prototype, {
|
||||
addEventListener() {
|
||||
this._super(...arguments);
|
||||
registerCleanup(() => this.removeEventListener(...arguments));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function setupTests() {
|
||||
// uncomment to debug memory leaks in qunit suite
|
||||
// let memoryBeforeModule;
|
||||
// QUnit.moduleStart(({ tests }) => {
|
||||
// if (tests.length) {
|
||||
// window.gc();
|
||||
// memoryBeforeModule = window.performance.memory.usedJSHeapSize;
|
||||
// }
|
||||
// });
|
||||
// QUnit.moduleDone(({ name }) => {
|
||||
// if (memoryBeforeModule) {
|
||||
// window.gc();
|
||||
// const afterGc = window.performance.memory.usedJSHeapSize;
|
||||
// console.log(
|
||||
// `MEMINFO - After suite "${name}" - after gc: ${afterGc} delta: ${
|
||||
// afterGc - memoryBeforeModule
|
||||
// }`
|
||||
// );
|
||||
// memoryBeforeModule = null;
|
||||
// }
|
||||
// });
|
||||
// if (window.gc) {
|
||||
// let memoryBeforeModule;
|
||||
// QUnit.moduleStart(({ tests }) => {
|
||||
// if (tests.length) {
|
||||
// window.gc();
|
||||
// memoryBeforeModule = window.performance.memory.usedJSHeapSize;
|
||||
// }
|
||||
// });
|
||||
// QUnit.moduleDone(({ name }) => {
|
||||
// if (memoryBeforeModule) {
|
||||
// window.gc();
|
||||
// const afterGc = window.performance.memory.usedJSHeapSize;
|
||||
// console.log(
|
||||
// `MEMINFO - After suite "${name}" - after gc: ${afterGc} delta: ${
|
||||
// afterGc - memoryBeforeModule
|
||||
// }`
|
||||
// );
|
||||
// memoryBeforeModule = null;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
QUnit.testStart(() => {
|
||||
checkGlobalObjectsIntegrity();
|
||||
@@ -381,6 +392,7 @@ export async function setupTests() {
|
||||
cleanLoadedLanguages();
|
||||
patchBrowserWithCleanup();
|
||||
patchBodyAddEventListener();
|
||||
patchEventBus();
|
||||
patchLegacyBus();
|
||||
patchOdoo();
|
||||
patchSessionInfo();
|
||||
|
||||
Reference in New Issue
Block a user