task.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. var global = require('../internals/global');
  2. var fails = require('../internals/fails');
  3. var bind = require('../internals/function-bind-context');
  4. var html = require('../internals/html');
  5. var createElement = require('../internals/document-create-element');
  6. var IS_IOS = require('../internals/engine-is-ios');
  7. var IS_NODE = require('../internals/engine-is-node');
  8. var location = global.location;
  9. var set = global.setImmediate;
  10. var clear = global.clearImmediate;
  11. var process = global.process;
  12. var MessageChannel = global.MessageChannel;
  13. var Dispatch = global.Dispatch;
  14. var counter = 0;
  15. var queue = {};
  16. var ONREADYSTATECHANGE = 'onreadystatechange';
  17. var defer, channel, port;
  18. var run = function (id) {
  19. // eslint-disable-next-line no-prototype-builtins -- safe
  20. if (queue.hasOwnProperty(id)) {
  21. var fn = queue[id];
  22. delete queue[id];
  23. fn();
  24. }
  25. };
  26. var runner = function (id) {
  27. return function () {
  28. run(id);
  29. };
  30. };
  31. var listener = function (event) {
  32. run(event.data);
  33. };
  34. var post = function (id) {
  35. // old engines have not location.origin
  36. global.postMessage(id + '', location.protocol + '//' + location.host);
  37. };
  38. // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
  39. if (!set || !clear) {
  40. set = function setImmediate(fn) {
  41. var args = [];
  42. var i = 1;
  43. while (arguments.length > i) args.push(arguments[i++]);
  44. queue[++counter] = function () {
  45. // eslint-disable-next-line no-new-func -- spec requirement
  46. (typeof fn == 'function' ? fn : Function(fn)).apply(undefined, args);
  47. };
  48. defer(counter);
  49. return counter;
  50. };
  51. clear = function clearImmediate(id) {
  52. delete queue[id];
  53. };
  54. // Node.js 0.8-
  55. if (IS_NODE) {
  56. defer = function (id) {
  57. process.nextTick(runner(id));
  58. };
  59. // Sphere (JS game engine) Dispatch API
  60. } else if (Dispatch && Dispatch.now) {
  61. defer = function (id) {
  62. Dispatch.now(runner(id));
  63. };
  64. // Browsers with MessageChannel, includes WebWorkers
  65. // except iOS - https://github.com/zloirock/core-js/issues/624
  66. } else if (MessageChannel && !IS_IOS) {
  67. channel = new MessageChannel();
  68. port = channel.port2;
  69. channel.port1.onmessage = listener;
  70. defer = bind(port.postMessage, port, 1);
  71. // Browsers with postMessage, skip WebWorkers
  72. // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
  73. } else if (
  74. global.addEventListener &&
  75. typeof postMessage == 'function' &&
  76. !global.importScripts &&
  77. location && location.protocol !== 'file:' &&
  78. !fails(post)
  79. ) {
  80. defer = post;
  81. global.addEventListener('message', listener, false);
  82. // IE8-
  83. } else if (ONREADYSTATECHANGE in createElement('script')) {
  84. defer = function (id) {
  85. html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
  86. html.removeChild(this);
  87. run(id);
  88. };
  89. };
  90. // Rest old browsers
  91. } else {
  92. defer = function (id) {
  93. setTimeout(runner(id), 0);
  94. };
  95. }
  96. }
  97. module.exports = {
  98. set: set,
  99. clear: clear
  100. };