123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- "use strict";
- var firstLineError;
- try {throw new Error(); } catch (e) {firstLineError = e;}
- var schedule = require("./schedule");
- var Queue = require("./queue");
- var util = require("./util");
-
- function Async() {
- this._customScheduler = false;
- this._isTickUsed = false;
- this._lateQueue = new Queue(16);
- this._normalQueue = new Queue(16);
- this._haveDrainedQueues = false;
- this._trampolineEnabled = true;
- 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.enableTrampoline = function() {
- this._trampolineEnabled = true;
- };
-
- Async.prototype.disableTrampolineIfNecessary = function() {
- if (util.hasDevTools) {
- this._trampolineEnabled = false;
- }
- };
-
- 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();
- }
-
- 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 {
- this._schedule(function() {
- setTimeout(function() {
- fn.call(receiver, arg);
- }, 100);
- });
- }
- };
-
- Async.prototype.invoke = function (fn, receiver, arg) {
- if (this._trampolineEnabled) {
- AsyncInvoke.call(this, fn, receiver, arg);
- } else {
- this._schedule(function() {
- fn.call(receiver, arg);
- });
- }
- };
-
- Async.prototype.settlePromises = function(promise) {
- if (this._trampolineEnabled) {
- AsyncSettlePromises.call(this, promise);
- } else {
- this._schedule(function() {
- promise._settlePromises();
- });
- }
- };
- }
-
- 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._haveDrainedQueues = true;
- 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 = Async;
- module.exports.firstLineError = firstLineError;
|