fix(web): make classic timer idempotent to stop 2x double-counting

The /play-classic timer ran at double speed. startTimer() always created a new
setInterval and overwrote timerInterval without clearing the old one, so any
extra call leaked a second interval that also incremented elapsedSecs. The
visibilitychange handler calls startTimer() on "visible", and a load-time
visibilitychange (while startGame's timer is already running) stacks a second
interval — after which stopTimer() only clears one, so the leak persists and
the clock counts ~2x forever.

Guard startTimer() to no-op when an interval is already running. This fixes the
two e2e timer tests that surfaced it once the suite actually ran (they were
asserting 0:03 / 0:04 but seeing 0:06 / 0:13), and the user-visible 2x timer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-23 17:18:10 -07:00
parent 0b7a24a75b
commit d4ad184324
+5
View File
@@ -270,6 +270,11 @@ function startGame(seed) {
// ── Timer ──────────────────────────────────────────────────────────────────── // ── Timer ────────────────────────────────────────────────────────────────────
function startTimer() { function startTimer() {
// Idempotent: never stack a second interval. The visibilitychange handler
// and startGame can both call this, and a stray call (e.g. a load-time
// visibilitychange while a timer is already running) would otherwise leak
// the old interval and make elapsedSecs increment twice per second.
if (timerInterval) return;
timerInterval = setInterval(() => { timerInterval = setInterval(() => {
elapsedSecs++; elapsedSecs++;
updateTimerDisplay(); updateTimerDisplay();