Advertisement
aarock1234

Untitled

Oct 11th, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.26 KB | None | 0 0
  1. 'use strict';
  2.  
  3. const { FunctionPrototype } = primordials;
  4.  
  5. const {
  6. // For easy access to the nextTick state in the C++ land,
  7. // and to avoid unnecessary calls into JS land.
  8. tickInfo,
  9. // Used to run V8's micro task queue.
  10. runMicrotasks,
  11. setTickCallback,
  12. enqueueMicrotask,
  13. triggerFatalException
  14. } = internalBinding('task_queue');
  15.  
  16. const {
  17. setHasRejectionToWarn,
  18. hasRejectionToWarn,
  19. listenForRejections,
  20. processPromiseRejections
  21. } = require('internal/process/promises');
  22.  
  23. const {
  24. getDefaultTriggerAsyncId,
  25. newAsyncId,
  26. initHooksExist,
  27. destroyHooksExist,
  28. emitInit,
  29. emitBefore,
  30. emitAfter,
  31. emitDestroy,
  32. symbols: { async_id_symbol, trigger_async_id_symbol }
  33. } = require('internal/async_hooks');
  34. const {
  35. ERR_INVALID_CALLBACK,
  36. ERR_INVALID_ARG_TYPE
  37. } = require('internal/errors').codes;
  38. const FixedQueue = require('internal/fixed_queue');
  39.  
  40. // *Must* match Environment::TickInfo::Fields in src/env.h.
  41. const kHasTickScheduled = 0;
  42.  
  43. function hasTickScheduled() {
  44. return tickInfo[kHasTickScheduled] === 1;
  45. }
  46. function setHasTickScheduled(value) {
  47. tickInfo[kHasTickScheduled] = value ? 1 : 0;
  48. }
  49.  
  50. const queue = new FixedQueue();
  51.  
  52. // Should be in sync with RunNextTicksNative in node_task_queue.cc
  53. function runNextTicks() {
  54. if (!hasTickScheduled() && !hasRejectionToWarn())
  55. runMicrotasks();
  56. if (!hasTickScheduled() && !hasRejectionToWarn())
  57. return;
  58.  
  59. processTicksAndRejections();
  60. }
  61.  
  62. function processTicksAndRejections() {
  63. let tock;
  64. do {
  65. while (tock = queue.shift()) {
  66. const asyncId = tock[async_id_symbol];
  67. emitBefore(asyncId, tock[trigger_async_id_symbol]);
  68. // emitDestroy() places the async_id_symbol into an asynchronous queue
  69. // that calls the destroy callback in the future. It's called before
  70. // calling tock.callback so destroy will be called even if the callback
  71. // throws an exception that is handled by 'uncaughtException' or a
  72. // domain.
  73. // TODO(trevnorris): This is a bit of a hack. It relies on the fact
  74. // that nextTick() doesn't allow the event loop to proceed, but if
  75. // any async hooks are enabled during the callback's execution then
  76. // this tock's after hook will be called, but not its destroy hook.
  77. if (destroyHooksExist())
  78. emitDestroy(asyncId);
  79.  
  80. const callback = tock.callback;
  81. if (tock.args === undefined)
  82. callback();
  83. else
  84. callback(...tock.args);
  85.  
  86. emitAfter(asyncId);
  87. }
  88. setHasTickScheduled(false);
  89. runMicrotasks();
  90. } while (!queue.isEmpty() || processPromiseRejections());
  91. setHasRejectionToWarn(false);
  92. }
  93.  
  94. class TickObject {
  95. constructor(callback, args, triggerAsyncId) {
  96. this.callback = callback;
  97. this.args = args;
  98.  
  99. const asyncId = newAsyncId();
  100. this[async_id_symbol] = asyncId;
  101. this[trigger_async_id_symbol] = triggerAsyncId;
  102.  
  103. if (initHooksExist()) {
  104. emitInit(asyncId,
  105. 'TickObject',
  106. triggerAsyncId,
  107. this);
  108. }
  109. }
  110. }
  111.  
  112. // `nextTick()` will not enqueue any callback when the process is about to
  113. // exit since the callback would not have a chance to be executed.
  114. function nextTick(callback) {
  115. if (typeof callback !== 'function')
  116. throw new ERR_INVALID_CALLBACK(callback);
  117.  
  118. if (process._exiting)
  119. return;
  120.  
  121. var args;
  122. switch (arguments.length) {
  123. case 1: break;
  124. case 2: args = [arguments[1]]; break;
  125. case 3: args = [arguments[1], arguments[2]]; break;
  126. case 4: args = [arguments[1], arguments[2], arguments[3]]; break;
  127. default:
  128. args = new Array(arguments.length - 1);
  129. for (var i = 1; i < arguments.length; i++)
  130. args[i - 1] = arguments[i];
  131. }
  132.  
  133. if (queue.isEmpty())
  134. setHasTickScheduled(true);
  135. queue.push(new TickObject(callback, args, getDefaultTriggerAsyncId()));
  136. }
  137.  
  138. let AsyncResource;
  139. function createMicrotaskResource() {
  140. // Lazy load the async_hooks module
  141. if (!AsyncResource) {
  142. AsyncResource = require('async_hooks').AsyncResource;
  143. }
  144. return new AsyncResource('Microtask', {
  145. triggerAsyncId: getDefaultTriggerAsyncId(),
  146. requireManualDestroy: true,
  147. });
  148. }
  149.  
  150. function runMicrotask() {
  151. this.runInAsyncScope(() => {
  152. const callback = this.callback;
  153. try {
  154. callback();
  155. } catch (error) {
  156. // TODO(devsnek): Remove this if
  157. // https://bugs.chromium.org/p/v8/issues/detail?id=8326
  158. // is resolved such that V8 triggers the fatal exception
  159. // handler for microtasks.
  160. triggerFatalException(error, false /* fromPromise */);
  161. } finally {
  162. this.emitDestroy();
  163. }
  164. });
  165. }
  166.  
  167. function queueMicrotask(callback) {
  168. if (typeof callback !== 'function') {
  169. throw new ERR_INVALID_ARG_TYPE('callback', 'function', callback);
  170. }
  171.  
  172. const asyncResource = createMicrotaskResource();
  173. asyncResource.callback = callback;
  174.  
  175. enqueueMicrotask(FunctionPrototype.bind(runMicrotask, asyncResource));
  176. }
  177.  
  178. module.exports = {
  179. setupTaskQueue() {
  180. // Sets the per-isolate promise rejection callback
  181. listenForRejections();
  182. // Sets the callback to be run in every tick.
  183. setTickCallback(processTicksAndRejections);
  184. return {
  185. nextTick,
  186. runNextTicks
  187. };
  188. },
  189. queueMicrotask
  190. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement