Safari doesn't garbage collect the registered listeners when a popup is closed, leaking all objects used by the listener, unless you manually remove the registered listeners. This is happening with an extension using Manifest V2 and a persistent background page. Tested in Safari 16.4 on an Apple Silicon Mac with OS Ventura 13.3.1. Also tested the latest Safari Technology Preview (169) and the issue happens there as well. The leak doesn't appear in other browsers like Chrome or Firefox. In them, all the listeners are destroyed when the popup is closed, without requiring manual removal. I have a small reproduction on this repo, created from the Xcode template: https://github.com/dani-garcia/safari_leak_repro https://github.com/dani-garcia/safari_leak_repro/tree/main/Shared%20(Extension)/Resources The changes needed to create this leak were: 1- Making the manifest version V2 and the background page persistent 2- Adding a call to onMessage.addListener to the popup.js file like this: > // Allocate some memory to make the leak more obvious, and use it > // inside the message listener to see that it's not garbage collected > const useSomeMemory = new Uint8Array(50 * 1024 * 1024); > > browser.runtime.onMessage.addListener(() => { > console.log(useSomeMemory[0]); > }) With that, each time you open the popup window you can see the memory usage of the extension in the activity monitor go up, and never be freed, to the point where if you open and close the popup dozens of times the memory usage can shoot up to gigabytes in size. If you load this same extension in Chrome, memory usage is stable regardless of how many times you open the popup.
<rdar://problem/109434587>