Files
Charlie CheeverandClaude Opus 5.5 a60c83e5be The README and guides cite the private design record by number and no longer link into it
The design record (llp/) is a separate, private repository, so every link into
it was a 404 for a reader of this one. Links become citations by number,
the README says once that the record is private and that the guides under
docs/ are the public documentation, and sentences that sent a reader to a file
under llp/ now name what they can open instead or are dropped.

Fixes #70.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-11 01:31:48 -08:00
..

Timer wait points: the platform behavior LLP 1147 rests on

LLP 1147 lets a Contract timer wait for the next frame, a UI update in progress, the end of a scroll, or idle. Its hosts read platform signals (scroll state, animation frames, idle callbacks, update links) whose behavior at the edges decides whether a held timer runs too early or never. These probes measure that behavior in real browsers, an iOS simulator and a compiled Exact app, so the RFC cites measurements rather than readings of documentation. They test the platforms, not this repository's code, so they are experiments and not part of any test lane (docs/testing.md, "Delete vacuous tests"); the RFC's §5 quotes their results.

Directory What it measures How to run it
web/ Chromium, Firefox and WebKit through Playwright: scroll and frame order, scrollend for a removed scroller and a held finger, animation states and their end signals, idle callbacks during animation, an offscreen cross-origin iframe, a blocked main thread, how long a scroll holds still before it ends bun experiments/timer-wait-points/web/probe.mjs [chromium|firefox|webkit …] [--only probe,…]
ios/ a plain UIKit app on an iOS simulator: a passive UIUpdateLink, run-loop modes during tracking and deceleration, scroll state across a held drag and backgrounding, the display link's rate its README.md
compiled/ Exact's Messages app on an iOS simulator under LLP 1144's fling report: whether a precise timer's batches land during a fling today its README.md

Each writes its results under its own results/. A browser probe returns plain data per engine; results/<engine>.json records the engine's version and the date with them. The probes use the browsers scripts/agent-launch.mjs's suiteBrowser pins (Playwright's, as package.json sets). A run with --only merges into the engine's earlier results, and ran gives each probe's browser version and date.

The web probes

support records whether requestIdleCallback, scrollend, getAnimations and ScrollTimeline exist. scrollThenFrame records, during a smooth scroll, how long after each scroll event the next animation-frame callback runs: HTML runs a rendering update's scroll steps just before its frame callbacks. removedScroller removes a scroller at its first scroll and records whether scrollend comes. animations reads playState for a CSS animation at playback rate 0 and for a scroll-driven one, and records how a CSS animation and an Element.animate() one announce their end: document-level events, Animation events, and their finished promises, including one cancelled. idleDuringAnimation counts requestIdleCallback calls and their budgets while an animation-frame loop moves a box. offscreenIframe loads a cross-origin iframe (two loopback origins), then counts its animation frames and 100 ms timeouts for two seconds on screen, off screen and back, with what an IntersectionObserver on its root, on a 1 px fixed corner element and on a fixed element covering the viewport say, and visibilityState; it also measures the frame with its top 100 px scrolled out of view, and with the child's own document scrolled 2,000 px while the frame is on screen. scrolledDocument lays a top-level page out as Exact's scroll document does (html at 100% height) and reads the same three observers before and after scrolling it 2,000 px. heldDrag (Chromium, through CDP touch input) drags a scroller, holds the finger still for 600 ms and lifts it, and records when scrollend comes. blockedMainThread blocks the main thread for 1.2 s at a scroll's first event and records how late an animation frame asked for before the block runs, and where the scroll is when scrollend comes. stillBeforeEnd records the scroller's position in every animation frame of ten smooth scrolls, three wheel scrolls and, in Chromium, three touch flings: the longest time it held one position before moving again, and from its last movement to its scrollend. It also replaces a smooth scroll with an instant one to the position it has reached and records whether it moves on and whether scrollend comes.

The wheel half of blockedMainThread is inconclusive: Playwright's wheel input waits on the renderer, so the scroll does not get far, and Firefox timed out. Its smooth half is what the RFC cites. The wheel runs of stillBeforeEnd are inconclusive for the same reason.