diff --git a/lib/internal/test_runner/mock/mock_timers.js b/lib/internal/test_runner/mock/mock_timers.js index fa4c13a5dec6dc..fdb0935ab64686 100644 --- a/lib/internal/test_runner/mock/mock_timers.js +++ b/lib/internal/test_runner/mock/mock_timers.js @@ -652,7 +652,7 @@ class MockTimers { // Check if the timeout was cleared by calling clearTimeout inside its own callback const afterCallback = this.#executionQueue.peek(); - if (afterCallback.id === timer.id) { + if (afterCallback?.id === timer.id) { this.#executionQueue.shift(); timer.priorityQueuePosition = undefined; } diff --git a/test/parallel/test-runner-mock-timers.js b/test/parallel/test-runner-mock-timers.js index 9af58d5cab0008..6ce6c28c95e326 100644 --- a/test/parallel/test-runner-mock-timers.js +++ b/test/parallel/test-runner-mock-timers.js @@ -548,6 +548,19 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.runAll(); assert.strictEqual(f.mock.callCount(), 3); }); + + it('should allow clearing timeout inside own callback', (t) => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + const f = t.mock.fn(); + + const timer = nodeTimers.setTimeout(() => { + f(); + nodeTimers.clearTimeout(timer); + }, 50); + + t.mock.timers.runAll(); + assert.strictEqual(f.mock.callCount(), 1); + }); }); describe('setInterval Suite', () => {