| "use strict"; |
| var firstLineError; |
| try {throw new Error(); } catch (e) {firstLineError = e;} |
| var schedule = require("./schedule.js"); |
| var Queue = require("./queue.js"); |
| var util = require("./util.js"); |
| |
| function Async() { |
| this._isTickUsed = false; |
| this._lateQueue = new Queue(16); |
| this._normalQueue = new Queue(16); |
| this._trampolineEnabled = true; |
| var self = this; |
| this.drainQueues = function () { |
| self._drainQueues(); |
| }; |
| this._schedule = |
| schedule.isStatic ? schedule(this.drainQueues) : schedule; |
| } |
| |
| Async.prototype.disableTrampolineIfNecessary = function() { |
| if (util.hasDevTools) { |
| this._trampolineEnabled = false; |
| } |
| }; |
| |
| Async.prototype.enableTrampoline = function() { |
| if (!this._trampolineEnabled) { |
| this._trampolineEnabled = true; |
| this._schedule = function(fn) { |
| setTimeout(fn, 0); |
| }; |
| } |
| }; |
| |
| Async.prototype.haveItemsQueued = function () { |
| return this._normalQueue.length() > 0; |
| }; |
| |
| Async.prototype.throwLater = function(fn, arg) { |
| if (arguments.length === 1) { |
| arg = fn; |
| fn = function () { throw arg; }; |
| } |
| var domain = this._getDomain(); |
| if (domain !== undefined) fn = domain.bind(fn); |
| 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/m3OTXk\u000a"); |
| } |
| }; |
| |
| Async.prototype._getDomain = function() {}; |
| |
| if (!false) { |
| if (util.isNode) { |
| var EventsModule = require("events"); |
| |
| var domainGetter = function() { |
| var domain = process.domain; |
| if (domain === null) return undefined; |
| return domain; |
| }; |
| |
| if (EventsModule.usingDomains) { |
| Async.prototype._getDomain = domainGetter; |
| } else { |
| var descriptor = |
| Object.getOwnPropertyDescriptor(EventsModule, "usingDomains"); |
| |
| if (descriptor) { |
| if (!descriptor.configurable) { |
| process.on("domainsActivated", function() { |
| Async.prototype._getDomain = domainGetter; |
| }); |
| } else { |
| var usingDomains = false; |
| Object.defineProperty(EventsModule, "usingDomains", { |
| configurable: false, |
| enumerable: true, |
| get: function() { |
| return usingDomains; |
| }, |
| set: function(value) { |
| if (usingDomains || !value) return; |
| usingDomains = true; |
| Async.prototype._getDomain = domainGetter; |
| util.toFastProperties(process); |
| process.emit("domainsActivated"); |
| } |
| }); |
| } |
| } |
| } |
| } |
| } |
| |
| function AsyncInvokeLater(fn, receiver, arg) { |
| var domain = this._getDomain(); |
| if (domain !== undefined) fn = domain.bind(fn); |
| this._lateQueue.push(fn, receiver, arg); |
| this._queueTick(); |
| } |
| |
| function AsyncInvoke(fn, receiver, arg) { |
| var domain = this._getDomain(); |
| if (domain !== undefined) fn = domain.bind(fn); |
| this._normalQueue.push(fn, receiver, arg); |
| this._queueTick(); |
| } |
| |
| function AsyncSettlePromises(promise) { |
| var domain = this._getDomain(); |
| if (domain !== undefined) { |
| var fn = domain.bind(promise._settlePromises); |
| this._normalQueue.push(fn, promise, undefined); |
| } else { |
| this._normalQueue._pushOne(promise); |
| } |
| this._queueTick(); |
| } |
| |
| if (!util.hasDevTools) { |
| Async.prototype.invokeLater = AsyncInvokeLater; |
| Async.prototype.invoke = AsyncInvoke; |
| Async.prototype.settlePromises = AsyncSettlePromises; |
| } else { |
| Async.prototype.invokeLater = function (fn, receiver, arg) { |
| if (this._trampolineEnabled) { |
| AsyncInvokeLater.call(this, fn, receiver, arg); |
| } else { |
| setTimeout(function() { |
| fn.call(receiver, arg); |
| }, 100); |
| } |
| }; |
| |
| Async.prototype.invoke = function (fn, receiver, arg) { |
| if (this._trampolineEnabled) { |
| AsyncInvoke.call(this, fn, receiver, arg); |
| } else { |
| setTimeout(function() { |
| fn.call(receiver, arg); |
| }, 0); |
| } |
| }; |
| |
| Async.prototype.settlePromises = function(promise) { |
| if (this._trampolineEnabled) { |
| AsyncSettlePromises.call(this, promise); |
| } else { |
| setTimeout(function() { |
| promise._settlePromises(); |
| }, 0); |
| } |
| }; |
| } |
| |
| Async.prototype.invokeFirst = function (fn, receiver, arg) { |
| var domain = this._getDomain(); |
| if (domain !== undefined) fn = domain.bind(fn); |
| this._normalQueue.unshift(fn, receiver, arg); |
| this._queueTick(); |
| }; |
| |
| Async.prototype._drainQueue = function(queue) { |
| while (queue.length() > 0) { |
| var fn = queue.shift(); |
| if (typeof fn !== "function") { |
| fn._settlePromises(); |
| continue; |
| } |
| var receiver = queue.shift(); |
| var arg = queue.shift(); |
| fn.call(receiver, arg); |
| } |
| }; |
| |
| Async.prototype._drainQueues = function () { |
| this._drainQueue(this._normalQueue); |
| this._reset(); |
| this._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 = new Async(); |
| module.exports.firstLineError = firstLineError; |