From 7c25ae6c4a0720a2f699bf0b49b1b9d42727ec79 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Tue, 26 Jul 2016 16:53:04 +0200 Subject: [PATCH 1/2] Prepare for 1.5.1 release --- AUTHORS | 11 +-- History.md | 10 ++- RELEASE.md | 15 +++- lolex.js | 198 ++++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 177 insertions(+), 57 deletions(-) diff --git a/AUTHORS b/AUTHORS index d33b0645..52497859 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,14 +1,15 @@ Christian Johansen -Morgan Roderick Carl-Erik Kopseng -Morgan Roderick +Morgan Roderick Maximilian Antoni Mark Wubben -Duncan Beevers Soutaro Matsumoto +Duncan Beevers Rogier Schouten Karl O'Keeffe -Rogier Schouten +Thibault Hild +Curtis M. Humphrey, Ph.D +Mark Banner Simen Bekkhus Sylvain Fraïssé -Christian Johansen +Andy Edwards diff --git a/History.md b/History.md index 449e42e1..e3464a8b 100644 --- a/History.md +++ b/History.md @@ -1,8 +1,12 @@ - -n.n.n / .... +1.5.1 / 2016-07-26 ================== - * Fix up some BitHound warnings + * Fix setInterval() behavior with string times + * Incorporate test from PR #65 + * Fix issue #59: context object required 'process' + * fixed a case where runAll was called and there are no timers (#70) + * Correct the clear{Interval|Timeout|Immediate} error message when calling `set*` for a different type of timer. + * Lots of minor changes to tooling and the build process v1.5.0 / 2016-05-18 =================== diff --git a/RELEASE.md b/RELEASE.md index 12101e4e..acb28ad6 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,14 +12,25 @@ Compile interesting highlights from [`git changelog`](https://github.com/tj/git- git authors --list > AUTHORS -## Create a new version +## Build a new bundle and commit changed files + + npm run bundle + git add lolex.js AUTHORS History.md + git commit -m "Prepare for new release" + +## Create a new PR + The `master` branch is protected. + You can merge it yourself. -Update package.json and create a new tag. +## Create a new version ``` $ npm version x.y.z ``` +Updates package.json and creates a new tag. + + ## Push new commits and tags ``` git push && git push --tags diff --git a/lolex.js b/lolex.js index 0d29f68e..b49929af 100644 --- a/lolex.js +++ b/lolex.js @@ -1,4 +1,4 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(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= 0 ? Math.floor(n) : Math.ceil(n)); + } + + /** + * % operator that also works for negative numbers + */ + function fixedModulo(n, m) { + return ((n % m) + m) % m; + } + /** * Used to grok the `now` parameter to createClock. */ @@ -130,22 +142,22 @@ // 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); + 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); } } @@ -179,6 +191,7 @@ } + /* eslint consistent-return: "off" */ function compareTimers(a, b) { // Sort first by absolute timing if (a.callAt < b.callAt) { @@ -250,6 +263,22 @@ return timer; } + function lastTimer(clock) { + var timers = clock.timers, + timer = null, + id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === -1) { + timer = timers[id]; + } + } + } + + return timer; + } + function callTimer(clock, timer) { var exception; @@ -263,6 +292,7 @@ if (typeof timer.func === "function") { timer.func.apply(null, timer.args); } else { + /* eslint no-eval: "off" */ eval(timer.func); } } catch (e) { @@ -284,11 +314,11 @@ function timerType(timer) { if (timer.immediate) { return "Immediate"; - } else if (typeof timer.interval !== "undefined") { + } + if (timer.interval !== undefined) { return "Interval"; - } else { - return "Timeout"; } + return "Timeout"; } function clearTimer(clock, timerId, ttype) { @@ -314,8 +344,9 @@ if (timerType(timer) === ttype) { delete clock.timers[timerId]; } else { - throw new Error("Cannot clear timer: timer created with set" + ttype + "() but cleared with clear" + timerType(timer) + "()"); - } + throw new Error("Cannot clear timer: timer created with set" + timerType(timer) + + "() but cleared with clear" + ttype + "()"); + } } } @@ -323,16 +354,20 @@ var method, i, l; + var installedHrTime = "_hrtime"; for (i = 0, l = clock.methods.length; i < l; i++) { method = clock.methods[i]; - - if (target[method].hadOwnProperty) { - target[method] = clock["_" + method]; + if (method === "hrtime" && target.process) { + target.process.hrtime = clock[installedHrTime]; } else { - try { - delete target[method]; - } catch (ignore) {} + if (target[method] && target[method].hadOwnProperty) { + target[method] = clock["_" + method]; + } else { + try { + delete target[method]; + } catch (ignore) { /* eslint empty-block: "off" */ } + } } } @@ -374,6 +409,10 @@ Date: Date }; + if (hrtimePresent) { + timers.hrtime = global.process.hrtime; + } + var keys = Object.keys || function (obj) { var ks = [], key; @@ -389,11 +428,15 @@ exports.timers = timers; - function createClock(now) { + function createClock(now, loopLimit) { + loopLimit = loopLimit || 1000; + var clock = { now: getEpoch(now), + hrNow: 0, timeouts: {}, - Date: createDate() + Date: createDate(), + loopLimit: loopLimit }; clock.Date.clock = clock; @@ -443,10 +486,16 @@ clock.duringTick = true; + function updateHrTime(newNow) { + clock.hrNow += (newNow - clock.now); + } + var firstException; while (timer && tickFrom <= tickTo) { if (clock.timers[timer.id]) { - tickFrom = clock.now = timer.callAt; + updateHrTime(timer.callAt); + tickFrom = timer.callAt; + clock.now = timer.callAt; try { oldNow = clock.now; callTimer(clock, timer); @@ -466,6 +515,7 @@ } clock.duringTick = false; + updateHrTime(tickTo); clock.now = tickTo; if (firstException) { @@ -491,6 +541,33 @@ } }; + clock.runAll = function runAll() { + var numTimers, i; + for (i = 0; i < clock.loopLimit; i++) { + if (!clock.timers) { + return clock.now; + } + + numTimers = Object.keys(clock.timers).length; + if (numTimers === 0) { + return clock.now; + } + + clock.next(); + } + + throw new Error("Aborting after running " + clock.loopLimit + "timers, assuming an infinite loop!"); + }; + + clock.runToLast = function runToLast() { + var timer = lastTimer(clock); + if (!timer) { + return clock.now; + } + + return clock.tick(timer.callAt); + }; + clock.reset = function reset() { clock.timers = {}; }; @@ -499,25 +576,46 @@ // determine time difference var newNow = getEpoch(now); var difference = newNow - clock.now; + var id, timer; // update 'system clock' clock.now = newNow; // update timers and intervals to keep them stable - for (var id in clock.timers) { + for (id in clock.timers) { if (clock.timers.hasOwnProperty(id)) { - var timer = clock.timers[id]; + timer = clock.timers[id]; timer.createdAt += difference; timer.callAt += difference; } } }; + 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 [ + fixedFloor(clock.hrNow / 1000), + fixedModulo(clock.hrNow * 1e6, 1e9) + ]; + }; + } + return clock; } exports.createClock = createClock; - exports.install = function install(target, now, toFake) { + exports.install = function install(target, now, toFake, loopLimit) { var i, l; @@ -531,7 +629,7 @@ target = global; } - var clock = createClock(now); + var clock = createClock(now, loopLimit); clock.uninstall = function () { uninstall(clock, target); @@ -544,7 +642,13 @@ } for (i = 0, l = clock.methods.length; i < l; i++) { - hijackMethod(target, clock.methods[i], clock); + if (clock.methods[i] === "hrtime") { + if (target.process && typeof target.process.hrtime === "function") { + hijackMethod(target.process, clock.methods[i], clock); + } + } else { + hijackMethod(target, clock.methods[i], clock); + } } return clock; From 3823eac06d08d2d6878245effdde57b357e43743 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Tue, 26 Jul 2016 16:55:19 +0200 Subject: [PATCH 2/2] 1.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c9ad6cf0..20c7d546 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "lolex", "description": "Fake JavaScript timers", - "version": "1.5.0", + "version": "1.5.1", "homepage": "http://github.com/sinonjs/lolex", "author": "Christian Johansen", "repository": {