Skip to content

test(Button): time a touch release from its animation's late start - #10975

Merged
cixzhang merged 3 commits into
meta:mainfrom
vjeux:test/touch-release-due-time
Nov 10, 2026
Merged

cixzhang merged 3 commits into
meta:mainfrom
vjeux:test/touch-release-due-time

Conversation

@vjeux

@vjeux vjeux commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Maintainer impact

On a loaded runner, the touch press test outside a scroller, a finger’s press highlights in the frame it lands, and the lift fades it on the shared release clock fails on a raw toBeLessThan. The load was a 2-CPU quota with 4 workers and 2 busy loops. Main failed the test 3 of 10 and 0 of 20 times in Chromium. It failed 4 of 10 and 6 of 20 times in WebKit. The release left 210–291 ms (Chromium) and 211–418 ms (WebKit) after the fading write, against a 205 ms bound.

Intended invariant

The press controller ends a release at the later of two times. One is its clock: the theme's exit duration from the fading write. The other is the end of the release animation. A busy page starts that animation late (endAfterRelease in utils/pressFeedback.ts). The test holds the release to that due time with its existing slack. A run on a starved page fails by name.

Change

Test only, in ButtonPress.interaction.browser.spec.ts:

  • The page stamps the press attribute's fading write and its removal as the press controller makes them. A mutation record arrives later on a busy page. One WebKit run measured a 115 ms release that way.
  • It keeps the release animations from each frame. As the press controller does, it counts only finite CSS animations on the button, or on a part no nested press owner holds. It reads their end at the removal, because the removal cancels them and clears their start times.
  • The release is due at the later of the clock and the animation's end. The bounds stay: at least the clock minus 5 ms, and less than 80 ms (now RELEASE_SLACK_MS) after the due time.
  • When the release ended late and the page drew no frame in those 80 ms, requireFrames throws FrameStarvationError.

Evidence

  • Failure before the change: the raw failures above, on main a1fda63.
  • Success after the change: under the same profile, Chromium 20 of 20 and WebKit 16 of 20 pass. The other 4 WebKit runs fail by name: no frame came for over 80 ms after the release was due.
  • Product/runtime behavior verified unchanged: no product file changes. A product mutant that ends the release 100 ms late fails the new test on its bound, 3 of 3 per engine.
  • CI impact: none. The change is test only.

Scope

Components: Button

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

  • Pressure profile: the Playwright v1.61.1 image in podman, with --cpus=2 on two pinned CPUs and CI=1. It ran 4 workers and 2 busy loops on the same CPUs, with --retries=0.
    • Main, --repeat-each=10: Chromium 3 failed (received 209.8, 230.1, 291.1 against < 205), WebKit 4 failed (387, 388, 397, 418).
    • Main, --repeat-each=20: Chromium 20 passed; WebKit 6 failed (211, 224, 231, 232, 262, 296).
    • This head, --repeat-each=20: Chromium 20 passed; WebKit 16 passed, 4 failed with FrameStarvationError.
  • A probe on main under the same profile: in Chromium the release animation started up to 80 ms after the fading write. The release ended 9–21 ms after the animation's end, and a control timer fired at most 5 ms late. WebKit drew frames 82–197 ms apart.
  • CI profile: Chromium pinned with 1 worker, and WebKit in the CI container with 1 worker. The test passed 10 of 10 per engine. The whole spec passed 7 of 7 in Chromium and 5 of 5 in WebKit.
  • Mutant, release ended 100 ms late: 3 of 3 failures per engine on toBeLessThan(RELEASE_SLACK_MS) (received 91.8–101).
  • At 0691138, which keeps only finite release animations: the test passed 5 of 5 per engine in the CI profile. The whole spec passed 7 of 7 in Chromium and 5 of 5 in WebKit. The release mutant failed 2 of 2 in Chromium (87.7, 88.0).
  • An infinite CSS animation added inside the button, with the release mutant: 0691138 fails 2 of 2 per engine on the bound (86.4–97). The previous head passed it, because its due time was infinite.
  • Lint and Prettier clean.

A busy page starts the release animation late, and the press
controller then ends the release at that animation's end. The test
timed the release from the `fading` write alone, so it failed raw
under load.

The test now stamps the press attribute's writes as the controller
makes them, and reads the release animation's end before the removal
cancels it. It holds the release to the later of the two due times,
with the same 80 ms slack. A late end on a page that drew no frame in
that slack fails by name, as frame starvation.
@vercel

vercel Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 10, 2026 6:03pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 10, 2026
@astracat-bot

astracat-bot Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 10, 2026, 6:08 PM UTC

@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 892917e

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC Visual · A11y · RTL
Button · Storybook 61.2 kB (0) · 10.0 kB CSS (0) 690 (0) ✓ · ✓ · ✗

Package size: no published package changed; no new dependencies.

API changes: none in this pull request

Committed API report behind this build: cli 36 rows, core 36 rows; run pnpm api:report.

Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. It is a draft from a fork, so CI starts once the pull request is marked ready for review and a maintainer adds the ci:run label.

The new due time matches how the press controller ends a release: the later of the exit clock and the end of a late-started release animation. In a Chromium check, the new bound passed a release whose animation started 150 ms late, which the old bound failed. It still failed a release that ended 100 ms late. One non-blocking hardening note is inline.

[Automated review]

@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 10, 2026
The release check kept every CSS animation in the button. An
infinite one, such as a spinner, made the due time infinite, so both
late checks passed without testing anything. The check now keeps
what the press controller waits for: finite CSS animations on the
button, or on a part that no nested press owner holds.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. The pull request is a draft, so its CI run starts when it is marked ready for review; it already carries the ci:run label.

The new due time matches how the press controller ends a release: the later of the exit clock and the end of a late-started release animation, counting only the finite animations the controller waits for. In a Chromium check, the new bound passed a release whose animation started 150 ms late, which the old bound failed, and it still failed a release held 100 ms late, also with an infinite animation or a nested press owner inside the button. The earlier note about infinite and nested animations is resolved.

[Automated review]

@vjeux
vjeux marked this pull request as ready for review November 10, 2026 17:20
@vjeux
vjeux marked this pull request as draft November 10, 2026 17:47

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. The pull request is a draft, so its CI run starts when it is marked ready for review; it already carries the ci:run label.

The new due time matches how the press controller ends a release: the later of the exit clock and the end of a late-started release animation. On this head, after the merge of main, the new bound passed a release whose animation started 150 ms late, which the old bound failed, and it still failed a release held 100 ms late.

[Automated review]

@vjeux
vjeux marked this pull request as ready for review November 10, 2026 18:30
@cixzhang
cixzhang merged commit ba460c0 into meta:main Nov 10, 2026
127 checks passed
@vjeux
vjeux deleted the test/touch-release-due-time branch November 10, 2026 19:07

This branch was successfully deployed

1 active deployment
Preview — 892917e6 Deployed Nov 10, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants