* Fixes handling of reentrant calls to `jasmine.clock().tick()`
* Merges #1948 from @thw0rted
* Fixes #1929
This commit is contained in:
Steve Gravrock
2021-12-31 09:50:09 -08:00
3 changed files with 74 additions and 12 deletions

View File

@@ -3565,7 +3565,6 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
var endTime = currentTime + millis;
runScheduledFunctions(endTime, tickDate);
currentTime = endTime;
};
self.scheduleFunction = function(
@@ -3683,16 +3682,20 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
function runScheduledFunctions(endTime, tickDate) {
tickDate = tickDate || function() {};
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
tickDate(endTime - currentTime);
if (endTime >= currentTime) {
tickDate(endTime - currentTime);
currentTime = endTime;
}
return;
}
do {
deletedKeys = [];
var newCurrentTime = scheduledLookup.shift();
tickDate(newCurrentTime - currentTime);
currentTime = newCurrentTime;
if (newCurrentTime >= currentTime) {
tickDate(newCurrentTime - currentTime);
currentTime = newCurrentTime;
}
var funcsToRun = scheduledFunctions[currentTime];
@@ -3721,8 +3724,9 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
);
// ran out of functions to call, but still time left on the clock
if (currentTime !== endTime) {
if (endTime >= currentTime) {
tickDate(endTime - currentTime);
currentTime = endTime;
}
}
}

View File

@@ -278,4 +278,58 @@ describe('DelayedFunctionScheduler', function() {
expect(tickDate).toHaveBeenCalledWith(0);
expect(tickDate).toHaveBeenCalledWith(1);
});
describe('ticking inside a scheduled function', function() {
let clock;
// Runner function calls the callback until it returns false
function runWork(workCallback) {
while (workCallback()) {}
}
// Make a worker that takes a little time and tracks when it finished
function mockWork(times) {
return () => {
clock.tick(1);
const now = new Date().getTime();
expect(lastWork)
.withContext('Previous function calls should always be in the past')
.toBeLessThan(now);
lastWork = now;
times--;
return times > 0;
};
}
let lastWork = 0;
beforeEach(() => {
clock = jasmine.clock();
clock.install();
clock.mockDate(new Date(1));
});
afterEach(function() {
jasmine.clock().uninstall();
});
it('preserves monotonically-increasing current time', () => {
const work1 = mockWork(3);
setTimeout(() => {
runWork(work1);
}, 1);
clock.tick(1);
expect(lastWork)
.withContext('tick should advance past last-scheduled function')
.toBeLessThanOrEqual(new Date().getTime());
const work2 = mockWork(3);
setTimeout(() => {
runWork(work2);
}, 1);
clock.tick(1);
expect(lastWork)
.withContext('tick should advance past last-scheduled function')
.toBeLessThanOrEqual(new Date().getTime());
});
});
});

View File

@@ -12,7 +12,6 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
var endTime = currentTime + millis;
runScheduledFunctions(endTime, tickDate);
currentTime = endTime;
};
self.scheduleFunction = function(
@@ -130,16 +129,20 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
function runScheduledFunctions(endTime, tickDate) {
tickDate = tickDate || function() {};
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
tickDate(endTime - currentTime);
if (endTime >= currentTime) {
tickDate(endTime - currentTime);
currentTime = endTime;
}
return;
}
do {
deletedKeys = [];
var newCurrentTime = scheduledLookup.shift();
tickDate(newCurrentTime - currentTime);
currentTime = newCurrentTime;
if (newCurrentTime >= currentTime) {
tickDate(newCurrentTime - currentTime);
currentTime = newCurrentTime;
}
var funcsToRun = scheduledFunctions[currentTime];
@@ -168,8 +171,9 @@ getJasmineRequireObj().DelayedFunctionScheduler = function(j$) {
);
// ran out of functions to call, but still time left on the clock
if (currentTime !== endTime) {
if (endTime >= currentTime) {
tickDate(endTime - currentTime);
currentTime = endTime;
}
}
}