2f85516cde0f3a0a8fae5a416be99c17c522bd9b
[platform/framework/web/crosswalk-tizen.git] /
1
2 // Use the fastest possible means to execute a task in a future turn
3 // of the event loop.
4
5 // linked list of tasks (single, with head node)
6 var head = {task: void 0, next: null};
7 var tail = head;
8 var flushing = false;
9 var requestFlush = void 0;
10 var isNodeJS = false;
11
12 function flush() {
13     /* jshint loopfunc: true */
14
15     while (head.next) {
16         head = head.next;
17         var task = head.task;
18         head.task = void 0;
19         var domain = head.domain;
20
21         if (domain) {
22             head.domain = void 0;
23             domain.enter();
24         }
25
26         try {
27             task();
28
29         } catch (e) {
30             if (isNodeJS) {
31                 // In node, uncaught exceptions are considered fatal errors.
32                 // Re-throw them synchronously to interrupt flushing!
33
34                 // Ensure continuation if the uncaught exception is suppressed
35                 // listening "uncaughtException" events (as domains does).
36                 // Continue in next event to avoid tick recursion.
37                 if (domain) {
38                     domain.exit();
39                 }
40                 setTimeout(flush, 0);
41                 if (domain) {
42                     domain.enter();
43                 }
44
45                 throw e;
46
47             } else {
48                 // In browsers, uncaught exceptions are not fatal.
49                 // Re-throw them asynchronously to avoid slow-downs.
50                 setTimeout(function() {
51                    throw e;
52                 }, 0);
53             }
54         }
55
56         if (domain) {
57             domain.exit();
58         }
59     }
60
61     flushing = false;
62 }
63
64 if (typeof process !== "undefined" && process.nextTick) {
65     // Node.js before 0.9. Note that some fake-Node environments, like the
66     // Mocha test runner, introduce a `process` global without a `nextTick`.
67     isNodeJS = true;
68
69     requestFlush = function () {
70         process.nextTick(flush);
71     };
72
73 } else if (typeof setImmediate === "function") {
74     // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
75     if (typeof window !== "undefined") {
76         requestFlush = setImmediate.bind(window, flush);
77     } else {
78         requestFlush = function () {
79             setImmediate(flush);
80         };
81     }
82
83 } else if (typeof MessageChannel !== "undefined") {
84     // modern browsers
85     // http://www.nonblocking.io/2011/06/windownexttick.html
86     var channel = new MessageChannel();
87     channel.port1.onmessage = flush;
88     requestFlush = function () {
89         channel.port2.postMessage(0);
90     };
91
92 } else {
93     // old browsers
94     requestFlush = function () {
95         setTimeout(flush, 0);
96     };
97 }
98
99 function asap(task) {
100     tail = tail.next = {
101         task: task,
102         domain: isNodeJS && process.domain,
103         next: null
104     };
105
106     if (!flushing) {
107         flushing = true;
108         requestFlush();
109     }
110 };
111
112 module.exports = asap;
113