Repository navigation
test(interaction-harness): a paced touch play keeps its spacing after a stalled dispatch and reads the release the page read - #9725
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
There was a problem hiding this comment.
This looks ready to approve: the paced touch play, the release check and the shared input recorder stay inside the private interaction harness, Core's velocity tracker stays unexported, and the new unit and WebKit self-tests cover the pacing rule, both stall attributions and the stopped wheel step.
One optional follow-up:
- The Core cross-check guards the copied release weight but not the stillness interval: every gesture lifts 8 to 16 ms or 88 ms after its last move, so a harness
TOUCH_STILLNESS_MSanywhere from 16 to 87 ms passes all seven cases; a lift exactlyUIKIT_VELOCITY.stillness.valueafter the last move and one 1 ms later, or a direct check of both constants againstUIKIT_VELOCITY, would keep that copy in sync too.
[Automated review]
| 'a rest before the lift': { | ||
| samples: [ | ||
| [100, 50, 0], | ||
| [116, 50, 16], | ||
| [132, 50, 32], | ||
| ], | ||
| lift: 120, | ||
| }, |
There was a problem hiding this comment.
Non-blocking: every other gesture lifts 8 to 16 ms after its last move, so with this one at 88 ms a harness TOUCH_STILLNESS_MS anywhere from 16 to 87 ms passes all seven cases, and a drift from UIKIT_VELOCITY.stillness would go unnoticed. A gesture that lifts exactly UIKIT_VELOCITY.stillness.value after its last move and one that lifts 1 ms later, or a direct expect(TOUCH_STILLNESS_MS).toBe(UIKIT_VELOCITY.stillness.value), would cover it.
…ing after a stalled dispatch WebKit's injected touches carry their real dispatch time, so the page reads a release velocity from when the moves arrive. Under a CPU quota a dispatch command stalls and real-time pacing then sends the moves behind it back to back, which reads as a far faster finger. `pacing: 'spacing'` keeps the script's spacing instead: each event leaves its interval after the one before it, or after that dispatch returned when it outlasted the interval, and a gap that reaches the release filter's 40 ms stillness interval fails the play as TouchPacingError once the lift is out. The default stays as it was.
…ad, fails a resting finger, and names a page that held a touch - The pacing check reads what the release velocity reads: the lifting finger's last two move intervals, blended as core blends them, and the lift's gap against the stillness interval (strictly longer). An earlier stall leaves the release intact and no longer fails the play. A page that read a resting finger fails it. A release that strays from the script's fails it only under the proof's own `releaseTolerance`: WebKit delivers touches at its own cadence, so a flick scripted at 120 Hz reads anywhere from a third to more than twice its speed. The lift's `PlayedEvent.release` names the release the page read beside the script's. - The page's own arrival stamps and handling times decide it, read by window listeners before and after the page's own. A gap the page's listeners held (they spent longer than the script's interval on the event before, and that handling accounts for the gap) fails as TouchPageStallError, the proof's own failure; any other as TouchPacingError, the runner's.
…t recorder `armInputRun(page, types)` records, for each trusted event of the given types, its stamp, when the page received it and when the page's own listeners finished with it. It replaces the wheel driver's recorder and the touch probe's copy of it. Each event keeps its own record, so events that interleave cannot overwrite each other's marks. An event whose propagation the page stops is marked by a task queued when it arrived, and never later than the next event's arrival.
…eners too A gesture host samples a finger from pointermove, and WebKit stamps a touch event only once the page's pointer listeners are done. The probe now records each step's pointer events with its touch event, and `touchArrivalsFrom` gives the step the earliest stamp and the latest handling of them. So a page whose pointer listener holds each move reads as the page's rest (`TouchPageStallError`), where the touch events alone showed no fault. A WebKit self-test spins a pointermove listener for 60 ms: the touch-only probe let the play resolve; it now fails as the page's.
…elocity tracker reads it `readRelease` now reads both the page's stamps and the script's times through Core's filter: only moved samples count, a sample at the newest moved sample's time replaces it, and an interval across no time reads 0. With fewer than two moves after the touch-down, or after a rest past the stillness interval, the release is 0. Both readings use the same positions, rounded once, as WebKit delivers whole pixels. Two moves that share a stamp no longer read Infinity, a single move reads 0, and a page that read every move at one stamp fails with the new `moves` kind. A late lift after a single move is no rest: one move releases at 0 for the script and the page alike. Each reading keeps its own rest, so a page that does not rest where the script does fails with the `throw` kind. The filter is a copy of Core's, which the harness cannot call, so a Core unit test reads the same samples with both and compares them.
bc0a405 to
b9ee608
Compare
There was a problem hiding this comment.
This looks ready to approve: the paced touch play, its release check and the shared input recorder stay inside the private interaction harness, Core's velocity tracker stays unexported, and the new unit and WebKit self-tests cover the pacing rule, both stall attributions and the stopped wheel step.
One optional follow-up, still open from the earlier review:
- The Core cross-check guards the copied release weight but not the stillness interval: a harness
TOUCH_STILLNESS_MSanywhere from 16 to 87 ms passes all seven cases, so a gesture that lifts exactlyUIKIT_VELOCITY.stillness.valueafter its last move and one 1 ms later, or a direct check of both constants againstUIKIT_VELOCITY, would keep that copy in sync.
[Automated review]
Maintainer impact
WebKit stamps an injected touch when it arrives, so the page reads a release velocity from arrival times. After a stalled dispatch, real-time pacing sent the rest of a flick back to back: a 900 px/s flick read as 4,000 px/s or more, and its coast ended before a busy block could judge it (4 of 20 runs of the Slider coast proof). This keeps a paced play's spacing, and names whose fault a stray release is. #9545 is the cast-step half.
Evidence
pacing: 'spacing'.touchmoveorpointermovelistener that holds the main thread fails a paced flick asTouchPageStallError; thepointermovecase passed under touch-only timing. A wheel listener that stops each step went from a re-taken runner stall toWheelPageStallError(3 of 3).VelocityTrackerand with the harness and finds them equal; a copy with another weight fails four of them.internal/interaction-harnessand one Core test change.Intended invariant
A paced play fails only when the page read another release than the script throws, and names whether the page or the runner caused it. A play without
pacing: 'spacing'behaves as before.Change
pacing: 'spacing': each event leaves its interval after the one before, or after a late dispatch returned, so a stall stretches one gap.armInputRun, shared with the wheel path, records each touch and pointer event and when the page finished with it, a stopped one included. The play reads each release as Core's velocity tracker does. It fails a page whose rest differs from the script's, or that read fewer than two moves. A stray release fails only underreleaseTolerance.TouchPageStallErrorwhen the page's listeners held the gap, else the runner'sTouchPacingError.This supersedes #8910's pacing half. #9694 moves the Slider's WebKit busy proof onto this and #9545.
Scope
Testing
Local gates at b9ee608, on
mainbd69bed: typecheck,CI=true pnpm lint(no errors, and no warnings in changed files), Prettier,check:knowledge, changeset coverage (nothing ships), the node suite (16,297 passed), the harness's and Core's gesture unit tests (919, the Core cross-check among them), and the harness's browser self-tests in Chromium on a 2-thread pin (one physical core) at four workers (110 passed, 3 skipped) and in WebKit in the CI job's container profile (100 passed, 13 skipped). Every commit passes the harness's typecheck and unit tests on its own.