diff --git a/src/routes/_utils/delegate.js b/src/routes/_utils/delegate.js index 32f9babd..43cb421f 100644 --- a/src/routes/_utils/delegate.js +++ b/src/routes/_utils/delegate.js @@ -2,8 +2,8 @@ const callbacks = {} -if (process.browser && process.env.NODE_ENV !== 'production') { - window.delegateCallbacks = callbacks +if (process.browser) { + window.__delegateCallbacks = callbacks } function onEvent (e) { diff --git a/src/routes/_utils/eventBus.js b/src/routes/_utils/eventBus.js index 86302717..1eaaeea6 100644 --- a/src/routes/_utils/eventBus.js +++ b/src/routes/_utils/eventBus.js @@ -2,8 +2,8 @@ import EventEmitter from 'events-light' export const eventBus = new EventEmitter() -if (process.browser && process.env.NODE_ENV !== 'production') { - window.eventBus = eventBus +if (process.browser) { + window.__eventBus = eventBus } export function on (eventName, component, method) { diff --git a/src/routes/_utils/resize.js b/src/routes/_utils/resize.js index bb4eb226..270cfc0c 100644 --- a/src/routes/_utils/resize.js +++ b/src/routes/_utils/resize.js @@ -4,8 +4,8 @@ const DEBOUNCE_DELAY = 700 const listeners = new Set() -if (process.browser && process.env.NODE_ENV !== 'production') { - window.resizeListeners = listeners +if (process.browser) { + window.__resizeListeners = listeners } if (process.browser) { diff --git a/tests/spec/038-memory-leaks.js b/tests/spec/038-memory-leaks.js new file mode 100644 index 00000000..81b56326 --- /dev/null +++ b/tests/spec/038-memory-leaks.js @@ -0,0 +1,46 @@ +import { + composeInput, + getNthAutosuggestionResult, + getNumSyntheticListeners, + getUrl, + homeNavButton, + scrollToStatus, + scrollToTop, + settingsNavButton, sleep +} from '../utils' +import { loginAsFoobar } from '../roles' + +fixture`038-memory-leaks.js` + .page`http://localhost:4002` + +async function goToStartPoint (t) { + await t + .click(settingsNavButton) + .expect(getUrl()).contains('/settings') +} + +async function interactAndGoToEndPoint (t) { + await t + .click(homeNavButton) + .expect(getUrl()).eql('http://localhost:4002/') + await scrollToStatus(t, 15) + await scrollToTop() + await t + .typeText(composeInput, 'hey @qu') + .expect(getNthAutosuggestionResult(1).find('.sr-only').innerText).contains('@quux') + .click(settingsNavButton) + .expect(getUrl()).contains('/settings') +} + +test('Does not leak synthetic listeners', async t => { + await loginAsFoobar(t) + await goToStartPoint(t) + await sleep(1000) + const numSyntheticListeners = await getNumSyntheticListeners() + await t + .expect(numSyntheticListeners).typeOf('number') + await interactAndGoToEndPoint(t) + await sleep(1000) + await t + .expect(getNumSyntheticListeners()).eql(numSyntheticListeners) +}) diff --git a/tests/utils.js b/tests/utils.js index ba70539e..2b7ab0cc 100644 --- a/tests/utils.js +++ b/tests/utils.js @@ -119,6 +119,13 @@ export const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeo export const getUrl = exec(() => window.location.href) +export const getNumSyntheticListeners = exec(() => { + return Object.keys(window.__eventBus.$e).map(key => window.__eventBus.listenerCount(key)) + .concat(window.__resizeListeners.size) + .concat(Object.keys(window.__delegateCallbacks).length) + .reduce((a, b) => a + b, 0) +}) + export const getMediaScrollLeft = exec(() => document.querySelector('.media-scroll').scrollLeft || 0) export const getActiveElementClassList = exec(() =>