Skip to content

Commit

Permalink
Merge pull request #225 from shdq/requestIdleCallback-support
Browse files Browse the repository at this point in the history
[WIP] Issue #218 – `requestIdleCallback` implementation
  • Loading branch information
benjamingr authored Jan 20, 2019
2 parents 94b280c + 89504ad commit 29b4ecc
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 1 deletion.
38 changes: 37 additions & 1 deletion src/lolex-src.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ function withGlobal(_global) {
var cancelAnimationFramePresent = (
_global.cancelAnimationFrame && typeof _global.cancelAnimationFrame === "function"
);
var requestIdleCallbackPresent = (
_global.requestIdleCallback && typeof _global.requestIdleCallback === "function"
);
var cancelIdleCallbackPresent = (
_global.cancelIdleCallback && typeof _global.cancelIdleCallback === "function"
);

_global.clearTimeout(timeoutResult);

Expand Down Expand Up @@ -188,7 +194,6 @@ function withGlobal(_global) {
return mirrorDateProperties(ClockDate, NativeDate);
}


function enqueueJob(clock, job) {
// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
if (!clock.jobs) {
Expand Down Expand Up @@ -496,6 +501,14 @@ function withGlobal(_global) {
timers.cancelAnimationFrame = _global.cancelAnimationFrame;
}

if (requestIdleCallbackPresent) {
timers.requestIdleCallback = _global.requestIdleCallback;
}

if (cancelIdleCallbackPresent) {
timers.cancelIdleCallback = _global.cancelIdleCallback;
}

var keys = Object.keys || function (obj) {
var ks = [];
var key;
Expand Down Expand Up @@ -561,6 +574,26 @@ function withGlobal(_global) {
return [secsSinceStart, remainderInNanos];
}

clock.requestIdleCallback = function requestIdleCallback(func, timeout) {
var timeToNextIdlePeriod = 0;

if (clock.countTimers() > 0) {
timeToNextIdlePeriod = 50; // const for now
}

var result = addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: typeof timeout === "undefined" ? timeToNextIdlePeriod : Math.min(timeout, timeToNextIdlePeriod)
});

return result.id || result;
};

clock.cancelIdleCallback = function cancelIdleCallback(timerId) {
return clearTimer(clock, timerId, "Timeout");
};

clock.setTimeout = function setTimeout(func, timeout) {
return addTimer(clock, {
func: func,
Expand All @@ -572,15 +605,18 @@ function withGlobal(_global) {
clock.clearTimeout = function clearTimeout(timerId) {
return clearTimer(clock, timerId, "Timeout");
};

clock.nextTick = function nextTick(func) {
return enqueueJob(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 1)
});
};

clock.queueMicrotask = function queueMicrotask(func) {
return clock.nextTick(func); // explicitly drop additional arguments
};

clock.setInterval = function setInterval(func, timeout) {
timeout = parseInt(timeout, 10);
return addTimer(clock, {
Expand Down
76 changes: 76 additions & 0 deletions test/lolex-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2769,4 +2769,80 @@ describe("lolex", function () {
}, true);
});
});

describe("requestIdleCallback", function () {
beforeEach(function () {
this.clock = lolex.createClock();
});

it("throws if no arguments", function () {
var clock = this.clock;

assert.exception(function () { clock.requestIdleCallback(); });
});

it("returns numeric id", function () {
var result = this.clock.requestIdleCallback(NOOP);

assert.isNumber(result);
});

it("returns unique id", function () {
var id1 = this.clock.requestIdleCallback(NOOP);
var id2 = this.clock.requestIdleCallback(NOOP);
this.clock.runAll();

refute.equals(id2, id1);
});

it("runs after all timers", function () {
var spy = sinon.spy();
this.clock.requestIdleCallback(spy);
this.clock.runAll();

assert(spy.called);
});

it("runs immediately with timeout option if there isn't any timer", function () {
var spy = sinon.spy();
this.clock.requestIdleCallback(spy, 20);
this.clock.tick(1);

assert(spy.called);
});

it("runs no later than timeout option even if there are any timers", function () {
var spy = sinon.spy();
this.clock.setTimeout(NOOP, 10);
this.clock.setTimeout(NOOP, 30);
this.clock.requestIdleCallback(spy, 20);
this.clock.tick(20);

assert(spy.called);
});

it("doesn't runs if there are any timers and no timeout option", function () {
var spy = sinon.spy();
this.clock.setTimeout(NOOP, 30);
this.clock.requestIdleCallback(spy);
this.clock.tick(35);

assert.isFalse(spy.called);
});
});

describe("cancelIdleCallback", function () {
beforeEach(function () {
this.clock = lolex.createClock();
});

it("removes idle callback", function () {
var stub = sinon.stub();
var callbackId = this.clock.requestIdleCallback(stub, 0);
this.clock.cancelIdleCallback(callbackId);
this.clock.runAll();

assert.isFalse(stub.called);
});
});
});

0 comments on commit 29b4ecc

Please sign in to comment.