diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index fd7eb87a..b225eca1 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1244,6 +1244,12 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { scheduledFn.runAtMillis + scheduledFn.millis); } + function forEachFunction(funcsToRun, callback) { + for (var i = 0; i < funcsToRun.length; ++i) { + callback(funcsToRun[i]); + } + } + function runScheduledFunctions(endTime) { if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { return; @@ -1255,15 +1261,15 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { var funcsToRun = scheduledFunctions[currentTime]; delete scheduledFunctions[currentTime]; - for (var i = 0; i < funcsToRun.length; ++i) { - var funcToRun = funcsToRun[i]; - + forEachFunction(funcsToRun, function(funcToRun) { if (funcToRun.recurring) { reschedule(funcToRun); } + }); + forEachFunction(funcsToRun, function(funcToRun) { funcToRun.funcToCall.apply(null, funcToRun.params || []); - } + }); } while (scheduledLookup.length > 0 && // checking first if we're out of time prevents setTimeout(0) // scheduled in a funcToRun from forcing an extra iteration diff --git a/spec/core/DelayedFunctionSchedulerSpec.js b/spec/core/DelayedFunctionSchedulerSpec.js index 37dfa766..6b5e2905 100644 --- a/spec/core/DelayedFunctionSchedulerSpec.js +++ b/spec/core/DelayedFunctionSchedulerSpec.js @@ -255,5 +255,42 @@ describe("DelayedFunctionScheduler", function() { scheduler.tick(10); }); + it("removes functions during a tick that runs the function", function() { + var scheduler = new j$.DelayedFunctionScheduler(), + fn = jasmine.createSpy('fn'), + fnDelay = 10, + timeoutKey; + + timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true); + scheduler.scheduleFunction(function () { + scheduler.removeFunctionWithId(timeoutKey); + }, 2 * fnDelay); + + expect(fn).not.toHaveBeenCalled(); + + scheduler.tick(3 * fnDelay); + + expect(fn).toHaveBeenCalled(); + expect(fn.calls.count()).toBe(2); + }); + + it("removes functions during the first tick that runs the function", function() { + var scheduler = new j$.DelayedFunctionScheduler(), + fn = jasmine.createSpy('fn'), + fnDelay = 10, + timeoutKey; + + timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true); + scheduler.scheduleFunction(function () { + scheduler.removeFunctionWithId(timeoutKey); + }, fnDelay); + + expect(fn).not.toHaveBeenCalled(); + + scheduler.tick(3 * fnDelay); + + expect(fn).toHaveBeenCalled(); + expect(fn.calls.count()).toBe(1); + }); }); diff --git a/src/core/DelayedFunctionScheduler.js b/src/core/DelayedFunctionScheduler.js index adb93d1e..99fab4e6 100644 --- a/src/core/DelayedFunctionScheduler.js +++ b/src/core/DelayedFunctionScheduler.js @@ -114,6 +114,12 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { scheduledFn.runAtMillis + scheduledFn.millis); } + function forEachFunction(funcsToRun, callback) { + for (var i = 0; i < funcsToRun.length; ++i) { + callback(funcsToRun[i]); + } + } + function runScheduledFunctions(endTime) { if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { return; @@ -125,15 +131,15 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() { var funcsToRun = scheduledFunctions[currentTime]; delete scheduledFunctions[currentTime]; - for (var i = 0; i < funcsToRun.length; ++i) { - var funcToRun = funcsToRun[i]; - + forEachFunction(funcsToRun, function(funcToRun) { if (funcToRun.recurring) { reschedule(funcToRun); } + }); + forEachFunction(funcsToRun, function(funcToRun) { funcToRun.funcToCall.apply(null, funcToRun.params || []); - } + }); } while (scheduledLookup.length > 0 && // checking first if we're out of time prevents setTimeout(0) // scheduled in a funcToRun from forcing an extra iteration