Skip to content

Instantly share code, notes, and snippets.

@thomasleveil
Last active October 17, 2022 07:44
Show Gist options
  • Save thomasleveil/c280d8a6f77682a2d15c11e0e11846a8 to your computer and use it in GitHub Desktop.
Save thomasleveil/c280d8a6f77682a2d15c11e0e11846a8 to your computer and use it in GitHub Desktop.
getEventListenersStats() Chrome bookmarklet

getEventListenersStats() Chrome bookmarklet

Because I had a hard time finding the cause of a memory leak, I ended up making this bookmarlet to help find evidence of a memory leak caused by event listener not being removed on a webpage.

Once this bookmarklet is activated on your webpage, you will be able to call the getEventListenersStats() from the Chrome DevTools Console. This function will give you stats about all events listeners and handlers.

How to install ?

Follow the instruction on http://htmlpreview.github.io/?https://gist.githubusercontent.com/thomasleveil/c280d8a6f77682a2d15c11e0e11846a8/raw/install.html

How to use ?

  • run getEventListenersStats()
  • do some action you suspect will leave event listeners behind
  • run getEventListenersStats()
  • compare the stats
window.getEventListenersStats = function(selectorOrNode) {
var domElements = [];
if (selectorOrNode instanceof Node || selectorOrNode instanceof Window) {
domElements = [selectorOrNode];
} else {
domElements = Array.from([window, document, ...document.querySelectorAll(selectorOrNode || '*')])
}
return domElements.reduce(function(pre1, dom){
var listeners = getEventListeners(dom);
var eventTypes = Object.keys(listeners);
var [handlersByType, nbHandlers] = eventTypes.reduce(function([preHandlersByType, preNbHandlers], eventType) {
var nbHandersForThisType = listeners[eventType].length;
if (!(eventType in preHandlersByType)) {
preHandlersByType[eventType] = 0;
}
preHandlersByType[eventType] += nbHandersForThisType;
preNbHandlers += nbHandersForThisType;
return [preHandlersByType, preNbHandlers];
}, [pre1.handlersByType, 0]);
pre1.handlersByType = handlersByType;
pre1.handlers += nbHandlers;
pre1.domElementWithListeners += nbHandlers > 0 ? 1 : 0;
return pre1;
}, {
domElementWithListeners: 0,
handlers: 0,
handlersByType: {}
})
};
console.info(`%c🦄 getEventListenersStats()
%cUsage: %cgetEventListenersStats(<optional: domNode>)
%cMore info at https://gist.github.com/thomasleveil/c280d8a6f77682a2d15c11e0e11846a8/`,
"background: yellow; color: blue; font-size: 18pt",
"font-size: 16pt; font-weight: bold",
"color: darkgray; font-size: 14pt; font-family; Consolas",
"color: lightgray; font-size: 12pt"
);
alert("You can now use `getEventListenersStats()` in the Chrome console");
<html>
<head>
<title>`getEventListenersStats()` Chrome bookmarklet</title>
</head>
<body>
<h1>`getEventListenersStats()` Chrome bookmarklet</h1>
<p>Just drag this link to your bookmark bar in Chrome.</p>
<p>
<a id="myBookmarklet1" href="javascript:alert('💩 something went wrong')"><button>getEventListenersStats()</button></a>
</p>
<script>
var linkId = "myBookmarklet1";
var gistLink = "https://gist.githubusercontent.com/thomasleveil/c280d8a6f77682a2d15c11e0e11846a8/raw/index.js";
fetch(gistLink).then(function(response) {
if (!response.ok) {
//alert("Error fetching "+response.statusText);
}
else {
response.text().then(function(text) {
var link = document.getElementById(linkId);
link.href = "javascript:"+encodeURIComponent("(function(){"+text+"})()");
});
}
});
</script>
<h2>Source code & Howto</h2>
<a href="https://gist.github.com/thomasleveil/c280d8a6f77682a2d15c11e0e11846a8/">https://gist.github.com/thomasleveil/c280d8a6f77682a2d15c11e0e11846a8/</a>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment