The previous round regressed the demo against main: dropped frames while a finger drags, and swipes ignored when they start imperfectly. Frame drops: hosts used touch-action: manipulation plus a blocking touchmove listener, so Chrome waited for JavaScript on every touch move (~30% of frames over 20ms in a drag, p95 28ms). Hosts again use per-axis touch-action like main (pan-y for horizontal gestures, and so on), and attach no touch listener. Flaky recognition: an irreversible decision after 6px dropped swipes with a wobbly or backward start. Recognition again measures from the pointer-down point until the pointer lifts, as on main. Scrolling beside gestures, natively: - .from.scrollEdge() uses direction-specific touch-action while its scroller is at the edge (pan-x pan-down for drag-down at the top), the pull-to-refresh pattern from the Pointer Events spec. A passive scroll listener keeps it current; no touch handling blocks the browser. - Where directional values are unsupported (Safari), scroll-edge gestures alone fall back to claiming touches at the browser's first cancelable touchmove. - Hosts publish touch-action as --nvo-touch-action and the stylesheet applies it to descendants, so nested scroll containers keep it and horizontal swipes over lists are not cancelled. Ignored subtrees get touch-action: auto back. - Bindings gain listeners and ref (spread on the host); the components use them. Feel tests (npm run test:feel): Chromium with emulated touch checks recognition on ten human-like traces, frame pacing budgets while dragging (p95 <= 20ms, <= 5% over 20ms) for a swipe and a scroll-edge dismiss, and the behaviour checks. Against the previous code they fail on exactly the reported regressions; now 23/23 pass. On the demo, all traces match main and drag frame pacing matches or beats it. Commit thresholds are unchanged (0.25 distance, 0.2 flick). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Faarh2Ts6StJPcz2mRiHiR
1.6 KiB
Benchmarks
Compares core-v2's performance against an earlier implementation (by default
main).
From the repository root:
packages/core-v2/verify/setup-baseline.sh main # extract into verify/.baseline/
ONLY=baseline npx vitest bench --run --config packages/core-v2/verify/vitest.config.ts
ONLY=rewrite npx vitest bench --run --config packages/core-v2/verify/vitest.config.ts
scene.bench.ts measures compositing, push/back cycles, and rendered frames.
Run each implementation in its own process with ONLY=; running both in one
process biases whichever runs second.
Behavioural verification lives with the unit tests: tests/property.test.ts
drives random operation sequences and pointer streams and checks the scene's
structural invariants after every step. Set PROPERTY_SEEDS to run more.
Real-browser feel tests
browser/ drives a development build in Chromium with emulated touch input,
which happy-dom cannot model: implicit touch pointer capture, native
scrolling, pointercancel, frame timing, and rendered styles. It checks:
- recognition on human-like traces: wobbly and diagonal starts, a small wind-up the wrong way, a twitch at lift-off, slow and short drags, flicks, and vertical scrolls that must not trigger gestures;
- frame pacing while a finger drags (p95 ≤ 20ms, ≤ 5% of frames over 20ms) for a horizontal swipe and a scroll-edge dismiss;
- behaviour: swipes over nested scrollers, native scrolling beside
gestures, scroll-edge dismissal,
onCommitinsidepointerup, and the development continuity warning.
npm run test:feel
Set CHROMIUM_PATH to use a Chromium other than Playwright's own.