You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Event replay: early event contract listeners on <body> are never removed after hydration #71518
This script adds listeners to <body>. They store each event in a queue, window._ejsas[appId].q, so Angular can replay events that happen before the app has loaded.
After hydration, Angular replays this queue once and sets window._ejsas[appId] to undefined. From then on, Angular handles events with its own listeners.
But the inline script's <body> listeners are never removed. They keep pushing every event into the same queue, and nothing reads it again. Each entry holds the event and its target element. So:
the queue grows with every click, for the whole life of the page;
elements removed from the page later (for example, after a route change) can't be garbage collected if they were ever clicked.
Cause
In packages/core/src/hydration/event_replay.ts, initEventReplay() replays the early events and calls clearAppScopedEarlyEventContract(appId), but never calls removeAllAppScopedEventListeners(appId). The same happens in the appRef.onDestroy() callback, for an app destroyed before it becomes stable.
For comparison, EventContract.replayEarlyEvents() in @angular/core/primitives/event-dispatch removes the early listeners right after it replays the events.
there's no error, memory grows because every event after hydration is added to `window._ejsas[appId].q` (captured by the early <body> listeners), and nothing reads or clears it
Please provide the environment you discovered this bug in (run ng version)
Activity
fix(core): remove early event listeners after replay
fix(core): remove early event listeners after replay
fix(core): remove early event listeners after replay
fix(core): remove early event listeners after replay