| "use strict"; | 
| var firstLineError; | 
| try {throw new Error(); } catch (e) {firstLineError = e;} | 
| var schedule = require("./schedule"); | 
| var Queue = require("./queue"); | 
|   | 
| function Async() { | 
|     this._customScheduler = false; | 
|     this._isTickUsed = false; | 
|     this._lateQueue = new Queue(16); | 
|     this._normalQueue = new Queue(16); | 
|     this._haveDrainedQueues = false; | 
|     var self = this; | 
|     this.drainQueues = function () { | 
|         self._drainQueues(); | 
|     }; | 
|     this._schedule = schedule; | 
| } | 
|   | 
| Async.prototype.setScheduler = function(fn) { | 
|     var prev = this._schedule; | 
|     this._schedule = fn; | 
|     this._customScheduler = true; | 
|     return prev; | 
| }; | 
|   | 
| Async.prototype.hasCustomScheduler = function() { | 
|     return this._customScheduler; | 
| }; | 
|   | 
| Async.prototype.haveItemsQueued = function () { | 
|     return this._isTickUsed || this._haveDrainedQueues; | 
| }; | 
|   | 
|   | 
| Async.prototype.fatalError = function(e, isNode) { | 
|     if (isNode) { | 
|         process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) + | 
|             "\n"); | 
|         process.exit(2); | 
|     } else { | 
|         this.throwLater(e); | 
|     } | 
| }; | 
|   | 
| Async.prototype.throwLater = function(fn, arg) { | 
|     if (arguments.length === 1) { | 
|         arg = fn; | 
|         fn = function () { throw arg; }; | 
|     } | 
|     if (typeof setTimeout !== "undefined") { | 
|         setTimeout(function() { | 
|             fn(arg); | 
|         }, 0); | 
|     } else try { | 
|         this._schedule(function() { | 
|             fn(arg); | 
|         }); | 
|     } catch (e) { | 
|         throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/MqrFmX\u000a"); | 
|     } | 
| }; | 
|   | 
| function AsyncInvokeLater(fn, receiver, arg) { | 
|     this._lateQueue.push(fn, receiver, arg); | 
|     this._queueTick(); | 
| } | 
|   | 
| function AsyncInvoke(fn, receiver, arg) { | 
|     this._normalQueue.push(fn, receiver, arg); | 
|     this._queueTick(); | 
| } | 
|   | 
| function AsyncSettlePromises(promise) { | 
|     this._normalQueue._pushOne(promise); | 
|     this._queueTick(); | 
| } | 
|   | 
| Async.prototype.invokeLater = AsyncInvokeLater; | 
| Async.prototype.invoke = AsyncInvoke; | 
| Async.prototype.settlePromises = AsyncSettlePromises; | 
|   | 
|   | 
| function _drainQueue(queue) { | 
|     while (queue.length() > 0) { | 
|         _drainQueueStep(queue); | 
|     } | 
| } | 
|   | 
| function _drainQueueStep(queue) { | 
|     var fn = queue.shift(); | 
|     if (typeof fn !== "function") { | 
|         fn._settlePromises(); | 
|     } else { | 
|         var receiver = queue.shift(); | 
|         var arg = queue.shift(); | 
|         fn.call(receiver, arg); | 
|     } | 
| } | 
|   | 
| Async.prototype._drainQueues = function () { | 
|     _drainQueue(this._normalQueue); | 
|     this._reset(); | 
|     this._haveDrainedQueues = true; | 
|     _drainQueue(this._lateQueue); | 
| }; | 
|   | 
| Async.prototype._queueTick = function () { | 
|     if (!this._isTickUsed) { | 
|         this._isTickUsed = true; | 
|         this._schedule(this.drainQueues); | 
|     } | 
| }; | 
|   | 
| Async.prototype._reset = function () { | 
|     this._isTickUsed = false; | 
| }; | 
|   | 
| module.exports = Async; | 
| module.exports.firstLineError = firstLineError; |