Three targeted fixes for pages with 5k+ elements:
1. build_snapshot_lookup: convert isClickable list to set before loop
_parse_rare_boolean_data used `index in list` (O(n) per call).
Called once per node = O(n²). Now O(1) via set lookup.
20k elements: 14,160ms → 2,973ms. 100k: 356s → 9s.
2. RectUnionPure: add _MAX_RECTS=5000 safety cap
Paint order rect union fragments exponentially with overlapping
layers. Uncapped, 20k elements took 372s. Capped: 4.7s.
Degrades gracefully (less aggressive filtering, same correctness).
3. Skip JS listener detection on pages with >10k elements
querySelectorAll('*') + per-element DOM.describeNode took 2.3s at 20k.
Elements still detected via accessibility tree + heuristics.
Combined effect at 20k elements: ~400s → ~16s (25x faster).
Normal pages (<5k elements) are completely unaffected.
Two additional performance fixes for heavy pages:
1. Hoist get_or_create_cdp_session() outside _construct_enhanced_node
Previously called once PER DOM NODE inside the recursive tree
construction. On a 100k-element page, this was 100k+ async
operations. Now resolved once before recursion starts.
2. Add _MAX_RECTS=5000 safety cap to RectUnionPure
The paint order rect union can fragment exponentially with many
overlapping translucent layers (each add() splits up to 4 rects).
Cap prevents memory/CPU explosion on complex pages.
Also: expanded stress test suite to 15 pages (up to 132k elements)
including shadow DOM + iframe combos, overlapping layers, cross-origin
iframes, and a 100k flat element test. All 15 pass.
Pages with very large DOMs (e.g. Stimulsoft designer with 20,000+
elements) cause the browser state capture to time out, making the
agent unable to interact with the browser.
Three targeted fixes:
1. Skip JS listener detection on heavy pages (>10k elements)
The querySelectorAll('*') + getEventListeners() loop followed by
individual DOM.describeNode CDP calls for each listener element is
O(n) and can take 10s+ alone on heavy pages.
2. Batch DOM.describeNode calls (chunks of 50)
Previously all calls fired at once via asyncio.gather, flooding the
CDP WebSocket and causing timeouts on concurrent operations.
3. Adaptive CDP timeouts based on page complexity
- >15k elements: 25s initial / 10s retry (was 10s/2s)
- >5k elements: 15s initial / 5s retry
- Normal pages: unchanged 10s/2s
Get pixel location of each iframe element that's out of the viewport, convert from pixels to number of page lengths, and provide that to the LLM as context
Elements in iframes beyond the 1000px viewport threshold are filtered from selector_map, causing agents to scroll blindly to find them. Add hints to the LLM context indicating hidden content
uses CDP Runtime.evaluate with includeCommandLineAPI to access getEventListeners() and mark elements with click/mousedown/pointerdown listeners before DOM snapshot capture
- Changed the type of the all_frames parameter to allow for None, enabling lazy fetching of cross-origin iframes only when necessary.
- Updated comments to clarify the behavior of all_frames during DOM tree construction.
- Improved the `create_task_with_error_handling` function to allow for better exception logging and retrieval based on the `suppress_exceptions` parameter.
- Updated `SessionManager` to implement event-driven recovery for stale agent focus, replacing polling with efficient event handling.
- Refactored session retrieval methods to ensure focus validation and recovery are handled automatically.
- Enhanced logging for recovery processes and session management to provide clearer insights into state changes and errors.
- Adjusted various watchdogs to utilize the new session management methods, ensuring they correctly handle focus validation and session retrieval.
- Eliminated the caching of target types in SessionManager, simplifying the management of target information.
- Updated various components to directly access target types from the Target objects, enhancing clarity and reducing redundancy.
- Adjusted related methods in BrowserSession, CrashWatchdog, and DomService to reflect the changes in target type retrieval.
- Updated DOMWatchdog to provide a detailed hierarchical breakdown of timing metrics for various operations, improving clarity in performance logging.
- Enhanced DomService to calculate and log specific timing metrics for iframe scrolling, CDP calls, and snapshot processing, contributing to more accurate performance tracking.
- Updated DOMWatchdog to exclude specific sub-timings from total tracked time to avoid double-counting.
- Enhanced DomService to calculate and log overhead timings for both get_dom_tree and get_serialized_dom_tree operations, improving accuracy in performance metrics.
- Introduced a utility function `create_task_with_error_handling` to manage asyncio tasks with proper exception logging and suppression options.
- Updated multiple components, including `SessionManager`, `BrowserSession`, and various watchdogs, to utilize the new error handling mechanism for background tasks.
- Enhanced overall robustness of asynchronous operations by ensuring exceptions are logged and handled appropriately, improving maintainability and debugging capabilities.
- Updated DOM tree retrieval methods to lazily fetch frame hierarchy only when necessary, improving performance for pages without cross-origin iframes.
- Adjusted method signatures to reflect optional frame fetching, enhancing flexibility in DOM service operations.
- Streamlined timing metrics by setting placeholders for timing logs, preparing for future performance enhancements.
- Updated DOM tree retrieval methods to include pre-fetched frame hierarchy, reducing redundant CDP calls and improving performance.
- Adjusted timing logs to provide detailed breakdowns of DOM tree construction, including total time and individual component timings.
- Removed commented-out code related to Python-based highlighting, streamlining the DOMWatchdog class.
- Reduced wait time in DOMWatchdog for page stability, enhancing responsiveness during DOM builds.
- Replaced instances of `agent_focus` with `agent_focus_target_id` across various components to ensure consistent target management.
- Enhanced error handling and logging in `Watchdog` classes to reflect the new target ID approach.
- Improved session retrieval methods to streamline interactions with the `SessionManager`, ensuring better performance and reliability.
- Updated the method of accessing iframe dimensions from dictionary-style to attribute-style for improved clarity and consistency.
- Ensured that width and height are directly accessed as properties of the bounds object.
- Updated logging statements to use multi-line formatting for better clarity.
- Ensured consistent spacing and formatting throughout the service to enhance code maintainability.