microtask.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. var global = require('../internals/global');
  2. var getOwnPropertyDescriptor = require('../internals/object-get-own-property-descriptor').f;
  3. var classof = require('../internals/classof-raw');
  4. var macrotask = require('../internals/task').set;
  5. var IS_IOS = require('../internals/engine-is-ios');
  6. var MutationObserver = global.MutationObserver || global.WebKitMutationObserver;
  7. var process = global.process;
  8. var Promise = global.Promise;
  9. var IS_NODE = classof(process) == 'process';
  10. // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
  11. var queueMicrotaskDescriptor = getOwnPropertyDescriptor(global, 'queueMicrotask');
  12. var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
  13. var flush, head, last, notify, toggle, node, promise, then;
  14. // modern engines have queueMicrotask method
  15. if (!queueMicrotask) {
  16. flush = function () {
  17. var parent, fn;
  18. if (IS_NODE && (parent = process.domain)) parent.exit();
  19. while (head) {
  20. fn = head.fn;
  21. head = head.next;
  22. try {
  23. fn();
  24. } catch (error) {
  25. if (head) notify();
  26. else last = undefined;
  27. throw error;
  28. }
  29. } last = undefined;
  30. if (parent) parent.enter();
  31. };
  32. // Node.js
  33. if (IS_NODE) {
  34. notify = function () {
  35. process.nextTick(flush);
  36. };
  37. // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
  38. } else if (MutationObserver && !IS_IOS) {
  39. toggle = true;
  40. node = document.createTextNode('');
  41. new MutationObserver(flush).observe(node, { characterData: true });
  42. notify = function () {
  43. node.data = toggle = !toggle;
  44. };
  45. // environments with maybe non-completely correct, but existent Promise
  46. } else if (Promise && Promise.resolve) {
  47. // Promise.resolve without an argument throws an error in LG WebOS 2
  48. promise = Promise.resolve(undefined);
  49. then = promise.then;
  50. notify = function () {
  51. then.call(promise, flush);
  52. };
  53. // for other environments - macrotask based on:
  54. // - setImmediate
  55. // - MessageChannel
  56. // - window.postMessag
  57. // - onreadystatechange
  58. // - setTimeout
  59. } else {
  60. notify = function () {
  61. // strange IE + webpack dev server bug - use .call(global)
  62. macrotask.call(global, flush);
  63. };
  64. }
  65. }
  66. module.exports = queueMicrotask || function (fn) {
  67. var task = { fn: fn, next: undefined };
  68. if (last) last.next = task;
  69. if (!head) {
  70. head = task;
  71. notify();
  72. } last = task;
  73. };