timer-shim
Version:
Test-friendly timer function replacements.
306 lines (267 loc) • 7.97 kB
JavaScript
// Generated by CoffeeScript 1.6.3
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
module.exports = (function() {
var ALIASES, CLEAN_THRESHOLD, INITIAL_THRESHOLD, IntervalTask, LinkedList, Task, TimeoutTask, Timer, alias, aliases, bindAll, key, taskFactoryFor, timer, validate, _ref, _ref1;
INITIAL_THRESHOLD = 10;
CLEAN_THRESHOLD = 1.10;
LinkedList = require('linkedlist');
LinkedList.prototype.remove = function(ll, item) {
ll.resetCursor();
while (ll.next() && item !== ll.current) {}
if (ll.current !== item) {
return false;
}
ll.removeCurrent();
return true;
};
alias = function(Klass, action, names) {
var name, _i, _len, _results;
_results = [];
for (_i = 0, _len = names.length; _i < _len; _i++) {
name = names[_i];
_results.push(Klass.prototype[name] = function() {
return Klass.prototype[action].apply(this, arguments);
});
}
return _results;
};
bindAll = function(obj, klass) {
var key, _results;
_results = [];
for (key in klass.prototype) {
if (typeof klass.prototype[key] === 'function' && !obj.hasOwnProperty(key)) {
_results.push((function(key) {
return obj[key] = function() {
return klass.prototype[key].apply(obj, arguments);
};
})(key));
} else {
_results.push(void 0);
}
}
return _results;
};
validate = function(timeout, action) {
var _ref;
if (typeof action === 'number') {
_ref = [timeout, action], action = _ref[0], timeout = _ref[1];
}
if (!isFinite(timeout)) {
throw new Error('timeout is not a valid number');
}
if (typeof action !== 'function') {
throw new Error('action is not a function');
}
return [timeout, action];
};
Task = (function() {
function Task(time, action) {
this.id = null;
this.time = time;
this.action = action;
this.paused = true;
this.canceled = false;
this.windedTime = 0;
}
Task.prototype.cancel = function() {
this.canceled = true;
return this._pause();
};
Task.prototype.pause = function() {
if (this.canceled || this.paused) {
return;
}
this._pause();
this.id = null;
this.paused = true;
return this.windedTime = 0;
};
Task.prototype.resume = function() {
if (this.canceled || !this.paused) {
return;
}
this.id = this._resume(this.windedTime);
this.paused = false;
return this.windedTime = 0;
};
Task.prototype.wind = function(time) {
if (this.canceled || !this.paused) {
return;
}
this.windedTime += time;
return this.windedTime = this._wind(this.windedTime);
};
Task.prototype.unref = function() {
if (!(this.id && typeof this.id.unref === 'function')) {
return;
}
return this.id.unref();
};
Task.prototype.ref = function() {
if (!(this.id && typeof this.id.ref === 'function')) {
return;
}
return this.id.ref();
};
Task.prototype._pause = function() {
throw new Error('must be overridden');
};
Task.prototype._resume = function() {
throw new Error('must be overridden');
};
return Task;
})();
IntervalTask = (function(_super) {
__extends(IntervalTask, _super);
function IntervalTask() {
_ref = IntervalTask.__super__.constructor.apply(this, arguments);
return _ref;
}
IntervalTask.prototype._pause = function() {
return clearInterval(this.id);
};
IntervalTask.prototype._resume = function(time) {
var _this = this;
if (!time) {
return setInterval(this.action, this.time);
} else {
return setTimeout(function() {
_this.action();
return _this.id = setInterval(_this.action, _this.time);
}, this.time - time);
}
};
IntervalTask.prototype._wind = function(time) {
while (time >= this.time) {
time -= this.time;
this.action();
}
return time;
};
return IntervalTask;
})(Task);
TimeoutTask = (function(_super) {
__extends(TimeoutTask, _super);
function TimeoutTask() {
_ref1 = TimeoutTask.__super__.constructor.apply(this, arguments);
return _ref1;
}
TimeoutTask.prototype._pause = function() {
return clearTimeout(this.id);
};
TimeoutTask.prototype._resume = function(time) {
return setTimeout(this.action, this.time - time);
};
TimeoutTask.prototype._wind = function(time) {
if (time < this.time) {
return time;
}
this.action();
this.canceled = true;
return 0;
};
return TimeoutTask;
})(Task);
taskFactoryFor = function(Klass) {
return function(timeout, action) {
var task, _ref2;
_ref2 = validate(timeout, action), timeout = _ref2[0], action = _ref2[1];
task = new Klass(timeout, action);
this.tasks.push(task);
if (!this.paused) {
task.resume();
}
this._checkAndClean();
return task;
};
};
Timer = (function() {
Timer.prototype.paused = false;
Timer.prototype.tasks = null;
Timer.prototype._lastCleanedLength = 0;
function Timer() {
this.tasks = new LinkedList;
this._lastCleanedLength = INITIAL_THRESHOLD;
bindAll(this, Timer);
}
Timer.prototype.timeout = taskFactoryFor(TimeoutTask);
Timer.prototype.interval = taskFactoryFor(IntervalTask);
Timer.prototype.clear = function(task) {
return task.cancel();
};
Timer.prototype.clearAll = function() {
this.tasks.resetCursor();
while (this.tasks.next()) {
this.clear(this.tasks.current);
}
return this.tasks = new LinkedList;
};
Timer.prototype.pause = function() {
this.tasks.resetCursor();
while (this.tasks.next()) {
this.tasks.current.pause();
}
return this.paused = true;
};
Timer.prototype.resume = function() {
this.tasks.resetCursor();
while (this.tasks.next()) {
this.tasks.current.resume();
}
return this.paused = false;
};
Timer.prototype.wind = function(time) {
var _results;
this.tasks.resetCursor();
_results = [];
while (this.tasks.next()) {
_results.push(this.tasks.current.wind(time));
}
return _results;
};
Timer.prototype.unref = function() {
var _results;
this.tasks.resetCursor();
_results = [];
while (this.tasks.next()) {
_results.push(this.tasks.current.unref());
}
return _results;
};
Timer.prototype.ref = function() {
var _results;
this.tasks.resetCursor();
_results = [];
while (this.tasks.next()) {
_results.push(this.tasks.current.ref());
}
return _results;
};
Timer.prototype._checkAndClean = function() {
if (!(this.tasks.length > this._lastCleanedLength * CLEAN_THRESHOLD)) {
return;
}
this.tasks.resetCursor();
while (this.tasks.next()) {
if (this.tasks.current.canceled) {
this.tasks.removeCurrent();
}
}
return this._lastCleanedLength = this.tasks.length;
};
return Timer;
})();
ALIASES = {
'timeout': 't,to,setTimeout',
'clear': 'c,ct,cto,clearTimeout,clearInterval',
'interval': 'i,in,iv,inv,setInterval'
};
for (key in ALIASES) {
aliases = ALIASES[key];
alias(Timer, key, aliases.split(','));
}
timer = new Timer();
Timer.prototype.Timer = Timer;
return timer;
})();