diff --git a/cli/tests/unit/timers_test.ts b/cli/tests/unit/timers_test.ts index c50cb779c6..5c076ad090 100644 --- a/cli/tests/unit/timers_test.ts +++ b/cli/tests/unit/timers_test.ts @@ -727,3 +727,32 @@ Deno.test({ assertEquals(output, ""); }, }); + +// Regression test for https://github.com/denoland/deno/issues/19866 +Deno.test({ + name: "regression for #19866", + fn: async () => { + const timeoutsFired = []; + + // deno-lint-ignore require-await + async function start(n: number) { + let i = 0; + const intervalId = setInterval(() => { + i++; + if (i > 2) { + clearInterval(intervalId!); + } + timeoutsFired.push(n); + }, 20); + } + + for (let n = 0; n < 100; n++) { + start(n); + } + + // 3s should be plenty of time for all the intervals to fire + // but it might still be flaky on CI. + await new Promise((resolve) => setTimeout(resolve, 3000)); + assertEquals(timeoutsFired.length, 300); + }, +}); diff --git a/ext/web/02_timers.js b/ext/web/02_timers.js index cfabdeb98b..ade1c7123c 100644 --- a/ext/web/02_timers.js +++ b/ext/web/02_timers.js @@ -243,6 +243,7 @@ function runAfterTimeout(task, millis, timerInfo) { resolved: false, prev: scheduledTimers.tail, next: null, + task, }; // Add timerObject to the end of the list. @@ -286,7 +287,7 @@ function runAfterTimeout(task, millis, timerInfo) { while (currentEntry !== null) { if (currentEntry.millis <= timerObject.millis) { currentEntry.resolved = true; - ArrayPrototypePush(timerTasks, task); + ArrayPrototypePush(timerTasks, currentEntry.task); removeFromScheduledTimers(currentEntry); if (currentEntry === timerObject) {