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