microtask.js 2.7 KB

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