-
Notifications
You must be signed in to change notification settings - Fork 55
/
nextTick.js
64 lines (60 loc) · 1.91 KB
/
nextTick.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//overall structure based on when
//https://github.com/cujojs/when/blob/master/when.js#L805-L852
let nextTick;
const MutationObserver = global.MutationObserver || global.WebKitMutationObserver;
/*if (typeof setImmediate === 'function') {
nextTick = setImmediate.bind(global,drainQueue);
}else */if(MutationObserver){
//based on RSVP
//https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/async.js
let observer = new MutationObserver(drainQueue);
const element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
addEventListener('unload', function () {
observer.disconnect();
observer = null;
}, false);
nextTick = function () {
element.setAttribute('drainQueue', 'drainQueue');
};
}else{
const codeWord = 'com.catiline.setImmediate' + Math.random();
addEventListener('message', function (event) {
// This will catch all incoming messages (even from other windows!), so we need to try reasonably hard to
// avoid letting anyone else trick us into firing off. We test the origin is still this window, and that a
// (randomly generated) unpredictable identifying prefix is present.
if (event.source === window && event.data === codeWord) {
drainQueue();
}
}, false);
nextTick = function() {
postMessage(codeWord, '*');
};
}
let mainQueue = [];
/**
* Enqueue a task. If the queue is not currently scheduled to be
* drained, schedule it.
* @param {function} task
*/
catiline.nextTick = function(task) {
if (mainQueue.push(task) === 1) {
nextTick();
}
};
/**
* Drain the handler queue entirely, being careful to allow the
* queue to be extended while it is being processed, and to continue
* processing until it is truly empty.
*/
function drainQueue() {
let i = 0;
let task;
const innerQueue = mainQueue;
mainQueue = [];
/*jslint boss: true */
while (task = innerQueue[i++]) {
task();
}
}