process: refactor global.queueMicrotask() · nodejs/node@255de69 (original) (raw)
`@@ -6,7 +6,9 @@ const {
`
6
6
` tickInfo,
`
7
7
`// Used to run V8's micro task queue.
`
8
8
` runMicrotasks,
`
9
``
`-
setTickCallback
`
``
9
`+
setTickCallback,
`
``
10
`+
enqueueMicrotask,
`
``
11
`+
triggerFatalException
`
10
12
`} = internalBinding('task_queue');
`
11
13
``
12
14
`const {
`
`@@ -27,7 +29,10 @@ const {
`
27
29
` emitDestroy,
`
28
30
`symbols: { async_id_symbol, trigger_async_id_symbol }
`
29
31
`} = require('internal/async_hooks');
`
30
``
`-
const { ERR_INVALID_CALLBACK } = require('internal/errors').codes;
`
``
32
`+
const {
`
``
33
`+
ERR_INVALID_CALLBACK,
`
``
34
`+
ERR_INVALID_ARG_TYPE
`
``
35
`+
} = require('internal/errors').codes;
`
31
36
`const FixedQueue = require('internal/fixed_queue');
`
32
37
``
33
38
`// Must match Environment::TickInfo::Fields in src/env.h.
`
`@@ -130,15 +135,52 @@ function nextTick(callback) {
`
130
135
`queue.push(new TickObject(callback, args, getDefaultTriggerAsyncId()));
`
131
136
`}
`
132
137
``
133
``
`-
// TODO(joyeecheung): make this a factory class so that node.js can
`
134
``
`-
// control the side effects caused by the initializers.
`
135
``
`-
exports.setup = function() {
`
136
``
`-
// Sets the per-isolate promise rejection callback
`
137
``
`-
listenForRejections();
`
138
``
`-
// Sets the callback to be run in every tick.
`
139
``
`-
setTickCallback(processTicksAndRejections);
`
140
``
`-
return {
`
141
``
`-
nextTick,
`
142
``
`-
runNextTicks
`
143
``
`-
};
`
``
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 queueMicrotask(callback) {
`
``
151
`+
if (typeof callback !== 'function') {
`
``
152
`+
throw new ERR_INVALID_ARG_TYPE('callback', 'function', callback);
`
``
153
`+
}
`
``
154
+
``
155
`+
const asyncResource = createMicrotaskResource();
`
``
156
+
``
157
`+
enqueueMicrotask(() => {
`
``
158
`+
asyncResource.runInAsyncScope(() => {
`
``
159
`+
try {
`
``
160
`+
callback();
`
``
161
`+
} catch (error) {
`
``
162
`+
// TODO(devsnek) remove this if
`
``
163
`+
// https://bugs.chromium.org/p/v8/issues/detail?id=8326
`
``
164
`+
// is resolved such that V8 triggers the fatal exception
`
``
165
`+
// handler for microtasks
`
``
166
`+
triggerFatalException(error);
`
``
167
`+
} finally {
`
``
168
`+
asyncResource.emitDestroy();
`
``
169
`+
}
`
``
170
`+
});
`
``
171
`+
});
`
``
172
`+
}
`
``
173
+
``
174
`+
module.exports = {
`
``
175
`+
setupTaskQueue() {
`
``
176
`+
// Sets the per-isolate promise rejection callback
`
``
177
`+
listenForRejections();
`
``
178
`+
// Sets the callback to be run in every tick.
`
``
179
`+
setTickCallback(processTicksAndRejections);
`
``
180
`+
return {
`
``
181
`+
nextTick,
`
``
182
`+
runNextTicks
`
``
183
`+
};
`
``
184
`+
},
`
``
185
`+
queueMicrotask
`
144
186
`};
`