Repository navigation
fix: exact element match first; add elements idb axbridge drops on iOS 18+ - #52
Open
cryptotavares wants to merge 3 commits into
Open
cryptotavares wants to merge 3 commits into
cryptotavares wants to merge 3 commits into
Conversation
findElement returned the first element, in tree order, whose field
contained the query. On the MetaMask Android wallet home the query
{ identifier: 'account-picker' } matched the earlier
'account-picker-avatar' (inside the profile button), so taps opened the
profile screen instead of the account list.
findElement now returns an exact match anywhere in the tree first, and
falls back to the first fuzzy (case-insensitive, contains) match only
when there is none. matchesQuery takes an optional exact flag.
On iOS 18+ snapshots read idb --api axbridge. It can report a React Native container as one unlabelled view without children: on the MetaMask wallet home, the balance and the Buy/Swap/Send/Receive buttons, so wallet-send-button could not be found or tapped. --api ax lists them. When axbridge is the preferred backend, snapshot() now also reads ax, concurrently and best effort, and adds each ax element whose identifier is missing from the axbridge tree, as a leaf of the smallest element whose frame contains it. raw stays the axbridge output.
This was referenced Nov 2, 2026
cryptotavares
added a commit
that referenced
this pull request
Nov 2, 2026
Pins `.nvmrc` to Node.js `v24.22.1` instead of `lts/*`.
## Why
`lts/*` now resolves to Node 26 (26.13.0 became LTS on 2026-10-28). The
**Check workflows** job does not set a Node version, so it follows
`.nvmrc`, and on Node 26 its `yarn --immutable` step fails (3 retries),
which also fails **All jobs pass**:
```
node_modules/yargs/yargs:3
const {applyExtends, cjsPlatformShim, Parser, Yargs, processArgv} = require('./build/index.cjs')
ReferenceError: require is not defined in ES module scope, you can use import instead
Node.js v26.13.0
```
The allow-scripts install plugin runs `@lavamoat/allow-scripts` (3.4.3),
which does `require('yargs/yargs')`. In yargs 17.7.2 (locked) that is an
extension-less file in a `"type": "module"` package, which Node 26 no
longer loads with `require`.
| Run | Node | Check workflows |
| --- | --- | --- |
| #47, #48, #51 (Oct 29-30) | 24.22.1 | pass |
| #52 (Nov 2), and its re-run | 26.13.0 | fail |
Reproduced locally: `node
node_modules/@lavamoat/allow-scripts/src/cli.js --help` works on 24.22.1
and throws the same error on 26.13.0.
The build, lint and test jobs set their own matrix (20.x / 22.x / 24.x)
and are not affected. `engines` stays `^20 || ^22 || >=24`.
## Follow-up (not in this PR)
Node 26 support for the install tooling: `yargs` 17.7.3 points
`yargs/yargs` to a `.cjs` file and loads on Node 26 (checked locally),
so `yarn up -R yargs` (or `@lavamoat/allow-scripts` 5.x) would let
`.nvmrc` move to Node 26 later.
cryptotavares
marked this pull request as ready for review
November 2, 2026 17:57
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two element-lookup fixes found while validating
@metamask/client-mcp-core0.13.0 on MetaMask Mobile (MetaMask/metamask-mobile#38594). Both madetap_element/wait_formiss or hit the wrong element on the MetaMask wallet home.findElementreturned the first element, in tree order, whose field contained the query. On Android,{ identifier: "account-picker" }matched the earlieraccount-picker-avatar(inside the profile button), so the tap opened the profile screen instead of the account list.axbridgedrops elements (iOS 18+)idb ui describe-all --api axbridge. On the wallet home it returns the balance and the Buy / Swap / Send / Receive row as one unlabelled view with no children.wallet-send-buttonwas not found, andtap_elementtimed out.--api axlists those buttons.axbridgeis the preferred backend,snapshot()also readsaxat the same time (best effort). Eachaxelement whose identifier is not in theaxbridgetree is added as a leaf of the smallest element whose frame contains it.rawstays theaxbridgeoutput.Decisions
Sendvssendby tree order; equality is the clearest rule.axtogether withaxbridgeinstead of switching toaxaxbridgekeeps the full tree (170 nodes vs 46 foraxon the wallet home) and the structure other code relies on.axonly fills gaps.tap_element/wait_fortarget, and the identifier is how we detect "missing" without duplicates.axbridgeread already handles recovery. A failedaxread leaves the snapshot as before.axis preferred (iOS ≤ 17) or--apiis unsupportedNot in this PR: the iOS
dismissKeyboardfix (idb ui key RETURNrejected) is already in #48.Interaction with the open stack (#47 → #48 → #50 → #51)
Checked by merging this branch onto #51 (no git conflicts) and running the stack's proofs on iOS and Android:
reads idb describe once per connection for snapshots and tapsexpects 3describe-allcalls; with theaxsupplement it is 6 (each snapshot =axbridge+ax, run at the same time).idb describe --jsonstays at 1. With that change: 752 passed.main-action-button-contentinsidewallet-send-button) is inside the target frame, soclick --testid wallet-send-buttonpasses the hit-test and opens Send.scroll-to-elementworks on added elements (trending-token-row-item-…, 2 swipes, in viewport) and back towallet-send-button.describe-screenon the wallet home 11.4 → 17.9 kB (54 → 73 nodes), because the missing elements are now listed. Android: no change (only the match order differs).Review guide
src/utils/element.ts:findElement→findFirst(exact)thenfindFirst(fuzzy);matchesQuerygets an optionalexactflag (defaultfalse, so existing callers are unchanged).src/backends/idb-backend.ts:snapshot()starts theaxread before the main read;#describeAllnow takes the API order and returns which API succeeded;addMissingIdentifiedElementsdoes the merge.src/utils/element.test.ts(exact over partial, fuzzy fallback, multi-field) andsrc/backends/idb-backend.test.ts(merge placement, no duplicates,axfailure, no supplement on iOS ≤ 17). One existing test now countsaxbridgereads instead of matching the whole list, because the concurrentaxread is also adescribe-allcall.Testing
yarn lint: pass.yarn test: 694 passed, 6 skipped.client-mcp-corerelease/0.13.0(its 1835 tests pass) and into the MetaMask MobilemmCLI (chore(llm-workflow): upgrade to @metamask/client-mcp-core 0.13.0 and @metamask/device-mcp 0.7.0 metamask-mobile#38594, 219 tests pass), dev build 8.20.0, read-only flows (nothing sent or signed):wallet-send-buttonin snapshotmm click --testid wallet-send-buttonmm click <ref>on Sendmm click --testid wallet-receive-buttonmm click --testid account-pickermm click --testid account-pickermm click <ref>on the account pickermm click --testid profile-buttonmm click --testid wallet-send-button