01044596119410f23741e605fe9bee4c82f96089
[aai/esr-gui.git] /
1 "use strict";
2 var firstLineError;
3 try {throw new Error(); } catch (e) {firstLineError = e;}
4 var schedule = require("./schedule.js");
5 var Queue = require("./queue.js");
6 var util = require("./util.js");
7
8 function Async() {
9     this._isTickUsed = false;
10     this._lateQueue = new Queue(16);
11     this._normalQueue = new Queue(16);
12     this._trampolineEnabled = true;
13     var self = this;
14     this.drainQueues = function () {
15         self._drainQueues();
16     };
17     this._schedule =
18         schedule.isStatic ? schedule(this.drainQueues) : schedule;
19 }
20
21 Async.prototype.disableTrampolineIfNecessary = function() {
22     if (util.hasDevTools) {
23         this._trampolineEnabled = false;
24     }
25 };
26
27 Async.prototype.enableTrampoline = function() {
28     if (!this._trampolineEnabled) {
29         this._trampolineEnabled = true;
30         this._schedule = function(fn) {
31             setTimeout(fn, 0);
32         };
33     }
34 };
35
36 Async.prototype.haveItemsQueued = function () {
37     return this._normalQueue.length() > 0;
38 };
39
40 Async.prototype.throwLater = function(fn, arg) {
41     if (arguments.length === 1) {
42         arg = fn;
43         fn = function () { throw arg; };
44     }
45     if (typeof setTimeout !== "undefined") {
46         setTimeout(function() {
47             fn(arg);
48         }, 0);
49     } else try {
50         this._schedule(function() {
51             fn(arg);
52         });
53     } catch (e) {
54         throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/m3OTXk\u000a");
55     }
56 };
57
58 function AsyncInvokeLater(fn, receiver, arg) {
59     this._lateQueue.push(fn, receiver, arg);
60     this._queueTick();
61 }
62
63 function AsyncInvoke(fn, receiver, arg) {
64     this._normalQueue.push(fn, receiver, arg);
65     this._queueTick();
66 }
67
68 function AsyncSettlePromises(promise) {
69     this._normalQueue._pushOne(promise);
70     this._queueTick();
71 }
72
73 if (!util.hasDevTools) {
74     Async.prototype.invokeLater = AsyncInvokeLater;
75     Async.prototype.invoke = AsyncInvoke;
76     Async.prototype.settlePromises = AsyncSettlePromises;
77 } else {
78     if (schedule.isStatic) {
79         schedule = function(fn) { setTimeout(fn, 0); };
80     }
81     Async.prototype.invokeLater = function (fn, receiver, arg) {
82         if (this._trampolineEnabled) {
83             AsyncInvokeLater.call(this, fn, receiver, arg);
84         } else {
85             this._schedule(function() {
86                 setTimeout(function() {
87                     fn.call(receiver, arg);
88                 }, 100);
89             });
90         }
91     };
92
93     Async.prototype.invoke = function (fn, receiver, arg) {
94         if (this._trampolineEnabled) {
95             AsyncInvoke.call(this, fn, receiver, arg);
96         } else {
97             this._schedule(function() {
98                 fn.call(receiver, arg);
99             });
100         }
101     };
102
103     Async.prototype.settlePromises = function(promise) {
104         if (this._trampolineEnabled) {
105             AsyncSettlePromises.call(this, promise);
106         } else {
107             this._schedule(function() {
108                 promise._settlePromises();
109             });
110         }
111     };
112 }
113
114 Async.prototype.invokeFirst = function (fn, receiver, arg) {
115     this._normalQueue.unshift(fn, receiver, arg);
116     this._queueTick();
117 };
118
119 Async.prototype._drainQueue = function(queue) {
120     while (queue.length() > 0) {
121         var fn = queue.shift();
122         if (typeof fn !== "function") {
123             fn._settlePromises();
124             continue;
125         }
126         var receiver = queue.shift();
127         var arg = queue.shift();
128         fn.call(receiver, arg);
129     }
130 };
131
132 Async.prototype._drainQueues = function () {
133     this._drainQueue(this._normalQueue);
134     this._reset();
135     this._drainQueue(this._lateQueue);
136 };
137
138 Async.prototype._queueTick = function () {
139     if (!this._isTickUsed) {
140         this._isTickUsed = true;
141         this._schedule(this.drainQueues);
142     }
143 };
144
145 Async.prototype._reset = function () {
146     this._isTickUsed = false;
147 };
148
149 module.exports = new Async();
150 module.exports.firstLineError = firstLineError;