Description
Reproducible Code
### Summary
While investigating Appium hybrid iOS failures after WebView refresh/restart, we found what appears to be a browser-side memory retention pattern in Selenium precompiled atoms used by remote-debugger integrations.
Specifically, `find_element_fragment` / `find_element` / `find_elements` atom flows serialize returned DOM nodes into element references by storing them in `document.$wdc_` via `tc(...)`/`Xf(...)`-style cache functions. The cache appears append-only unless a specific cached id is looked up again and found stale. In dynamic pages (frequent DOM recreation, refresh, WebContent restarts), this can retain detached nodes and grow memory over long sessions.
This is especially visible with frequent XPath lookups.
### Original report context
- Appium issue: [appium/appium#22178](https://github.com/appium/appium/issues/22178)
- Comment referencing XPath/find-element timeout behavior: [issue comment](https://github.com/appium/appium/issues/22178#issuecomment-4258153148)
### Observed behavior
- Repeated `findElement`/`findElements` on dynamic pages gradually increases browser process memory.
- In long-running sessions (especially real iOS hybrid apps), memory growth correlates with later lookup instability/timeouts.
- XPath usage amplifies the effect because multi-match snapshots can create many cached element ids quickly.
### Why this looks like an atom-level retention issue
From the precompiled atoms path:
1. `find_element*` returns DOM node(s).
2. Result serialization path wraps node(s) as WebDriver element refs.
3. Wrapper stores node references in `document.$wdc_` map (`:wdc:<id> -> node`).
4. Entries are not proactively pruned; stale cleanup is mostly opportunistic (on future dereference of that exact id).
This means detached nodes may remain strongly referenced by the cache and avoid GC.
### Expected behavior
- Element cache should not retain unbounded references to detached DOM nodes.
- Long sessions with repeated find operations should not show monotonic memory growth from atom cache retention.
- Cache management should be bounded and/or sweep stale entries proactively.
### Minimal repro idea
1. Open a page that re-renders or fully refreshes DOM periodically.
2. Run loop:
- execute `findElements(By.xpath(...))` repeatedly (including broad XPath).
- optionally trigger periodic refresh/navigation.
3. Observe browser process memory over time.
4. Compare with CSS/id single-match lookups and with reduced lookup frequency.
### Suggested directions
- Add bounded cache policy for atom-side node cache (`$wdc_`) (size limit / LRU).
- Perform periodic stale sweep of cached nodes (detach check with capped batch size).
- Consider cache reset on navigation/refresh boundaries where safe.
- Add diagnostics hook: report cache size / stale ratio for debugging.
- Add stress test to prevent regressions (repeated XPath queries + DOM churn, assert no unbounded growth).
Debugging Logs
### Notes
- This report is not claiming XPath evaluator internals are leaking by themselves.
- The likely hotspot is element-reference cache retention in atom serialization of found nodes.
Description
Reproducible Code
Debugging Logs