Add forcing support and improve tests

Also verify that we're using tabs, whee.
This commit is contained in:
Pat Cavit 2016-05-18 23:08:35 -07:00 committed by Pat Cavit
parent 86ce23a2bd
commit 0cf509f674
3 changed files with 104 additions and 29 deletions

View file

@ -5,22 +5,23 @@ module.exports = function($window, render) {
var cAF = $window.cancelAnimationFrame || $window.clearTimeout var cAF = $window.cancelAnimationFrame || $window.clearTimeout
var last = 0 var last = 0
var pending var pending = null
return function() { return function(force) {
var now = new Date() var now = new Date()
// First render, OR if the time since the last render is greater // Immediately render if:
// than the frame budget // Forced
// just immediately render // Haven't rendered yet
if(!last || now - last > FRAME_BUDGET) { // Time since the last render is greater than the frame budget
if(force || !last || now - last > FRAME_BUDGET) {
last = now; last = now;
return render() return render()
} }
// Redraw already pending, abort // Redraw already pending, abort
if(pending) { if(pending !== null) {
return return
} }

View file

@ -1,12 +1,46 @@
var _fns = []
var _last = 0
var _frame = 1000 / 60
module.exports = { module.exports = {
setTimeout : function($window) { setTimeout : function($window) {
$window.setTimeout = window.setTimeout; $window.setTimeout = typeof window === "object" ? window.setTimeout : global.setTimeout;
$window.clearTimeout = window.clearTimeout; $window.clearTimeout = typeof window === "object" ? window.clearTimeout : global.setTimeout;
}, },
requestAnimationFrame : function($window) { requestAnimationFrame : function($window) {
$window.requestAnimationFrame = window.requestAnimationFrame; // Modified version of https://github.com/chrisdickinson/raf
$window.cancelAnimationFrame = window.cancelAnimationFrame; // Copyright chrisdickinson I guess?
$window.requestAnimationFrame = typeof window === "object" ? window.requestAnimationFrame : function(fn) {
if(!_fns.length) {
var now = Date.now()
var next = Math.max(0, _frame - (now - _last))
_last = next + now
setTimeout(function() {
var fns = _fns.slice()
_fns = []
for(var i = 0; i < fns.length; i++) {
if(typeof fns[i] !== "function") {
continue
}
fns[i](_last)
}
}, Math.round(next))
}
_fns.push(fn)
return _fns.length - 1;
}
$window.cancelAnimationFrame = typeof window === "object" ? window.cancelAnimationFrame : function(handle) {
_fns[handle] = null
};
} }
} }

View file

@ -7,23 +7,63 @@ var async = require("./async")
var limiter = require("../limiter") var limiter = require("../limiter")
o.spec("fps limiter", function() { o.spec("fps limiter", function() {
var $window, root var $window, root
[ "setTimeout", "requestAnimationFrame" ].forEach(function(type) { [
o.spec(type, function() { "setTimeout",
o.beforeEach(function() { "requestAnimationFrame",
$window = domMock() ].forEach(function(type) {
o.spec(type, function() {
async[type]($window) o.beforeEach(function() {
}) $window = domMock()
o("is a function", function() { async[type]($window)
o(typeof limiter).equals("function") })
})
o("is a function", function() {
o("it returns a function", function() { o(typeof limiter).equals("function")
o(typeof limiter(false)).equals("function") })
})
}) o("it returns a function", function() {
}) o(typeof limiter($window, false)).equals("function")
})
o("it runs synchronously the first time", function() {
var spy = o.spy()
var run = limiter($window, spy)
run()
o(spy.callCount).equals(1)
})
o("it only runs once per tick", function(done) {
var spy = o.spy()
var run = limiter($window, spy)
run()
run()
run()
o(spy.callCount).equals(1)
setTimeout(function() {
o(spy.callCount).equals(2)
done()
}, 17)
})
o("it supports forcing a synchronous redraw", function() {
var spy = o.spy()
var run = limiter($window, spy)
run()
run()
run(true)
o(spy.callCount).equals(2)
})
})
})
}) })