UNPKG

zurvan

Version:

A library for simulating time in Node.js

140 lines (112 loc) 3.66 kB
'use strict'; var FieldOverrider = require('./utils/FieldOverrider'); var UIDManager = require('./utils/UIDManager'); var SequenceGenerator = require('./utils/SequenceGenerator'); var TypeChecks = require('./utils/TypeChecks'); var assert = require('assert'); function ImmediateInterceptor() { this.awaitingImmediates = { size: 0 }; this.uidManager = new UIDManager(); } ImmediateInterceptor.prototype.intercept = function(config) { this.config = config; this.setImmediates = new FieldOverrider( global, 'setImmediate', this.addImmediate.bind(this) ); this.clearImmediates = new FieldOverrider( global, 'clearImmediate', this.removeImmediate.bind(this) ); if (this.config.fakeNodeDedicatedTimers) { var timers = require('timers'); this.nodeSetImmediates = new FieldOverrider( timers, 'setImmediate', setImmediate.bind(global) ); this.nodeClearImmediates = new FieldOverrider( timers, 'clearImmediate', setImmediate.bind(global) ); } this.enqueue = this.setImmediates.oldValue; this.dequeue = this.clearImmediates.oldValue; this.uidManager.setUp(this.config.throwOnInvalidClearTimer, 'immediate'); if (TypeChecks.isFunction(this.config.bluebird)) { this.previousBluebirdScheduler = this.config.bluebird.setScheduler( this.endOfQueueScheduler() ); } else if (this.config.bluebird !== undefined) { throw new Error( 'if given, bluebird configuration parameter to zurvan must be a function representing bluebird library' ); } }; ImmediateInterceptor.prototype.release = function(forced) { var that = this; var leftImmediates = this.awaitingImmediates; this.awaitingImmediates = { size: 0 }; this.setImmediates.restore(); this.clearImmediates.restore(); if (this.config.fakeNodeDedicatedTimers) { this.nodeSetImmediates.restore(); this.nodeClearImmediates.restore(); } this.uidManager.clear(); if (this.previousBluebirdScheduler) { this.config.bluebird.setScheduler(this.previousBluebirdScheduler); this.previousBluebirdScheduler = undefined; } this.enqueue = undefined; this.dequeue = undefined; return leftImmediates; }; ImmediateInterceptor.prototype.startDroppingImmediates = function() { this.dropImmediates = true; }; ImmediateInterceptor.prototype.addImmediate = function(callback) { var uid = this.uidManager.getUid(); if (this.dropImmediates) { this.awaitingImmediates[uid.uid] = new Error().stack; ++this.awaitingImmediates.size; return uid; } var that = this; var args = [].splice.call(arguments, 1); this.awaitingImmediates[uid.uid] = this.enqueue(function() { that.remove(uid); callback.apply(undefined, args); }); ++this.awaitingImmediates.size; return uid; }; ImmediateInterceptor.prototype.remove = function(uid) { var toDequeue; if (this.awaitingImmediates[uid.uid] !== undefined) { toDequeue = this.awaitingImmediates[uid.uid]; delete this.awaitingImmediates[uid.uid]; --this.awaitingImmediates.size; } assert(this.awaitingImmediates.size >= 0); return toDequeue; }; ImmediateInterceptor.prototype.removeImmediate = function(uid) { if (!this.uidManager.isAcceptableUid(uid)) { return; } return this.dequeue(this.remove(uid)); }; ImmediateInterceptor.prototype.areAwaiting = function() { return this.awaitingImmediates.size > 0; }; ImmediateInterceptor.prototype.endOfQueueScheduler = function() { return setImmediate.bind(global); }; ImmediateInterceptor.prototype.internalScheduler = function() { return this.enqueue; }; module.exports = ImmediateInterceptor;