I had wrapped onBeforeRenderObservable.removeCallback() inside a hasObservers() check to avoid calling removeCallback unnecessarily. But then I noticed that there are situations where the observer would keep firing even though my remove function was called correctly.
It turned out that hasObservers() reported false even though my observer was still there.
If Observer.remove() is called more than once before the internal this._remove() timeout fires, it causes internal this._numObserversMarkedAsDeleted to incremented twice (once for both remove calls), so even after the observer is removed the counter remains positive.
Oh, and as a related note: While inspecting the source code trying to figure out what could cause this I noticed another potential case where this could happen. (Although that wasnât happening in my case.)
If notifyObserver() is called with an observer that isnât actually part of the Observable I believe that would also cause the increment counter to be stuck with too high value. Although I havenât verified this with actual code.
A good fix would be to make _deferUnregister() itself check for observer._willBeUnregistered === false before doing anything. That way even if in the future another âbadâ call of _deferUnregister() is added somewhere, it would not break the counter again.