RESOLVED FIXED320837
RemoteProgressBasedTimelineRegistry keeps empty source entries of threaded animations after a progress-based timeline changes source
https://bugs.webkit.org/show_bug.cgi?id=320837
Summary RemoteProgressBasedTimelineRegistry keeps empty source entries of threaded an...
David Kilzer (:ddkilzer)
Reported 2026-08-02 05:08:05 PDT
`RemoteProgressBasedTimelineRegistry::update()` keeps a map of progress-based timelines per process, keyed by the scrolling node that sources them: `m_timelines` maps a `ProcessIdentifier` to a map of `ScrollingNodeID` -> `HashSet<Ref<RemoteProgressBasedTimeline>>`. When an update reports a timeline whose source scrolling node has changed, `update()` finds the timeline under its former source, takes it out of that source's set with `takeIf`, and adds it to the set for the new source. The former source's set is left empty, but its entry remains in the per-process map. The only code that drops empty source entries is nested inside the loop over `timelinesUpdate.destroyed`. An update that creates or modifies timelines without destroying any timelines never executes that loop body, so every empty entry it left behind stays in the map. As a result, a page that repeatedly re-targets progress-based timelines accumulates one empty entry per abandoned scrolling node in the UI process. Because the per-process map never becomes empty, the trailing `if (processTimelines.isEmpty()) m_timelines.remove(processIdentifier);` never fires either, so the registry also retains state for a process whose timelines have all moved. The stale entries are dropped only if some later update for that process happens to destroy a timeline. There is no known functional symptom: `get()`, `updateTimelinesForNode()`, and `timelinesForScrollingNodeIDForTesting()` all treat an empty source entry the same as an absent one, so the effect is retained memory and bookkeeping rather than incorrect animation behavior. The change-source path was added in Bug 301501 (302282@main), which had no empty-entry cleanup. Bug 303655 (304042@main) added the empty-source cleanup, but placed it inside the loop over destroyed timelines, so it does not cover this case. Found by inspection while auditing remove-matching-entries loops (see Bug 320290, for example).
Attachments
Radar WebKit Bug Importer
Comment 1 2026-08-02 05:08:14 PDT
David Kilzer (:ddkilzer)
Comment 2 2026-08-02 18:12:51 PDT
EWS
Comment 3 2026-08-05 13:23:44 PDT
Committed 318657@main (2d3a7739eeee): <https://commits.webkit.org/318657@main> Reviewed commits have been landed. Closing PR #70719 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.