Skip to content

fix(dom): include shadow-DOM form elements when offsetWidth/Height === 0#39

Draft
caffeinum wants to merge 2 commits into
webllm:mainfrom
caffeinum:fix/shadow-dom-form-elements
Draft

fix(dom): include shadow-DOM form elements when offsetWidth/Height === 0#39
caffeinum wants to merge 2 commits into
webllm:mainfrom
caffeinum:fix/shadow-dom-form-elements

Conversation

@caffeinum
Copy link
Copy Markdown
Contributor

Summary

isElementVisible in src/dom/dom_tree/index.js hard-fails when offsetWidth === 0 || offsetHeight === 0. Shadow-DOM-hosted form elements (commonly seen in web components like Stripe Elements, password manager extensions, custom input widgets) frequently report offsetWidth/Height = 0 even when they're real interactive elements visible on screen. The agent then can't see them in the element index and can't interact with them.

Fix

Add a SHADOW_DOM_FORM_TAGS whitelist (input, select, textarea, button) and an isInsideShadowDom() helper. In buildDomTree, if an element is a form tag inside a shadow root, treat it as visible regardless of offsetWidth/Height — its actual visibility is governed by the shadow host's layout, not the element's own offset box.

Reference: Python upstream

Python browser-use no longer uses an in-page buildDomTree.js; visibility is computed server-side via CDP DOMSnapshot in browser_use/dom/service.py::is_element_visible_according_to_all_parents (L242-336). It checks display/visibility/opacity + snapshot_node.bounds, NOT offsetWidth/Height. Shadow roots are walked separately (L866-882) and pass through the same visibility func. Notably, the python file has a debug log at L897-912 explicitly flagging form elements inside iframes/shadow trees with missing bounds — so the failure mode is known upstream but unfixed there too (different code path, separate problem).

So this is not a port of an existing python fix; it's a TS-side fix for an analogous gap. Framing it as parity would be inaccurate — framing it as a fresh bug fix for shadow-DOM form discovery is correct.

Test plan

  • Manually exercise an existing repro page with shadow-DOM form inputs (Stripe Elements, web-component password fields)
  • Verify shadow-DOM <input> / <select> appear in the element index when their offsetWidth/Height = 0
  • Confirm non-shadow elements still respect the offsetWidth/Height = 0 invisibility check

🤖 Generated with Claude Code

caffeinum and others added 2 commits May 19, 2026 12:25
`isElementVisible` in the in-page DOM walker hard-fails when
`offsetWidth === 0 || offsetHeight === 0`. Shadow-DOM-hosted form
elements (e.g. Stripe Elements, password manager extensions, auth0
login widgets, custom input components) commonly report 0 dimensions
on the inner control even when they're real interactive elements
visible on screen — visibility is governed by the shadow host's
layout, not the element's own offset box. The agent then can't see
them in the element index and can't interact with them.

Add a SHADOW_DOM_FORM_TAGS whitelist (input, select, textarea,
button, a) and an isInsideShadowDom() helper. In buildDomTree, if an
element is a form tag inside a shadow root, treat it as visible+top
so isInteractiveElement runs and it lands in selector_map regardless
of offsetWidth/Height.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…covered

Adds a regression test for the SHADOW_DOM_FORM_TAGS / isInsideShadowDom
exception in src/dom/dom_tree/index.js. The test:

  1. Navigates (via data: URL — about:blank short-circuits selector_map)
     to a page hosting a shadow root that contains an <input> and a
     <button>, both styled width:0; height:0; display:block so they
     report offsetWidth/Height === 0 while remaining rendered.
  2. Sanity-checks the offset dimensions to confirm the bug surface
     (offsetWidth=0 with display !== none) is actually exercised.
  3. Asserts the shadow-DOM <input> and <button> reach selector_map.

Verified failure-on-baseline by checking out upstream/main's version of
src/dom/dom_tree/index.js (which lacks the fix) and re-running the test:
the new "discovers shadow-DOM input with offsetWidth/Height = 0" case
fails with "expected 0 to be greater than 0", proving the test
genuinely exercises the bug. Restoring HEAD's version makes it pass.

Also adds a guard test ensuring the whitelist stays a whitelist — a
plain <div> with offsetWidth=0/Height=0 inside a shadow root must NOT
be promoted by the shadow-DOM exception.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant