Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lolex

Package Overview
Dependencies
Maintainers
4
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lolex - npm Package Compare versions

Comparing version 2.3.2 to 2.4.0

7

History.md
v2.4.0 / 2018-05-08
==================
* Add `withGlobal` export
* expose runMicrotasks
* Fix that performance.mark is undefined after timer install
v2.3.2 / 2018-01-29

@@ -3,0 +10,0 @@ ==================

1298

lolex.js

@@ -5,799 +5,829 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lolex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){

var userAgent = global.navigator && global.navigator.userAgent;
var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
function withGlobal(_global) {
var userAgent = _global.navigator && _global.navigator.userAgent;
var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
// Make properties writable in IE, as per
// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
if (isRunningInIE) {
global.setTimeout = global.setTimeout;
global.clearTimeout = global.clearTimeout;
global.setInterval = global.setInterval;
global.clearInterval = global.clearInterval;
global.Date = global.Date;
}
// Make properties writable in IE, as per
// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
if (isRunningInIE) {
_global.setTimeout = _global.setTimeout;
_global.clearTimeout = _global.clearTimeout;
_global.setInterval = _global.setInterval;
_global.clearInterval = _global.clearInterval;
_global.Date = _global.Date;
}
// setImmediate is not a standard function
// avoid adding the prop to the window object if not present
if (global.setImmediate !== undefined) {
global.setImmediate = global.setImmediate;
global.clearImmediate = global.clearImmediate;
}
// setImmediate is not a standard function
// avoid adding the prop to the window object if not present
if (_global.setImmediate !== undefined) {
_global.setImmediate = _global.setImmediate;
_global.clearImmediate = _global.clearImmediate;
}
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
// browsers, a number.
// see https://github.com/cjohansen/Sinon.JS/pull/436
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
// browsers, a number.
// see https://github.com/cjohansen/Sinon.JS/pull/436
var NOOP = function () { return undefined; };
var timeoutResult = setTimeout(NOOP, 0);
var addTimerReturnsObject = typeof timeoutResult === "object";
var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
var performancePresent = (global.performance && typeof global.performance.now === "function");
var requestAnimationFramePresent = (global.requestAnimationFrame && typeof global.requestAnimationFrame === "function");
var cancelAnimationFramePresent = (global.cancelAnimationFrame && typeof global.cancelAnimationFrame === "function");
var NOOP = function () { return undefined; };
var timeoutResult = _global.setTimeout(NOOP, 0);
var addTimerReturnsObject = typeof timeoutResult === "object";
var hrtimePresent = (_global.process && typeof _global.process.hrtime === "function");
var nextTickPresent = (_global.process && typeof _global.process.nextTick === "function");
var performancePresent = (_global.performance && typeof _global.performance.now === "function");
var requestAnimationFramePresent = (
_global.requestAnimationFrame && typeof _global.requestAnimationFrame === "function"
);
var cancelAnimationFramePresent = (
_global.cancelAnimationFrame && typeof _global.cancelAnimationFrame === "function"
);
clearTimeout(timeoutResult);
_global.clearTimeout(timeoutResult);
var NativeDate = Date;
var uniqueTimerId = 1;
var NativeDate = Date;
var uniqueTimerId = 1;
/**
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
* number of milliseconds. This is used to support human-readable strings passed
* to clock.tick()
*/
function parseTime(str) {
if (!str) {
return 0;
}
/**
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
* number of milliseconds. This is used to support human-readable strings passed
* to clock.tick()
*/
function parseTime(str) {
if (!str) {
return 0;
}
var strings = str.split(":");
var l = strings.length;
var i = l;
var ms = 0;
var parsed;
var strings = str.split(":");
var l = strings.length;
var i = l;
var ms = 0;
var parsed;
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
}
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
}
while (i--) {
parsed = parseInt(strings[i], 10);
while (i--) {
parsed = parseInt(strings[i], 10);
if (parsed >= 60) {
throw new Error("Invalid time " + str);
if (parsed >= 60) {
throw new Error("Invalid time " + str);
}
ms += parsed * Math.pow(60, (l - i - 1));
}
ms += parsed * Math.pow(60, (l - i - 1));
return ms * 1000;
}
return ms * 1000;
}
/**
* Floor function that also works for negative numbers
*/
function fixedFloor(n) {
return (n >= 0 ? Math.floor(n) : Math.ceil(n));
}
/**
* Floor function that also works for negative numbers
*/
function fixedFloor(n) {
return (n >= 0 ? Math.floor(n) : Math.ceil(n));
}
/**
* % operator that also works for negative numbers
*/
function fixedModulo(n, m) {
return ((n % m) + m) % m;
}
/**
* % operator that also works for negative numbers
*/
function fixedModulo(n, m) {
return ((n % m) + m) % m;
}
/**
* Used to grok the `now` parameter to createClock.
* @param epoch {Date|number} the system time
*/
function getEpoch(epoch) {
if (!epoch) { return 0; }
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
if (typeof epoch === "number") { return epoch; }
throw new TypeError("now should be milliseconds since UNIX epoch");
}
/**
* Used to grok the `now` parameter to createClock.
* @param epoch {Date|number} the system time
*/
function getEpoch(epoch) {
if (!epoch) { return 0; }
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
if (typeof epoch === "number") { return epoch; }
throw new TypeError("now should be milliseconds since UNIX epoch");
}
function inRange(from, to, timer) {
return timer && timer.callAt >= from && timer.callAt <= to;
}
function inRange(from, to, timer) {
return timer && timer.callAt >= from && timer.callAt <= to;
}
function mirrorDateProperties(target, source) {
var prop;
for (prop in source) {
if (source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
function mirrorDateProperties(target, source) {
var prop;
for (prop in source) {
if (source.hasOwnProperty(prop)) {
target[prop] = source[prop];
// set special now implementation
if (source.now) {
target.now = function now() {
return target.clock.now;
};
} else {
delete target.now;
}
}
// set special now implementation
if (source.now) {
target.now = function now() {
return target.clock.now;
// set special toSource implementation
if (source.toSource) {
target.toSource = function toSource() {
return source.toSource();
};
} else {
delete target.toSource;
}
// set special toString implementation
target.toString = function toString() {
return source.toString();
};
} else {
delete target.now;
}
// set special toSource implementation
if (source.toSource) {
target.toSource = function toSource() {
return source.toSource();
};
} else {
delete target.toSource;
target.prototype = source.prototype;
target.parse = source.parse;
target.UTC = source.UTC;
target.prototype.toUTCString = source.prototype.toUTCString;
return target;
}
// set special toString implementation
target.toString = function toString() {
return source.toString();
};
function createDate() {
function ClockDate(year, month, date, hour, minute, second, ms) {
// Defensive and verbose to avoid potential harm in passing
// explicit undefined when user does not pass argument
switch (arguments.length) {
case 0:
return new NativeDate(ClockDate.clock.now);
case 1:
return new NativeDate(year);
case 2:
return new NativeDate(year, month);
case 3:
return new NativeDate(year, month, date);
case 4:
return new NativeDate(year, month, date, hour);
case 5:
return new NativeDate(year, month, date, hour, minute);
case 6:
return new NativeDate(year, month, date, hour, minute, second);
default:
return new NativeDate(year, month, date, hour, minute, second, ms);
}
}
target.prototype = source.prototype;
target.parse = source.parse;
target.UTC = source.UTC;
target.prototype.toUTCString = source.prototype.toUTCString;
return mirrorDateProperties(ClockDate, NativeDate);
}
return target;
}
function createDate() {
function ClockDate(year, month, date, hour, minute, second, ms) {
// Defensive and verbose to avoid potential harm in passing
// explicit undefined when user does not pass argument
switch (arguments.length) {
case 0:
return new NativeDate(ClockDate.clock.now);
case 1:
return new NativeDate(year);
case 2:
return new NativeDate(year, month);
case 3:
return new NativeDate(year, month, date);
case 4:
return new NativeDate(year, month, date, hour);
case 5:
return new NativeDate(year, month, date, hour, minute);
case 6:
return new NativeDate(year, month, date, hour, minute, second);
default:
return new NativeDate(year, month, date, hour, minute, second, ms);
function enqueueJob(clock, job) {
// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
if (!clock.jobs) {
clock.jobs = [];
}
clock.jobs.push(job);
}
return mirrorDateProperties(ClockDate, NativeDate);
}
function enqueueJob(clock, job) {
// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
if (!clock.jobs) {
function runJobs(clock) {
// runs all microtick-deferred tasks - ecma262/#sec-runjobs
if (!clock.jobs) {
return;
}
for (var i = 0; i < clock.jobs.length; i++) {
var job = clock.jobs[i];
job.func.apply(null, job.args);
}
clock.jobs = [];
}
clock.jobs.push(job);
}
function runJobs(clock) {
// runs all microtick-deferred tasks - ecma262/#sec-runjobs
if (!clock.jobs) {
return;
}
for (var i = 0; i < clock.jobs.length; i++) {
var job = clock.jobs[i];
job.func.apply(null, job.args);
}
clock.jobs = [];
}
function addTimer(clock, timer) {
if (timer.func === undefined) {
throw new Error("Callback must be provided to timer calls");
}
function addTimer(clock, timer) {
if (timer.func === undefined) {
throw new Error("Callback must be provided to timer calls");
}
timer.type = timer.immediate ? "Immediate" : "Timeout";
timer.type = timer.immediate ? "Immediate" : "Timeout";
if (timer.hasOwnProperty("delay")) {
timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
timer.delay = Math.max(0, timer.delay);
}
if (timer.hasOwnProperty("delay")) {
timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
timer.delay = Math.max(0, timer.delay);
}
if (timer.hasOwnProperty("interval")) {
timer.type = "Interval";
timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
}
if (timer.hasOwnProperty("interval")) {
timer.type = "Interval";
timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
}
if (timer.hasOwnProperty("animation")) {
timer.type = "AnimationFrame";
timer.animation = true;
}
if (timer.hasOwnProperty("animation")) {
timer.type = "AnimationFrame";
timer.animation = true;
}
if (!clock.timers) {
clock.timers = {};
}
if (!clock.timers) {
clock.timers = {};
}
timer.id = uniqueTimerId++;
timer.createdAt = clock.now;
timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
timer.id = uniqueTimerId++;
timer.createdAt = clock.now;
timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
clock.timers[timer.id] = timer;
clock.timers[timer.id] = timer;
if (addTimerReturnsObject) {
return {
id: timer.id,
ref: NOOP,
unref: NOOP
};
}
if (addTimerReturnsObject) {
return {
id: timer.id,
ref: NOOP,
unref: NOOP
};
return timer.id;
}
return timer.id;
}
/* eslint consistent-return: "off" */
function compareTimers(a, b) {
// Sort first by absolute timing
if (a.callAt < b.callAt) {
return -1;
}
if (a.callAt > b.callAt) {
return 1;
}
/* eslint consistent-return: "off" */
function compareTimers(a, b) {
// Sort first by absolute timing
if (a.callAt < b.callAt) {
return -1;
}
if (a.callAt > b.callAt) {
return 1;
}
// Sort next by immediate, immediate timers take precedence
if (a.immediate && !b.immediate) {
return -1;
}
if (!a.immediate && b.immediate) {
return 1;
}
// Sort next by immediate, immediate timers take precedence
if (a.immediate && !b.immediate) {
return -1;
}
if (!a.immediate && b.immediate) {
return 1;
}
// Sort next by creation time, earlier-created timers take precedence
if (a.createdAt < b.createdAt) {
return -1;
}
if (a.createdAt > b.createdAt) {
return 1;
}
// Sort next by creation time, earlier-created timers take precedence
if (a.createdAt < b.createdAt) {
return -1;
}
if (a.createdAt > b.createdAt) {
return 1;
}
// Sort next by id, lower-id timers take precedence
if (a.id < b.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
// Sort next by id, lower-id timers take precedence
if (a.id < b.id) {
return -1;
// As timer ids are unique, no fallback `0` is necessary
}
if (a.id > b.id) {
return 1;
}
// As timer ids are unique, no fallback `0` is necessary
}
function firstTimerInRange(clock, from, to) {
var timers = clock.timers;
var timer = null;
var id, isInRange;
function firstTimerInRange(clock, from, to) {
var timers = clock.timers;
var timer = null;
var id, isInRange;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
isInRange = inRange(from, to, timers[id]);
for (id in timers) {
if (timers.hasOwnProperty(id)) {
isInRange = inRange(from, to, timers[id]);
if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
timer = timers[id];
if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function firstTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
function firstTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === 1) {
timer = timers[id];
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === 1) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function lastTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
function lastTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === -1) {
timer = timers[id];
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === -1) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function callTimer(clock, timer) {
if (typeof timer.interval === "number") {
clock.timers[timer.id].callAt += timer.interval;
} else {
delete clock.timers[timer.id];
}
function callTimer(clock, timer) {
if (typeof timer.interval === "number") {
clock.timers[timer.id].callAt += timer.interval;
} else {
delete clock.timers[timer.id];
if (typeof timer.func === "function") {
timer.func.apply(null, timer.args);
} else {
/* eslint no-eval: "off" */
eval(timer.func);
}
}
if (typeof timer.func === "function") {
timer.func.apply(null, timer.args);
} else {
/* eslint no-eval: "off" */
eval(timer.func);
}
}
function clearTimer(clock, timerId, ttype) {
if (!timerId) {
// null appears to be allowed in most browsers, and appears to be
// relied upon by some libraries, like Bootstrap carousel
return;
}
function clearTimer(clock, timerId, ttype) {
if (!timerId) {
// null appears to be allowed in most browsers, and appears to be
// relied upon by some libraries, like Bootstrap carousel
return;
}
if (!clock.timers) {
clock.timers = [];
}
if (!clock.timers) {
clock.timers = [];
}
// in Node, timerId is an object with .ref()/.unref(), and
// its .id field is the actual timer id.
if (typeof timerId === "object") {
timerId = timerId.id;
}
// in Node, timerId is an object with .ref()/.unref(), and
// its .id field is the actual timer id.
if (typeof timerId === "object") {
timerId = timerId.id;
if (clock.timers.hasOwnProperty(timerId)) {
// check that the ID matches a timer of the correct type
var timer = clock.timers[timerId];
if (timer.type === ttype) {
delete clock.timers[timerId];
} else {
var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
throw new Error("Cannot clear timer: timer created with " + schedule
+ "() but cleared with " + clear + "()");
}
}
}
if (clock.timers.hasOwnProperty(timerId)) {
// check that the ID matches a timer of the correct type
var timer = clock.timers[timerId];
if (timer.type === ttype) {
delete clock.timers[timerId];
} else {
var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
throw new Error("Cannot clear timer: timer created with " + schedule
+ "() but cleared with " + clear + "()");
function uninstall(clock, target, config) {
var method,
i,
l;
var installedHrTime = "_hrtime";
var installedNextTick = "_nextTick";
for (i = 0, l = clock.methods.length; i < l; i++) {
method = clock.methods[i];
if (method === "hrtime" && target.process) {
target.process.hrtime = clock[installedHrTime];
} else if (method === "nextTick" && target.process) {
target.process.nextTick = clock[installedNextTick];
} else {
if (target[method] && target[method].hadOwnProperty) {
target[method] = clock["_" + method];
if (method === "clearInterval" && config.shouldAdvanceTime === true) {
target[method](clock.attachedInterval);
}
} else {
try {
delete target[method];
} catch (ignore) { /* eslint empty-block: "off" */ }
}
}
}
// Prevent multiple executions which will completely remove these props
clock.methods = [];
// return pending timers, to enable checking what timers remained on uninstall
if (!clock.timers) {
return [];
}
return Object.keys(clock.timers).map(function mapper(key) {
return clock.timers[key];
});
}
}
function uninstall(clock, target, config) {
var method,
i,
l;
var installedHrTime = "_hrtime";
var installedNextTick = "_nextTick";
function hijackMethod(target, method, clock) {
var prop;
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
clock["_" + method] = target[method];
for (i = 0, l = clock.methods.length; i < l; i++) {
method = clock.methods[i];
if (method === "hrtime" && target.process) {
target.process.hrtime = clock[installedHrTime];
} else if (method === "nextTick" && target.process) {
target.process.nextTick = clock[installedNextTick];
if (method === "Date") {
var date = mirrorDateProperties(clock[method], target[method]);
target[method] = date;
} else {
if (target[method] && target[method].hadOwnProperty) {
target[method] = clock["_" + method];
if (method === "clearInterval" && config.shouldAdvanceTime === true) {
target[method](clock.attachedInterval);
target[method] = function () {
return clock[method].apply(clock, arguments);
};
for (prop in clock[method]) {
if (clock[method].hasOwnProperty(prop)) {
target[method][prop] = clock[method][prop];
}
} else {
try {
delete target[method];
} catch (ignore) { /* eslint empty-block: "off" */ }
}
}
target[method].clock = clock;
}
// Prevent multiple executions which will completely remove these props
clock.methods = [];
// return pending timers, to enable checking what timers remained on uninstall
if (!clock.timers) {
return [];
function doIntervalTick(clock, advanceTimeDelta) {
clock.tick(advanceTimeDelta);
}
return Object.keys(clock.timers).map(function mapper(key) {
return clock.timers[key];
});
}
function hijackMethod(target, method, clock) {
var prop;
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
clock["_" + method] = target[method];
var timers = {
setTimeout: _global.setTimeout,
clearTimeout: _global.clearTimeout,
setImmediate: _global.setImmediate,
clearImmediate: _global.clearImmediate,
setInterval: _global.setInterval,
clearInterval: _global.clearInterval,
Date: _global.Date
};
if (method === "Date") {
var date = mirrorDateProperties(clock[method], target[method]);
target[method] = date;
} else {
target[method] = function () {
return clock[method].apply(clock, arguments);
};
if (hrtimePresent) {
timers.hrtime = _global.process.hrtime;
}
for (prop in clock[method]) {
if (clock[method].hasOwnProperty(prop)) {
target[method][prop] = clock[method][prop];
}
}
if (nextTickPresent) {
timers.nextTick = _global.process.nextTick;
}
target[method].clock = clock;
}
if (performancePresent) {
timers.performance = _global.performance;
}
function doIntervalTick(clock, advanceTimeDelta) {
clock.tick(advanceTimeDelta);
}
if (requestAnimationFramePresent) {
timers.requestAnimationFrame = _global.requestAnimationFrame;
}
var timers = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setImmediate: global.setImmediate,
clearImmediate: global.clearImmediate,
setInterval: setInterval,
clearInterval: clearInterval,
Date: Date
};
if (cancelAnimationFramePresent) {
timers.cancelAnimationFrame = _global.cancelAnimationFrame;
}
if (hrtimePresent) {
timers.hrtime = global.process.hrtime;
}
var keys = Object.keys || function (obj) {
var ks = [];
var key;
if (nextTickPresent) {
timers.nextTick = global.process.nextTick;
}
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ks.push(key);
}
}
if (performancePresent) {
timers.performance = global.performance;
}
return ks;
};
if (requestAnimationFramePresent) {
timers.requestAnimationFrame = global.requestAnimationFrame;
}
/**
* @param start {Date|number} the system time
* @param loopLimit {number} maximum number of timers that will be run when calling runAll()
*/
function createClock(start, loopLimit) {
start = start || 0;
loopLimit = loopLimit || 1000;
if (cancelAnimationFramePresent) {
timers.cancelAnimationFrame = global.cancelAnimationFrame;
}
var clock = {
now: getEpoch(start),
hrNow: 0,
timeouts: {},
Date: createDate(),
loopLimit: loopLimit
};
var keys = Object.keys || function (obj) {
var ks = [];
var key;
clock.Date.clock = clock;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ks.push(key);
function getTimeToNextFrame() {
return 16 - ((clock.now - start) % 16);
}
}
return ks;
};
clock.setTimeout = function setTimeout(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout
});
};
exports.timers = timers;
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.setInterval = function setInterval(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout,
interval: timeout
});
};
/**
* @param start {Date|number} the system time
* @param loopLimit {number} maximum number of timers that will be run when calling runAll()
*/
function createClock(start, loopLimit) {
start = start || 0;
loopLimit = loopLimit || 1000;
clock.clearInterval = function clearInterval(timerId) {
return clearTimer(clock, timerId, "Interval");
};
var clock = {
now: getEpoch(start),
hrNow: 0,
timeouts: {},
Date: createDate(),
loopLimit: loopLimit
};
clock.setImmediate = function setImmediate(func) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 1),
immediate: true
});
};
clock.Date.clock = clock;
clock.clearImmediate = function clearImmediate(timerId) {
return clearTimer(clock, timerId, "Immediate");
};
function getTimeToNextFrame() {
return 16 - ((clock.now - start) % 16);
}
clock.requestAnimationFrame = function requestAnimationFrame(func) {
var result = addTimer(clock, {
func: func,
delay: getTimeToNextFrame(),
args: [clock.now + getTimeToNextFrame()],
animation: true
});
clock.setTimeout = function setTimeout(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout
});
};
return result.id || result;
};
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.setInterval = function setInterval(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout,
interval: timeout
});
};
clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
return clearTimer(clock, timerId, "AnimationFrame");
};
clock.clearInterval = function clearInterval(timerId) {
return clearTimer(clock, timerId, "Interval");
};
function updateHrTime(newNow) {
clock.hrNow += (newNow - clock.now);
}
clock.setImmediate = function setImmediate(func) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 1),
immediate: true
});
};
clock.runMicrotasks = function runMicrotasks() {
runJobs(clock);
};
clock.clearImmediate = function clearImmediate(timerId) {
return clearTimer(clock, timerId, "Immediate");
};
clock.tick = function tick(ms) {
ms = typeof ms === "number" ? ms : parseTime(ms);
var tickFrom = clock.now;
var tickTo = clock.now + ms;
var previous = clock.now;
var timer, firstException, oldNow;
clock.requestAnimationFrame = function requestAnimationFrame(func) {
var result = addTimer(clock, {
func: func,
delay: getTimeToNextFrame(),
args: [clock.now + getTimeToNextFrame()],
animation: true
});
clock.duringTick = true;
return result.id || result;
};
// perform process.nextTick()s
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
return clearTimer(clock, timerId, "AnimationFrame");
};
// perform each timer in the requested range
timer = firstTimerInRange(clock, tickFrom, tickTo);
while (timer && tickFrom <= tickTo) {
if (clock.timers[timer.id]) {
updateHrTime(timer.callAt);
tickFrom = timer.callAt;
clock.now = timer.callAt;
oldNow = clock.now;
try {
runJobs(clock);
callTimer(clock, timer);
} catch (e) {
firstException = firstException || e;
}
function updateHrTime(newNow) {
clock.hrNow += (newNow - clock.now);
}
// compensate for any setSystemTime() call during timer callback
if (oldNow !== clock.now) {
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
previous += clock.now - oldNow;
}
}
clock.tick = function tick(ms) {
ms = typeof ms === "number" ? ms : parseTime(ms);
var tickFrom = clock.now;
var tickTo = clock.now + ms;
var previous = clock.now;
var timer, firstException, oldNow;
timer = firstTimerInRange(clock, previous, tickTo);
previous = tickFrom;
}
clock.duringTick = true;
// perform process.nextTick()s again
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.duringTick = false;
// perform process.nextTick()s
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
// perform each timer in the requested range
timer = firstTimerInRange(clock, tickFrom, tickTo);
while (timer && tickFrom <= tickTo) {
if (clock.timers[timer.id]) {
updateHrTime(timer.callAt);
tickFrom = timer.callAt;
clock.now = timer.callAt;
oldNow = clock.now;
// corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
timer = firstTimerInRange(clock, tickFrom, tickTo);
if (timer) {
try {
runJobs(clock);
callTimer(clock, timer);
clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
} catch (e) {
firstException = firstException || e;
}
} else {
// no timers remaining in the requested range: move the clock all the way to the end
updateHrTime(tickTo);
clock.now = tickTo;
}
if (firstException) {
throw firstException;
}
return clock.now;
};
// compensate for any setSystemTime() call during timer callback
if (oldNow !== clock.now) {
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
previous += clock.now - oldNow;
}
clock.next = function next() {
runJobs(clock);
var timer = firstTimer(clock);
if (!timer) {
return clock.now;
}
timer = firstTimerInRange(clock, previous, tickTo);
previous = tickFrom;
}
// perform process.nextTick()s again
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.duringTick = false;
// corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
timer = firstTimerInRange(clock, tickFrom, tickTo);
if (timer) {
clock.duringTick = true;
try {
clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
} catch (e) {
firstException = firstException || e;
updateHrTime(timer.callAt);
clock.now = timer.callAt;
callTimer(clock, timer);
runJobs(clock);
return clock.now;
} finally {
clock.duringTick = false;
}
} else {
// no timers remaining in the requested range: move the clock all the way to the end
updateHrTime(tickTo);
clock.now = tickTo;
}
if (firstException) {
throw firstException;
}
return clock.now;
};
};
clock.next = function next() {
runJobs(clock);
var timer = firstTimer(clock);
if (!timer) {
return clock.now;
}
clock.duringTick = true;
try {
updateHrTime(timer.callAt);
clock.now = timer.callAt;
callTimer(clock, timer);
clock.runAll = function runAll() {
var numTimers, i;
runJobs(clock);
return clock.now;
} finally {
clock.duringTick = false;
}
};
for (i = 0; i < clock.loopLimit; i++) {
if (!clock.timers) {
return clock.now;
}
clock.runAll = function runAll() {
var numTimers, i;
runJobs(clock);
for (i = 0; i < clock.loopLimit; i++) {
if (!clock.timers) {
return clock.now;
numTimers = keys(clock.timers).length;
if (numTimers === 0) {
return clock.now;
}
clock.next();
}
numTimers = keys(clock.timers).length;
if (numTimers === 0) {
throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
};
clock.runToFrame = function runToFrame() {
return clock.tick(getTimeToNextFrame());
};
clock.runToLast = function runToLast() {
var timer = lastTimer(clock);
if (!timer) {
runJobs(clock);
return clock.now;
}
clock.next();
}
return clock.tick(timer.callAt);
};
throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
};
clock.reset = function reset() {
clock.timers = {};
};
clock.runToFrame = function runToFrame() {
return clock.tick(getTimeToNextFrame());
};
clock.setSystemTime = function setSystemTime(systemTime) {
// determine time difference
var newNow = getEpoch(systemTime);
var difference = newNow - clock.now;
var id, timer;
clock.runToLast = function runToLast() {
var timer = lastTimer(clock);
if (!timer) {
runJobs(clock);
return clock.now;
}
// update 'system clock'
clock.now = newNow;
return clock.tick(timer.callAt);
};
// update timers and intervals to keep them stable
for (id in clock.timers) {
if (clock.timers.hasOwnProperty(id)) {
timer = clock.timers[id];
timer.createdAt += difference;
timer.callAt += difference;
}
}
};
clock.reset = function reset() {
clock.timers = {};
};
if (performancePresent) {
clock.performance = Object.create(_global.performance);
clock.setSystemTime = function setSystemTime(systemTime) {
// determine time difference
var newNow = getEpoch(systemTime);
var difference = newNow - clock.now;
var id, timer;
var proto = Performance.prototype;
// update 'system clock'
clock.now = newNow;
Object
.getOwnPropertyNames(_global.Performance.prototype)
.forEach(function (name) {
clock.performance[name] = proto[name];
});
// update timers and intervals to keep them stable
for (id in clock.timers) {
if (clock.timers.hasOwnProperty(id)) {
timer = clock.timers[id];
timer.createdAt += difference;
timer.callAt += difference;
}
clock.performance.now = function lolexNow() {
return clock.hrNow;
};
}
};
if (performancePresent) {
clock.performance = Object.create(global.performance);
clock.performance.now = function lolexNow() {
return clock.hrNow;
};
}
if (hrtimePresent) {
clock.hrtime = function (prev) {
if (Array.isArray(prev)) {
var oldSecs = (prev[0] + prev[1] / 1e9);
var newSecs = (clock.hrNow / 1000);
var difference = (newSecs - oldSecs);
var secs = fixedFloor(difference);
var nanosecs = fixedModulo(difference * 1e9, 1e9);
if (hrtimePresent) {
clock.hrtime = function (prev) {
if (Array.isArray(prev)) {
var oldSecs = (prev[0] + prev[1] / 1e9);
var newSecs = (clock.hrNow / 1000);
var difference = (newSecs - oldSecs);
var secs = fixedFloor(difference);
var nanosecs = fixedModulo(difference * 1e9, 1e9);
return [
secs,
nanosecs
];
}
return [
secs,
nanosecs
fixedFloor(clock.hrNow / 1000),
fixedModulo(clock.hrNow * 1e6, 1e9)
];
}
return [
fixedFloor(clock.hrNow / 1000),
fixedModulo(clock.hrNow * 1e6, 1e9)
];
};
};
}
return clock;
}
return clock;
}
exports.createClock = createClock;
/**
* @param config {Object} optional config
* @param config.target {Object} the target to install timers in (default `window`)
* @param config.now {number|Date} a number (in milliseconds) or a Date object (default epoch)
* @param config.toFake {string[]} names of the methods that should be faked.
* @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
* @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
* @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
*/
function install(config) {
if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
throw new TypeError("lolex.install called with " + String(config) +
" lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
}
config = typeof config !== "undefined" ? config : {};
config.shouldAdvanceTime = config.shouldAdvanceTime || false;
config.advanceTimeDelta = config.advanceTimeDelta || 20;
/**
* @param config {Object} optional config
* @param config.target {Object} the target to install timers in (default `window`)
* @param config.now {number|Date} a number (in milliseconds) or a Date object (default epoch)
* @param config.toFake {string[]} names of the methods that should be faked.
* @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
* @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
* @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
*/
exports.install = function install(config) {
if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
throw new TypeError("lolex.install called with " + String(config) +
" lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
}
config = typeof config !== "undefined" ? config : {};
config.shouldAdvanceTime = config.shouldAdvanceTime || false;
config.advanceTimeDelta = config.advanceTimeDelta || 20;
var i, l;
var target = config.target || _global;
var clock = createClock(config.now, config.loopLimit);
var i, l;
var target = config.target || global;
var clock = createClock(config.now, config.loopLimit);
clock.uninstall = function () {
return uninstall(clock, target, config);
};
clock.uninstall = function () {
return uninstall(clock, target, config);
};
clock.methods = config.toFake || [];
clock.methods = config.toFake || [];
if (clock.methods.length === 0) {
// do not fake nextTick by default - GitHub#126
clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
}
if (clock.methods.length === 0) {
// do not fake nextTick by default - GitHub#126
clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
}
for (i = 0, l = clock.methods.length; i < l; i++) {
if (clock.methods[i] === "hrtime") {
if (target.process && typeof target.process.hrtime === "function") {
hijackMethod(target.process, clock.methods[i], clock);
for (i = 0, l = clock.methods.length; i < l; i++) {
if (clock.methods[i] === "hrtime") {
if (target.process && typeof target.process.hrtime === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else if (clock.methods[i] === "nextTick") {
if (target.process && typeof target.process.nextTick === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else {
if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
var intervalId = target[clock.methods[i]](
intervalTick,
config.advanceTimeDelta);
clock.attachedInterval = intervalId;
}
hijackMethod(target, clock.methods[i], clock);
}
} else if (clock.methods[i] === "nextTick") {
if (target.process && typeof target.process.nextTick === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else {
if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
var intervalId = target[clock.methods[i]](
intervalTick,
config.advanceTimeDelta);
clock.attachedInterval = intervalId;
}
hijackMethod(target, clock.methods[i], clock);
}
return clock;
}
return clock;
};
return {
timers: timers,
createClock: createClock,
install: install,
withGlobal: withGlobal
};
}
var defaultImplementation = withGlobal(global || window);
exports.timers = defaultImplementation.timers;
exports.createClock = defaultImplementation.createClock;
exports.install = defaultImplementation.install;
exports.withGlobal = withGlobal;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1])(1)
});
{
"name": "lolex",
"description": "Fake JavaScript timers",
"version": "2.3.2",
"version": "2.4.0",
"homepage": "http://github.com/sinonjs/lolex",

@@ -34,4 +34,4 @@ "author": "Christian Johansen",

"devDependencies": {
"browserify": "14.4.0",
"eslint": "4.2.0",
"browserify": "16.2.0",
"eslint": "4.19.1",
"eslint-config-sinon": "1.0.3",

@@ -41,8 +41,8 @@ "eslint-plugin-ie11": "1.0.0",

"husky": "0.14.3",
"lint-staged": "4.0.2",
"mocha": "4.0.1",
"lint-staged": "7.0.4",
"mocha": "5.1.0",
"mochify": "4.0.0",
"npm-run-all": "4.0.2",
"npm-run-all": "4.1.2",
"referee": "1.2.0",
"sinon": "4.1.2"
"sinon": "4.5.0"
},

@@ -49,0 +49,0 @@ "eslintConfig": {

@@ -1,2 +0,2 @@

# Lolex [![Build Status](https://travis-ci.org/sinonjs/lolex.svg?branch=master)](https://travis-ci.org/sinonjs/lolex) [![bitHound Overall Score](https://www.bithound.io/github/sinonjs/lolex/badges/score.svg)](https://www.bithound.io/github/sinonjs/lolex)
# Lolex [![Build Status](https://travis-ci.org/sinonjs/lolex.svg?branch=master)](https://travis-ci.org/sinonjs/lolex)

@@ -236,2 +236,6 @@ JavaScript implementation of the timer APIs; `setTimeout`, `clearTimeout`, `setImmediate`, `clearImmediate`, `setInterval`, `clearInterval`, `requestAnimationFrame`, and `cancelAnimationFrame`, along with a clock instance that controls the flow of time. Lolex also provides a `Date` implementation that gets its time from the clock.

### `clock.runMicrotasks()`
This runs all pending microtasks scheduled with `nextTick` but none of the timers and is mostly useful for libraries using lolex underneath and for running `nextTick` items without any timers.
### `clock.runToFrame()`

@@ -273,2 +277,6 @@

### `lolex.withGlobal`
In order to support creating clocks based on separate or sandboxed environments (such as JSDOM), Lolex exports a factory method which takes single argument `global`, which it inspects to figure out what to mock and what features to support. When invoking this function with a global, you will get back an object with `timers`, `createClock` and `install` - same as the regular Lolex exports only based on the passed in global instead of the global environment.
## Running tests

@@ -275,0 +283,0 @@

"use strict";
var userAgent = global.navigator && global.navigator.userAgent;
var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
function withGlobal(_global) {
var userAgent = _global.navigator && _global.navigator.userAgent;
var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
var maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint
// Make properties writable in IE, as per
// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
if (isRunningInIE) {
global.setTimeout = global.setTimeout;
global.clearTimeout = global.clearTimeout;
global.setInterval = global.setInterval;
global.clearInterval = global.clearInterval;
global.Date = global.Date;
}
// Make properties writable in IE, as per
// http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
if (isRunningInIE) {
_global.setTimeout = _global.setTimeout;
_global.clearTimeout = _global.clearTimeout;
_global.setInterval = _global.setInterval;
_global.clearInterval = _global.clearInterval;
_global.Date = _global.Date;
}
// setImmediate is not a standard function
// avoid adding the prop to the window object if not present
if (global.setImmediate !== undefined) {
global.setImmediate = global.setImmediate;
global.clearImmediate = global.clearImmediate;
}
// setImmediate is not a standard function
// avoid adding the prop to the window object if not present
if (_global.setImmediate !== undefined) {
_global.setImmediate = _global.setImmediate;
_global.clearImmediate = _global.clearImmediate;
}
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
// browsers, a number.
// see https://github.com/cjohansen/Sinon.JS/pull/436
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
// browsers, a number.
// see https://github.com/cjohansen/Sinon.JS/pull/436
var NOOP = function () { return undefined; };
var timeoutResult = setTimeout(NOOP, 0);
var addTimerReturnsObject = typeof timeoutResult === "object";
var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
var nextTickPresent = (global.process && typeof global.process.nextTick === "function");
var performancePresent = (global.performance && typeof global.performance.now === "function");
var requestAnimationFramePresent = (global.requestAnimationFrame && typeof global.requestAnimationFrame === "function");
var cancelAnimationFramePresent = (global.cancelAnimationFrame && typeof global.cancelAnimationFrame === "function");
var NOOP = function () { return undefined; };
var timeoutResult = _global.setTimeout(NOOP, 0);
var addTimerReturnsObject = typeof timeoutResult === "object";
var hrtimePresent = (_global.process && typeof _global.process.hrtime === "function");
var nextTickPresent = (_global.process && typeof _global.process.nextTick === "function");
var performancePresent = (_global.performance && typeof _global.performance.now === "function");
var requestAnimationFramePresent = (
_global.requestAnimationFrame && typeof _global.requestAnimationFrame === "function"
);
var cancelAnimationFramePresent = (
_global.cancelAnimationFrame && typeof _global.cancelAnimationFrame === "function"
);
clearTimeout(timeoutResult);
_global.clearTimeout(timeoutResult);
var NativeDate = Date;
var uniqueTimerId = 1;
var NativeDate = Date;
var uniqueTimerId = 1;
/**
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
* number of milliseconds. This is used to support human-readable strings passed
* to clock.tick()
*/
function parseTime(str) {
if (!str) {
return 0;
}
/**
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
* number of milliseconds. This is used to support human-readable strings passed
* to clock.tick()
*/
function parseTime(str) {
if (!str) {
return 0;
}
var strings = str.split(":");
var l = strings.length;
var i = l;
var ms = 0;
var parsed;
var strings = str.split(":");
var l = strings.length;
var i = l;
var ms = 0;
var parsed;
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
}
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
}
while (i--) {
parsed = parseInt(strings[i], 10);
while (i--) {
parsed = parseInt(strings[i], 10);
if (parsed >= 60) {
throw new Error("Invalid time " + str);
if (parsed >= 60) {
throw new Error("Invalid time " + str);
}
ms += parsed * Math.pow(60, (l - i - 1));
}
ms += parsed * Math.pow(60, (l - i - 1));
return ms * 1000;
}
return ms * 1000;
}
/**
* Floor function that also works for negative numbers
*/
function fixedFloor(n) {
return (n >= 0 ? Math.floor(n) : Math.ceil(n));
}
/**
* Floor function that also works for negative numbers
*/
function fixedFloor(n) {
return (n >= 0 ? Math.floor(n) : Math.ceil(n));
}
/**
* % operator that also works for negative numbers
*/
function fixedModulo(n, m) {
return ((n % m) + m) % m;
}
/**
* % operator that also works for negative numbers
*/
function fixedModulo(n, m) {
return ((n % m) + m) % m;
}
/**
* Used to grok the `now` parameter to createClock.
* @param epoch {Date|number} the system time
*/
function getEpoch(epoch) {
if (!epoch) { return 0; }
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
if (typeof epoch === "number") { return epoch; }
throw new TypeError("now should be milliseconds since UNIX epoch");
}
/**
* Used to grok the `now` parameter to createClock.
* @param epoch {Date|number} the system time
*/
function getEpoch(epoch) {
if (!epoch) { return 0; }
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
if (typeof epoch === "number") { return epoch; }
throw new TypeError("now should be milliseconds since UNIX epoch");
}
function inRange(from, to, timer) {
return timer && timer.callAt >= from && timer.callAt <= to;
}
function inRange(from, to, timer) {
return timer && timer.callAt >= from && timer.callAt <= to;
}
function mirrorDateProperties(target, source) {
var prop;
for (prop in source) {
if (source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
function mirrorDateProperties(target, source) {
var prop;
for (prop in source) {
if (source.hasOwnProperty(prop)) {
target[prop] = source[prop];
// set special now implementation
if (source.now) {
target.now = function now() {
return target.clock.now;
};
} else {
delete target.now;
}
}
// set special now implementation
if (source.now) {
target.now = function now() {
return target.clock.now;
// set special toSource implementation
if (source.toSource) {
target.toSource = function toSource() {
return source.toSource();
};
} else {
delete target.toSource;
}
// set special toString implementation
target.toString = function toString() {
return source.toString();
};
} else {
delete target.now;
}
// set special toSource implementation
if (source.toSource) {
target.toSource = function toSource() {
return source.toSource();
};
} else {
delete target.toSource;
target.prototype = source.prototype;
target.parse = source.parse;
target.UTC = source.UTC;
target.prototype.toUTCString = source.prototype.toUTCString;
return target;
}
// set special toString implementation
target.toString = function toString() {
return source.toString();
};
function createDate() {
function ClockDate(year, month, date, hour, minute, second, ms) {
// Defensive and verbose to avoid potential harm in passing
// explicit undefined when user does not pass argument
switch (arguments.length) {
case 0:
return new NativeDate(ClockDate.clock.now);
case 1:
return new NativeDate(year);
case 2:
return new NativeDate(year, month);
case 3:
return new NativeDate(year, month, date);
case 4:
return new NativeDate(year, month, date, hour);
case 5:
return new NativeDate(year, month, date, hour, minute);
case 6:
return new NativeDate(year, month, date, hour, minute, second);
default:
return new NativeDate(year, month, date, hour, minute, second, ms);
}
}
target.prototype = source.prototype;
target.parse = source.parse;
target.UTC = source.UTC;
target.prototype.toUTCString = source.prototype.toUTCString;
return mirrorDateProperties(ClockDate, NativeDate);
}
return target;
}
function createDate() {
function ClockDate(year, month, date, hour, minute, second, ms) {
// Defensive and verbose to avoid potential harm in passing
// explicit undefined when user does not pass argument
switch (arguments.length) {
case 0:
return new NativeDate(ClockDate.clock.now);
case 1:
return new NativeDate(year);
case 2:
return new NativeDate(year, month);
case 3:
return new NativeDate(year, month, date);
case 4:
return new NativeDate(year, month, date, hour);
case 5:
return new NativeDate(year, month, date, hour, minute);
case 6:
return new NativeDate(year, month, date, hour, minute, second);
default:
return new NativeDate(year, month, date, hour, minute, second, ms);
function enqueueJob(clock, job) {
// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
if (!clock.jobs) {
clock.jobs = [];
}
clock.jobs.push(job);
}
return mirrorDateProperties(ClockDate, NativeDate);
}
function enqueueJob(clock, job) {
// enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
if (!clock.jobs) {
function runJobs(clock) {
// runs all microtick-deferred tasks - ecma262/#sec-runjobs
if (!clock.jobs) {
return;
}
for (var i = 0; i < clock.jobs.length; i++) {
var job = clock.jobs[i];
job.func.apply(null, job.args);
}
clock.jobs = [];
}
clock.jobs.push(job);
}
function runJobs(clock) {
// runs all microtick-deferred tasks - ecma262/#sec-runjobs
if (!clock.jobs) {
return;
}
for (var i = 0; i < clock.jobs.length; i++) {
var job = clock.jobs[i];
job.func.apply(null, job.args);
}
clock.jobs = [];
}
function addTimer(clock, timer) {
if (timer.func === undefined) {
throw new Error("Callback must be provided to timer calls");
}
function addTimer(clock, timer) {
if (timer.func === undefined) {
throw new Error("Callback must be provided to timer calls");
}
timer.type = timer.immediate ? "Immediate" : "Timeout";
timer.type = timer.immediate ? "Immediate" : "Timeout";
if (timer.hasOwnProperty("delay")) {
timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
timer.delay = Math.max(0, timer.delay);
}
if (timer.hasOwnProperty("delay")) {
timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;
timer.delay = Math.max(0, timer.delay);
}
if (timer.hasOwnProperty("interval")) {
timer.type = "Interval";
timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
}
if (timer.hasOwnProperty("interval")) {
timer.type = "Interval";
timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;
}
if (timer.hasOwnProperty("animation")) {
timer.type = "AnimationFrame";
timer.animation = true;
}
if (timer.hasOwnProperty("animation")) {
timer.type = "AnimationFrame";
timer.animation = true;
}
if (!clock.timers) {
clock.timers = {};
}
if (!clock.timers) {
clock.timers = {};
}
timer.id = uniqueTimerId++;
timer.createdAt = clock.now;
timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
timer.id = uniqueTimerId++;
timer.createdAt = clock.now;
timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
clock.timers[timer.id] = timer;
clock.timers[timer.id] = timer;
if (addTimerReturnsObject) {
return {
id: timer.id,
ref: NOOP,
unref: NOOP
};
}
if (addTimerReturnsObject) {
return {
id: timer.id,
ref: NOOP,
unref: NOOP
};
return timer.id;
}
return timer.id;
}
/* eslint consistent-return: "off" */
function compareTimers(a, b) {
// Sort first by absolute timing
if (a.callAt < b.callAt) {
return -1;
}
if (a.callAt > b.callAt) {
return 1;
}
/* eslint consistent-return: "off" */
function compareTimers(a, b) {
// Sort first by absolute timing
if (a.callAt < b.callAt) {
return -1;
}
if (a.callAt > b.callAt) {
return 1;
}
// Sort next by immediate, immediate timers take precedence
if (a.immediate && !b.immediate) {
return -1;
}
if (!a.immediate && b.immediate) {
return 1;
}
// Sort next by immediate, immediate timers take precedence
if (a.immediate && !b.immediate) {
return -1;
}
if (!a.immediate && b.immediate) {
return 1;
}
// Sort next by creation time, earlier-created timers take precedence
if (a.createdAt < b.createdAt) {
return -1;
}
if (a.createdAt > b.createdAt) {
return 1;
}
// Sort next by creation time, earlier-created timers take precedence
if (a.createdAt < b.createdAt) {
return -1;
}
if (a.createdAt > b.createdAt) {
return 1;
}
// Sort next by id, lower-id timers take precedence
if (a.id < b.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
// Sort next by id, lower-id timers take precedence
if (a.id < b.id) {
return -1;
// As timer ids are unique, no fallback `0` is necessary
}
if (a.id > b.id) {
return 1;
}
// As timer ids are unique, no fallback `0` is necessary
}
function firstTimerInRange(clock, from, to) {
var timers = clock.timers;
var timer = null;
var id, isInRange;
function firstTimerInRange(clock, from, to) {
var timers = clock.timers;
var timer = null;
var id, isInRange;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
isInRange = inRange(from, to, timers[id]);
for (id in timers) {
if (timers.hasOwnProperty(id)) {
isInRange = inRange(from, to, timers[id]);
if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
timer = timers[id];
if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function firstTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
function firstTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === 1) {
timer = timers[id];
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === 1) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function lastTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
function lastTimer(clock) {
var timers = clock.timers;
var timer = null;
var id;
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === -1) {
timer = timers[id];
for (id in timers) {
if (timers.hasOwnProperty(id)) {
if (!timer || compareTimers(timer, timers[id]) === -1) {
timer = timers[id];
}
}
}
return timer;
}
return timer;
}
function callTimer(clock, timer) {
if (typeof timer.interval === "number") {
clock.timers[timer.id].callAt += timer.interval;
} else {
delete clock.timers[timer.id];
}
function callTimer(clock, timer) {
if (typeof timer.interval === "number") {
clock.timers[timer.id].callAt += timer.interval;
} else {
delete clock.timers[timer.id];
if (typeof timer.func === "function") {
timer.func.apply(null, timer.args);
} else {
/* eslint no-eval: "off" */
eval(timer.func);
}
}
if (typeof timer.func === "function") {
timer.func.apply(null, timer.args);
} else {
/* eslint no-eval: "off" */
eval(timer.func);
}
}
function clearTimer(clock, timerId, ttype) {
if (!timerId) {
// null appears to be allowed in most browsers, and appears to be
// relied upon by some libraries, like Bootstrap carousel
return;
}
function clearTimer(clock, timerId, ttype) {
if (!timerId) {
// null appears to be allowed in most browsers, and appears to be
// relied upon by some libraries, like Bootstrap carousel
return;
}
if (!clock.timers) {
clock.timers = [];
}
if (!clock.timers) {
clock.timers = [];
}
// in Node, timerId is an object with .ref()/.unref(), and
// its .id field is the actual timer id.
if (typeof timerId === "object") {
timerId = timerId.id;
}
// in Node, timerId is an object with .ref()/.unref(), and
// its .id field is the actual timer id.
if (typeof timerId === "object") {
timerId = timerId.id;
if (clock.timers.hasOwnProperty(timerId)) {
// check that the ID matches a timer of the correct type
var timer = clock.timers[timerId];
if (timer.type === ttype) {
delete clock.timers[timerId];
} else {
var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
throw new Error("Cannot clear timer: timer created with " + schedule
+ "() but cleared with " + clear + "()");
}
}
}
if (clock.timers.hasOwnProperty(timerId)) {
// check that the ID matches a timer of the correct type
var timer = clock.timers[timerId];
if (timer.type === ttype) {
delete clock.timers[timerId];
} else {
var clear = ttype === "AnimationFrame" ? "cancelAnimationFrame" : "clear" + ttype;
var schedule = timer.type === "AnimationFrame" ? "requestAnimationFrame" : "set" + timer.type;
throw new Error("Cannot clear timer: timer created with " + schedule
+ "() but cleared with " + clear + "()");
function uninstall(clock, target, config) {
var method,
i,
l;
var installedHrTime = "_hrtime";
var installedNextTick = "_nextTick";
for (i = 0, l = clock.methods.length; i < l; i++) {
method = clock.methods[i];
if (method === "hrtime" && target.process) {
target.process.hrtime = clock[installedHrTime];
} else if (method === "nextTick" && target.process) {
target.process.nextTick = clock[installedNextTick];
} else {
if (target[method] && target[method].hadOwnProperty) {
target[method] = clock["_" + method];
if (method === "clearInterval" && config.shouldAdvanceTime === true) {
target[method](clock.attachedInterval);
}
} else {
try {
delete target[method];
} catch (ignore) { /* eslint empty-block: "off" */ }
}
}
}
// Prevent multiple executions which will completely remove these props
clock.methods = [];
// return pending timers, to enable checking what timers remained on uninstall
if (!clock.timers) {
return [];
}
return Object.keys(clock.timers).map(function mapper(key) {
return clock.timers[key];
});
}
}
function uninstall(clock, target, config) {
var method,
i,
l;
var installedHrTime = "_hrtime";
var installedNextTick = "_nextTick";
function hijackMethod(target, method, clock) {
var prop;
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
clock["_" + method] = target[method];
for (i = 0, l = clock.methods.length; i < l; i++) {
method = clock.methods[i];
if (method === "hrtime" && target.process) {
target.process.hrtime = clock[installedHrTime];
} else if (method === "nextTick" && target.process) {
target.process.nextTick = clock[installedNextTick];
if (method === "Date") {
var date = mirrorDateProperties(clock[method], target[method]);
target[method] = date;
} else {
if (target[method] && target[method].hadOwnProperty) {
target[method] = clock["_" + method];
if (method === "clearInterval" && config.shouldAdvanceTime === true) {
target[method](clock.attachedInterval);
target[method] = function () {
return clock[method].apply(clock, arguments);
};
for (prop in clock[method]) {
if (clock[method].hasOwnProperty(prop)) {
target[method][prop] = clock[method][prop];
}
} else {
try {
delete target[method];
} catch (ignore) { /* eslint empty-block: "off" */ }
}
}
target[method].clock = clock;
}
// Prevent multiple executions which will completely remove these props
clock.methods = [];
// return pending timers, to enable checking what timers remained on uninstall
if (!clock.timers) {
return [];
function doIntervalTick(clock, advanceTimeDelta) {
clock.tick(advanceTimeDelta);
}
return Object.keys(clock.timers).map(function mapper(key) {
return clock.timers[key];
});
}
function hijackMethod(target, method, clock) {
var prop;
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
clock["_" + method] = target[method];
var timers = {
setTimeout: _global.setTimeout,
clearTimeout: _global.clearTimeout,
setImmediate: _global.setImmediate,
clearImmediate: _global.clearImmediate,
setInterval: _global.setInterval,
clearInterval: _global.clearInterval,
Date: _global.Date
};
if (method === "Date") {
var date = mirrorDateProperties(clock[method], target[method]);
target[method] = date;
} else {
target[method] = function () {
return clock[method].apply(clock, arguments);
};
if (hrtimePresent) {
timers.hrtime = _global.process.hrtime;
}
for (prop in clock[method]) {
if (clock[method].hasOwnProperty(prop)) {
target[method][prop] = clock[method][prop];
}
}
if (nextTickPresent) {
timers.nextTick = _global.process.nextTick;
}
target[method].clock = clock;
}
if (performancePresent) {
timers.performance = _global.performance;
}
function doIntervalTick(clock, advanceTimeDelta) {
clock.tick(advanceTimeDelta);
}
if (requestAnimationFramePresent) {
timers.requestAnimationFrame = _global.requestAnimationFrame;
}
var timers = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setImmediate: global.setImmediate,
clearImmediate: global.clearImmediate,
setInterval: setInterval,
clearInterval: clearInterval,
Date: Date
};
if (cancelAnimationFramePresent) {
timers.cancelAnimationFrame = _global.cancelAnimationFrame;
}
if (hrtimePresent) {
timers.hrtime = global.process.hrtime;
}
var keys = Object.keys || function (obj) {
var ks = [];
var key;
if (nextTickPresent) {
timers.nextTick = global.process.nextTick;
}
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ks.push(key);
}
}
if (performancePresent) {
timers.performance = global.performance;
}
return ks;
};
if (requestAnimationFramePresent) {
timers.requestAnimationFrame = global.requestAnimationFrame;
}
/**
* @param start {Date|number} the system time
* @param loopLimit {number} maximum number of timers that will be run when calling runAll()
*/
function createClock(start, loopLimit) {
start = start || 0;
loopLimit = loopLimit || 1000;
if (cancelAnimationFramePresent) {
timers.cancelAnimationFrame = global.cancelAnimationFrame;
}
var clock = {
now: getEpoch(start),
hrNow: 0,
timeouts: {},
Date: createDate(),
loopLimit: loopLimit
};
var keys = Object.keys || function (obj) {
var ks = [];
var key;
clock.Date.clock = clock;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ks.push(key);
function getTimeToNextFrame() {
return 16 - ((clock.now - start) % 16);
}
}
return ks;
};
clock.setTimeout = function setTimeout(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout
});
};
exports.timers = timers;
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.setInterval = function setInterval(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout,
interval: timeout
});
};
/**
* @param start {Date|number} the system time
* @param loopLimit {number} maximum number of timers that will be run when calling runAll()
*/
function createClock(start, loopLimit) {
start = start || 0;
loopLimit = loopLimit || 1000;
clock.clearInterval = function clearInterval(timerId) {
return clearTimer(clock, timerId, "Interval");
};
var clock = {
now: getEpoch(start),
hrNow: 0,
timeouts: {},
Date: createDate(),
loopLimit: loopLimit
};
clock.setImmediate = function setImmediate(func) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 1),
immediate: true
});
};
clock.Date.clock = clock;
clock.clearImmediate = function clearImmediate(timerId) {
return clearTimer(clock, timerId, "Immediate");
};
function getTimeToNextFrame() {
return 16 - ((clock.now - start) % 16);
}
clock.requestAnimationFrame = function requestAnimationFrame(func) {
var result = addTimer(clock, {
func: func,
delay: getTimeToNextFrame(),
args: [clock.now + getTimeToNextFrame()],
animation: true
});
clock.setTimeout = function setTimeout(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout
});
};
return result.id || result;
};
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.setInterval = function setInterval(func, timeout) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 2),
delay: timeout,
interval: timeout
});
};
clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
return clearTimer(clock, timerId, "AnimationFrame");
};
clock.clearInterval = function clearInterval(timerId) {
return clearTimer(clock, timerId, "Interval");
};
function updateHrTime(newNow) {
clock.hrNow += (newNow - clock.now);
}
clock.setImmediate = function setImmediate(func) {
return addTimer(clock, {
func: func,
args: Array.prototype.slice.call(arguments, 1),
immediate: true
});
};
clock.runMicrotasks = function runMicrotasks() {
runJobs(clock);
};
clock.clearImmediate = function clearImmediate(timerId) {
return clearTimer(clock, timerId, "Immediate");
};
clock.tick = function tick(ms) {
ms = typeof ms === "number" ? ms : parseTime(ms);
var tickFrom = clock.now;
var tickTo = clock.now + ms;
var previous = clock.now;
var timer, firstException, oldNow;
clock.requestAnimationFrame = function requestAnimationFrame(func) {
var result = addTimer(clock, {
func: func,
delay: getTimeToNextFrame(),
args: [clock.now + getTimeToNextFrame()],
animation: true
});
clock.duringTick = true;
return result.id || result;
};
// perform process.nextTick()s
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {
return clearTimer(clock, timerId, "AnimationFrame");
};
// perform each timer in the requested range
timer = firstTimerInRange(clock, tickFrom, tickTo);
while (timer && tickFrom <= tickTo) {
if (clock.timers[timer.id]) {
updateHrTime(timer.callAt);
tickFrom = timer.callAt;
clock.now = timer.callAt;
oldNow = clock.now;
try {
runJobs(clock);
callTimer(clock, timer);
} catch (e) {
firstException = firstException || e;
}
function updateHrTime(newNow) {
clock.hrNow += (newNow - clock.now);
}
// compensate for any setSystemTime() call during timer callback
if (oldNow !== clock.now) {
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
previous += clock.now - oldNow;
}
}
clock.tick = function tick(ms) {
ms = typeof ms === "number" ? ms : parseTime(ms);
var tickFrom = clock.now;
var tickTo = clock.now + ms;
var previous = clock.now;
var timer, firstException, oldNow;
timer = firstTimerInRange(clock, previous, tickTo);
previous = tickFrom;
}
clock.duringTick = true;
// perform process.nextTick()s again
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.duringTick = false;
// perform process.nextTick()s
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
// perform each timer in the requested range
timer = firstTimerInRange(clock, tickFrom, tickTo);
while (timer && tickFrom <= tickTo) {
if (clock.timers[timer.id]) {
updateHrTime(timer.callAt);
tickFrom = timer.callAt;
clock.now = timer.callAt;
oldNow = clock.now;
// corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
timer = firstTimerInRange(clock, tickFrom, tickTo);
if (timer) {
try {
runJobs(clock);
callTimer(clock, timer);
clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
} catch (e) {
firstException = firstException || e;
}
} else {
// no timers remaining in the requested range: move the clock all the way to the end
updateHrTime(tickTo);
clock.now = tickTo;
}
if (firstException) {
throw firstException;
}
return clock.now;
};
// compensate for any setSystemTime() call during timer callback
if (oldNow !== clock.now) {
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
previous += clock.now - oldNow;
}
clock.next = function next() {
runJobs(clock);
var timer = firstTimer(clock);
if (!timer) {
return clock.now;
}
timer = firstTimerInRange(clock, previous, tickTo);
previous = tickFrom;
}
// perform process.nextTick()s again
oldNow = clock.now;
runJobs(clock);
if (oldNow !== clock.now) {
// compensate for any setSystemTime() call during process.nextTick() callback
tickFrom += clock.now - oldNow;
tickTo += clock.now - oldNow;
}
clock.duringTick = false;
// corner case: during runJobs, new timers were scheduled which could be in the range [clock.now, tickTo]
timer = firstTimerInRange(clock, tickFrom, tickTo);
if (timer) {
clock.duringTick = true;
try {
clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range
} catch (e) {
firstException = firstException || e;
updateHrTime(timer.callAt);
clock.now = timer.callAt;
callTimer(clock, timer);
runJobs(clock);
return clock.now;
} finally {
clock.duringTick = false;
}
} else {
// no timers remaining in the requested range: move the clock all the way to the end
updateHrTime(tickTo);
clock.now = tickTo;
}
if (firstException) {
throw firstException;
}
return clock.now;
};
};
clock.next = function next() {
runJobs(clock);
var timer = firstTimer(clock);
if (!timer) {
return clock.now;
}
clock.duringTick = true;
try {
updateHrTime(timer.callAt);
clock.now = timer.callAt;
callTimer(clock, timer);
clock.runAll = function runAll() {
var numTimers, i;
runJobs(clock);
return clock.now;
} finally {
clock.duringTick = false;
}
};
for (i = 0; i < clock.loopLimit; i++) {
if (!clock.timers) {
return clock.now;
}
clock.runAll = function runAll() {
var numTimers, i;
runJobs(clock);
for (i = 0; i < clock.loopLimit; i++) {
if (!clock.timers) {
return clock.now;
numTimers = keys(clock.timers).length;
if (numTimers === 0) {
return clock.now;
}
clock.next();
}
numTimers = keys(clock.timers).length;
if (numTimers === 0) {
throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
};
clock.runToFrame = function runToFrame() {
return clock.tick(getTimeToNextFrame());
};
clock.runToLast = function runToLast() {
var timer = lastTimer(clock);
if (!timer) {
runJobs(clock);
return clock.now;
}
clock.next();
}
return clock.tick(timer.callAt);
};
throw new Error("Aborting after running " + clock.loopLimit + " timers, assuming an infinite loop!");
};
clock.reset = function reset() {
clock.timers = {};
};
clock.runToFrame = function runToFrame() {
return clock.tick(getTimeToNextFrame());
};
clock.setSystemTime = function setSystemTime(systemTime) {
// determine time difference
var newNow = getEpoch(systemTime);
var difference = newNow - clock.now;
var id, timer;
clock.runToLast = function runToLast() {
var timer = lastTimer(clock);
if (!timer) {
runJobs(clock);
return clock.now;
}
// update 'system clock'
clock.now = newNow;
return clock.tick(timer.callAt);
};
// update timers and intervals to keep them stable
for (id in clock.timers) {
if (clock.timers.hasOwnProperty(id)) {
timer = clock.timers[id];
timer.createdAt += difference;
timer.callAt += difference;
}
}
};
clock.reset = function reset() {
clock.timers = {};
};
if (performancePresent) {
clock.performance = Object.create(_global.performance);
clock.setSystemTime = function setSystemTime(systemTime) {
// determine time difference
var newNow = getEpoch(systemTime);
var difference = newNow - clock.now;
var id, timer;
var proto = Performance.prototype;
// update 'system clock'
clock.now = newNow;
Object
.getOwnPropertyNames(_global.Performance.prototype)
.forEach(function (name) {
clock.performance[name] = proto[name];
});
// update timers and intervals to keep them stable
for (id in clock.timers) {
if (clock.timers.hasOwnProperty(id)) {
timer = clock.timers[id];
timer.createdAt += difference;
timer.callAt += difference;
}
clock.performance.now = function lolexNow() {
return clock.hrNow;
};
}
};
if (performancePresent) {
clock.performance = Object.create(global.performance);
clock.performance.now = function lolexNow() {
return clock.hrNow;
};
}
if (hrtimePresent) {
clock.hrtime = function (prev) {
if (Array.isArray(prev)) {
var oldSecs = (prev[0] + prev[1] / 1e9);
var newSecs = (clock.hrNow / 1000);
var difference = (newSecs - oldSecs);
var secs = fixedFloor(difference);
var nanosecs = fixedModulo(difference * 1e9, 1e9);
if (hrtimePresent) {
clock.hrtime = function (prev) {
if (Array.isArray(prev)) {
var oldSecs = (prev[0] + prev[1] / 1e9);
var newSecs = (clock.hrNow / 1000);
var difference = (newSecs - oldSecs);
var secs = fixedFloor(difference);
var nanosecs = fixedModulo(difference * 1e9, 1e9);
return [
secs,
nanosecs
];
}
return [
secs,
nanosecs
fixedFloor(clock.hrNow / 1000),
fixedModulo(clock.hrNow * 1e6, 1e9)
];
}
return [
fixedFloor(clock.hrNow / 1000),
fixedModulo(clock.hrNow * 1e6, 1e9)
];
};
};
}
return clock;
}
return clock;
}
exports.createClock = createClock;
/**
* @param config {Object} optional config
* @param config.target {Object} the target to install timers in (default `window`)
* @param config.now {number|Date} a number (in milliseconds) or a Date object (default epoch)
* @param config.toFake {string[]} names of the methods that should be faked.
* @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
* @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
* @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
*/
function install(config) {
if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
throw new TypeError("lolex.install called with " + String(config) +
" lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
}
config = typeof config !== "undefined" ? config : {};
config.shouldAdvanceTime = config.shouldAdvanceTime || false;
config.advanceTimeDelta = config.advanceTimeDelta || 20;
/**
* @param config {Object} optional config
* @param config.target {Object} the target to install timers in (default `window`)
* @param config.now {number|Date} a number (in milliseconds) or a Date object (default epoch)
* @param config.toFake {string[]} names of the methods that should be faked.
* @param config.loopLimit {number} the maximum number of timers that will be run when calling runAll()
* @param config.shouldAdvanceTime {Boolean} tells lolex to increment mocked time automatically (default false)
* @param config.advanceTimeDelta {Number} increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)
*/
exports.install = function install(config) {
if ( arguments.length > 1 || config instanceof Date || Array.isArray(config) || typeof config === "number") {
throw new TypeError("lolex.install called with " + String(config) +
" lolex 2.0+ requires an object parameter - see https://github.com/sinonjs/lolex");
}
config = typeof config !== "undefined" ? config : {};
config.shouldAdvanceTime = config.shouldAdvanceTime || false;
config.advanceTimeDelta = config.advanceTimeDelta || 20;
var i, l;
var target = config.target || _global;
var clock = createClock(config.now, config.loopLimit);
var i, l;
var target = config.target || global;
var clock = createClock(config.now, config.loopLimit);
clock.uninstall = function () {
return uninstall(clock, target, config);
};
clock.uninstall = function () {
return uninstall(clock, target, config);
};
clock.methods = config.toFake || [];
clock.methods = config.toFake || [];
if (clock.methods.length === 0) {
// do not fake nextTick by default - GitHub#126
clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
}
if (clock.methods.length === 0) {
// do not fake nextTick by default - GitHub#126
clock.methods = keys(timers).filter(function (key) {return key !== "nextTick";});
}
for (i = 0, l = clock.methods.length; i < l; i++) {
if (clock.methods[i] === "hrtime") {
if (target.process && typeof target.process.hrtime === "function") {
hijackMethod(target.process, clock.methods[i], clock);
for (i = 0, l = clock.methods.length; i < l; i++) {
if (clock.methods[i] === "hrtime") {
if (target.process && typeof target.process.hrtime === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else if (clock.methods[i] === "nextTick") {
if (target.process && typeof target.process.nextTick === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else {
if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
var intervalId = target[clock.methods[i]](
intervalTick,
config.advanceTimeDelta);
clock.attachedInterval = intervalId;
}
hijackMethod(target, clock.methods[i], clock);
}
} else if (clock.methods[i] === "nextTick") {
if (target.process && typeof target.process.nextTick === "function") {
hijackMethod(target.process, clock.methods[i], clock);
}
} else {
if (clock.methods[i] === "setInterval" && config.shouldAdvanceTime === true) {
var intervalTick = doIntervalTick.bind(null, clock, config.advanceTimeDelta);
var intervalId = target[clock.methods[i]](
intervalTick,
config.advanceTimeDelta);
clock.attachedInterval = intervalId;
}
hijackMethod(target, clock.methods[i], clock);
}
return clock;
}
return clock;
};
return {
timers: timers,
createClock: createClock,
install: install,
withGlobal: withGlobal
};
}
var defaultImplementation = withGlobal(global || window);
exports.timers = defaultImplementation.timers;
exports.createClock = defaultImplementation.createClock;
exports.install = defaultImplementation.install;
exports.withGlobal = withGlobal;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc