1var global = require('./_global');
2var macrotask = require('./_task').set;
3var Observer = global.MutationObserver || global.WebKitMutationObserver;
4var process = global.process;
5var Promise = global.Promise;
6var isNode = require('./_cof')(process) == 'process';
7
8module.exports = function () {
9  var head, last, notify;
10
11  var flush = function () {
12    var parent, fn;
13    if (isNode && (parent = process.domain)) parent.exit();
14    while (head) {
15      fn = head.fn;
16      head = head.next;
17      try {
18        fn();
19      } catch (e) {
20        if (head) notify();
21        else last = undefined;
22        throw e;
23      }
24    } last = undefined;
25    if (parent) parent.enter();
26  };
27
28  // Node.js
29  if (isNode) {
30    notify = function () {
31      process.nextTick(flush);
32    };
33  // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339
34  } else if (Observer && !(global.navigator && global.navigator.standalone)) {
35    var toggle = true;
36    var node = document.createTextNode('');
37    new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
38    notify = function () {
39      node.data = toggle = !toggle;
40    };
41  // environments with maybe non-completely correct, but existent Promise
42  } else if (Promise && Promise.resolve) {
43    // Promise.resolve without an argument throws an error in LG WebOS 2
44    var promise = Promise.resolve(undefined);
45    notify = function () {
46      promise.then(flush);
47    };
48  // for other environments - macrotask based on:
49  // - setImmediate
50  // - MessageChannel
51  // - window.postMessag
52  // - onreadystatechange
53  // - setTimeout
54  } else {
55    notify = function () {
56      // strange IE + webpack dev server bug - use .call(global)
57      macrotask.call(global, flush);
58    };
59  }
60
61  return function (fn) {
62    var task = { fn: fn, next: undefined };
63    if (last) last.next = task;
64    if (!head) {
65      head = task;
66      notify();
67    } last = task;
68  };
69};
70