diff --git a/src/lolex-src.js b/src/lolex-src.js index 0791af87..5385abed 100644 --- a/src/lolex-src.js +++ b/src/lolex-src.js @@ -33,6 +33,7 @@ function withGlobal(_global) { var nextTickPresent = (_global.process && typeof _global.process.nextTick === "function"); var performancePresent = (_global.performance && typeof _global.performance.now === "function"); var hasPerformancePrototype = (_global.Performance && (typeof _global.Performance).match(/^(function|object)$/)); + var queueMicrotaskPresent = (typeof _global.queueMicrotask === "function"); var requestAnimationFramePresent = ( _global.requestAnimationFrame && typeof _global.requestAnimationFrame === "function" ); @@ -487,6 +488,9 @@ function withGlobal(_global) { if (requestAnimationFramePresent) { timers.requestAnimationFrame = _global.requestAnimationFrame; } + if (queueMicrotaskPresent) { + timers.queueMicrotask = _global.queueMicrotask; + } if (cancelAnimationFramePresent) { timers.cancelAnimationFrame = _global.cancelAnimationFrame; @@ -574,6 +578,9 @@ function withGlobal(_global) { args: Array.prototype.slice.call(arguments, 1) }); }; + clock.queueMicrotask = function queueMicrotask(func) { + return clock.nextTick(func); // explicitly drop additional arguments + }; clock.setInterval = function setInterval(func, timeout) { timeout = parseInt(timeout, 10); return addTimer(clock, { @@ -650,11 +657,11 @@ function withGlobal(_global) { clock.duringTick = true; - // perform process.nextTick()s + // perform microtasks oldNow = clock.now; runJobs(clock); if (oldNow !== clock.now) { - // compensate for any setSystemTime() call during process.nextTick() callback + // compensate for any setSystemTime() call during microtask callback tickFrom += clock.now - oldNow; tickTo += clock.now - oldNow; } diff --git a/test/lolex-test.js b/test/lolex-test.js index 44c950cb..a877de99 100644 --- a/test/lolex-test.js +++ b/test/lolex-test.js @@ -19,6 +19,7 @@ var GlobalDate = Date; var NOOP = function NOOP() { return undefined; }; var nextTickPresent = (global.process && typeof global.process.nextTick === "function"); +var queueMicrotaskPresent = (typeof global.queueMicrotask === "function"); var hrtimePresent = (global.process && typeof global.process.hrtime === "function"); var performanceNowPresent = (global.performance && typeof global.performance.now === "function"); var performanceMarkPresent = (global.performance && typeof global.performance.mark === "function"); @@ -2518,8 +2519,46 @@ describe("lolex", function () { }); }); - describe("microtask semantics", function () { + describe("queueMicrotask semantics", function () { + // adapted from Node's tests + var clock, called; + before( function () { + if (!queueMicrotaskPresent) { this.skip(); } + }); + beforeEach( function () { + clock = lolex.createClock(); + called = false; + }); + it("runs without timers", function () { + clock.queueMicrotask(function () { + called = true; + }); + clock.runAll(); + assert(called); + }); + it("runs when runMicrotasks is called on the clock", function () { + clock.queueMicrotask(function () { + called = true; + }); + clock.runMicrotasks(); + assert(called); + }); + it("runs with timers and before them", function () { + var last = ""; + clock.runMicrotasks(function () { + called = true; + last = "tick"; + }); + clock.setTimeout(function () { + last = "timeout"; + }); + clock.runAll(); + assert(called); + assert.equals(last, "timeout"); + }); + }); + describe("nextTick semantics", function () { before( function () { if (!nextTickPresent) { this.skip(); } });