Problem: A document could drop a load if it ran a stream of synchronous
same-document history navigations (say, a pushState flood) while it was
concurrently loaded again. The load never finished — so on sanitizer/
slow builds, this had been intermittently taking down unrelated tests in
CI — since test-web reuses one WebContent process, and the next test’s
load can arrive while the previous document’s history work is still
draining. A synchronous commit also claimed a session history step it
never retired — so claimed steps piled up without bound.
Cause: A sync same-document navigation committed immediately and could
jump the session-history-traversal queue while a queued apply-history-
step — such as a cross-document load — was still waiting behind it. The
queued run read the active session-history entry after the sync
navigation had installed it, but before its step number was assigned —
then judged itself stale against that still-pending step, and was
discarded. The shared step numbering was fragile under the same nesting:
A number computed from the current step alone could collide with an in-
flight one — and a stale run that completed later could write its own
step back over a newer one. 394312ab5a stopped the crash this used to
cause, but the races remained.
Fix: Treat a queued push whose displayed entry’s step is still pending
as live rather than stale — so the concurrent load isn’t dropped. Number
apply-history-step runs, and let a run commit its target step only if no
newer run has committed one — so a stale run can’t move the current step
backwards. Claim each new step past every claimed-but-uncommitted step —
rather than from the current step alone, and keep clearing the forward
session history from removing those entries. And retire the step a sync
commit claims, since it applies in the same task, and nothing else will.
See https://github.com/LadybirdBrowser/ladybird/issues/10028