Skip to content

feat(native): the tree view and aria-refs, into cross-site iframes too (phase 4) - #11

Merged
unohee merged 1 commit into
masterfrom
feat/native-snapshot
Oct 25, 2026
Merged

unohee merged 1 commit into
masterfrom
feat/native-snapshot

Conversation

@unohee

@unohee unohee commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Stacked on #10 (phase 3), which is stacked on #9 (phases 1–2). This is phase 4 of the plan.

What

  • native/snapshot.py builds the tree from Accessibility.getFullAXTree, one frame at a time. Its output follows Playwright's aria_snapshot(mode="ai", boxes=True) format, so compact_snapshot reads it unchanged.
    • Chrome's internal roles are mapped back to the ones Playwright prints.
    • A link's /url is the href attribute as written.
    • Boxes are given in the element's own frame, as Playwright gives them.
    • Refs are e<n> in the top frame and f<k>e<n> inside frames. Each snapshot replaces the page's ref table.
  • native/frames.py auto-attaches out-of-process iframes and maps each frame to the session that controls it, nested OOPIFs included. For an element inside an OOPIF, the offset of the owner <iframe> is added to its coordinates, so input lands in the right place.
  • native/locator.py
    • Each element carries its frame and session through every action.
    • An aria-ref resolves in the ref's own frame.
    • An unknown or stale ref matches nothing.
    • A ref into a frame that no longer exists raises Invalid frame in aria-ref selector, which the tools report as not_found.

Verified

  • pytest: 1745 passed. The two pre-existing macOS sha256sum failures were deselected.

  • tests/native: 82 tests.

  • testing/native_tree_parity_261023_v1.py passes headless and headful (headful run twice):

    check result
    read_page(mode="tree"), native vs. playwright driver the same 75 elements, in the same in-view order
    click by ref: top frame, same-site iframe, cross-site OOPIF all three clicked
    Korean typed into an OOPIF field by ref, then submitted value arrived and submitted
    a ref taken before a navigation not_found
  • The phase 1–2 smoke and the phase 3 smoke still pass.

…o (phase 4)

read_page(mode="tree") now runs on the native driver, and click /
type_text / any element tool take its aria-refs.

- snapshot: Accessibility.getFullAXTree frame by frame, written as
  Playwright's aria_snapshot(mode="ai", boxes=True) so compact_snapshot reads
  it unchanged. Chrome's internal roles are mapped back (MenuListOption is an
  option, StaticText a text), a link's /url is its href as written (Chrome's
  tree has the resolved URL), boxes are in the element's own frame's
  viewport as Playwright gives them, and refs go to every rendered node with
  a box: e<n> in the top frame, f<k>e<n> in the k-th frame met. A snapshot
  replaces the page's ref table, so refs belong to the latest read.
- frames: out-of-process iframes are auto-attached (no waitForDebuggerOnStart,
  as for tabs: cdp_guard holds them) and every frame maps to the session that
  speaks for its document; nested OOPIFs included. Coordinates from an OOPIF
  session get the owner <iframe> content boxes added on the way out, so input
  lands where it should in the window.
- locator: elements carry their frame (and session) through every action;
  an aria-ref selector switches to the ref's frame, an unknown or stale one
  matches nothing, and one into a frame that is gone raises Playwright's
  "Invalid frame in aria-ref selector" (read as not_found).

Verified: pytest 1745 passed (2 pre-existing macOS sha256sum failures
deselected); tests/native 82; testing/native_tree_parity_261023_v1.py,
headless and headful (headful twice): read_page(mode="tree") on the native
and the playwright driver gives the same 75 elements in the same in-view
order; refs click a button in the top frame, in a same-site iframe and in a
cross-site OOPIF, type Korean into an OOPIF field and submit it, and a ref
from before a navigation answers not_found. The phase 1-2 and phase 3
smokes still pass.
@unohee
unohee force-pushed the feat/native-snapshot branch from 1f9d938 to 95aa236 Compare October 25, 2026 03:59
@unohee
unohee changed the base branch from feat/native-locators to master October 25, 2026 03:59
@unohee
unohee marked this pull request as ready for review October 25, 2026 03:59
@unohee
unohee merged commit 629579b into master Oct 25, 2026
4 checks passed
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