perf(ios): read each resolved text input through one snapshot
Merged
TH
1h ago+489+489+012345678901234567890123456789-236-236-012345678901234567890123456789
Summary
Each attribute read from a live XCUIElement re-runs its query, and each query snapshots the whole app. A fill made 35 queries. Now:
- Every resolver returns
ResolvedTextEntryInput(element + snapshot). It owns the exists-first and snapshot-first reads. Value, frame, identity, and the baseline come from that snapshot. The point lookup's snapshots also answer identity, so its consumers stop probing again. TextEntryReaderowns reuse:input()hands out the last read untildispatch { }runs, which wraps every post, tap, and pause. The focus step's post-focus read seeds it. A bound target refuses a replacement input after any dispatch.
Read-back, unconfirmed evidence, identity refusal, the tap witness, textEntryRoute, and the penalized route are unchanged. 12 runner files. The fixture gains a value-read counter and an on-demand input replacement.
Validation
pnpm check:affected --run --head 737fa35cbc: passed,exactCommit: true. GitHub owns the Swift and smoke lanes.- 121 runner tests (text entry, input probe, typing, command execution, interaction) pass at 737fa35cbc, iPhone 17 Pro iOS 27.0 simulator.
- The query-count test reads 35 on main, 19 at 2d345058e9, and 17 now (pin โค 24).
- Mutation: a warmup pause that bypasses the reader fails
testFillFailsWhenAppReplacesMaskedInputWhileWarmupPauses(types23456into the successor). - Runner
typemedian ms, interleaved, 2d345058e9 โ 737fa35cbc: test-appfield-email3483 โ 3280; Bluesky Sign in 2910 โ 2767.
Risk: a fill can reuse a read only between dispatches; readiness's slow path pays one extra snapshot.
๐ค Generated with Claude Code