fix(mobile): reject stale refs after transition refresh
SH
2h ago+47+47+01234567890123456789-7-7-0123456789
What and why
- When a transition refresh no longer lists the same control, fail with retryable
NODE_STALEbefore sending input. The existing locator loop resolves the selector again within its timeout. - Clarify that contract in
settled()andrelocated(), remove the repeated inline comment, and describe the user-visible result in one sentence. - Related: #1297 determines when keyboard changes require a refresh. This PR handles a target disappearing or changing during that refresh. They address different contracts and overlap in
relocated(): merge this fix first, then retain its stale check when rebasing #1297. A disposable checkout combining the runtime fixes passed all 367 mobile unit tests after resolving the binding-argument overlap; neither adds an input retry after possible dispatch.
Issue
Closes #1299.
Verified
Ran it locally: no new device run for this documentation-only follow-up.
Head: 1454929f42e405ff99823c89163abe7e6cf8146d.
pnpm check passes; all 344 mobile unit tests pass. Fresh-context review has no important or critical findings. Runtime behavior is unchanged by the review follow-up.
The existing scripted-client regressions cover both a disappearing target and a reused native reference. The independent review at c076670 confirmed they fail with surface.ts reverted to main and pass with the fix:
| Scenario | Main | This PR |
|---|---|---|
| Target absent after refresh | Dispatches stale binding | NODE_STALE, no input |
| Old reference reused by another control | Dispatches wrong binding | Locator resolves intended control again |
The earlier downstream device evidence is private and is not attached. It established compatibility, not deterministic elimination of every navigation race. No upstream benchmark or Android device pass is claimed.