123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. 'use strict';
  2. var callable, byObserver;
  3. callable = function (fn) {
  4. if (typeof fn !== 'function') throw new TypeError(fn + " is not a function");
  5. return fn;
  6. };
  7. byObserver = function (Observer) {
  8. var node = document.createTextNode(''), queue, currentQueue, i = 0;
  9. new Observer(function () {
  10. var callback;
  11. if (!queue) {
  12. if (!currentQueue) return;
  13. queue = currentQueue;
  14. } else if (currentQueue) {
  15. queue = currentQueue.concat(queue);
  16. }
  17. currentQueue = queue;
  18. queue = null;
  19. if (typeof currentQueue === 'function') {
  20. callback = currentQueue;
  21. currentQueue = null;
  22. callback();
  23. return;
  24. }
  25. node.data = (i = ++i % 2); // Invoke other batch, to handle leftover callbacks in case of crash
  26. while (currentQueue) {
  27. callback = currentQueue.shift();
  28. if (!currentQueue.length) currentQueue = null;
  29. callback();
  30. }
  31. }).observe(node, { characterData: true });
  32. return function (fn) {
  33. callable(fn);
  34. if (queue) {
  35. if (typeof queue === 'function') queue = [queue, fn];
  36. else queue.push(fn);
  37. return;
  38. }
  39. queue = fn;
  40. node.data = (i = ++i % 2);
  41. };
  42. };
  43. module.exports = (function () {
  44. // Node.js
  45. if ((typeof process === 'object') && process && (typeof process.nextTick === 'function')) {
  46. return process.nextTick;
  47. }
  48. // MutationObserver
  49. if ((typeof document === 'object') && document) {
  50. if (typeof MutationObserver === 'function') return byObserver(MutationObserver);
  51. if (typeof WebKitMutationObserver === 'function') return byObserver(WebKitMutationObserver);
  52. }
  53. // W3C Draft
  54. // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
  55. if (typeof setImmediate === 'function') {
  56. return function (cb) { setImmediate(callable(cb)); };
  57. }
  58. // Wide available standard
  59. if ((typeof setTimeout === 'function') || (typeof setTimeout === 'object')) {
  60. return function (cb) { setTimeout(callable(cb), 0); };
  61. }
  62. return null;
  63. }());