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

`};

`