“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;