process: add --unhandled-rejections flag · nodejs/node@9dcc9b6 (original) (raw)

1

1

`'use strict';

`

2

2

``

3

``

`-

const { safeToString } = internalBinding('util');

`

``

3

`+

const { Object } = primordials;

`

``

4

+

``

5

`+

const {

`

``

6

`+

safeToString

`

``

7

`+

} = internalBinding('util');

`

4

8

`const {

`

5

9

` tickInfo,

`

6

10

`promiseRejectEvents: {

`

`@@ -9,7 +13,8 @@ const {

`

9

13

` kPromiseResolveAfterResolved,

`

10

14

` kPromiseRejectAfterResolved

`

11

15

`},

`

12

``

`-

setPromiseRejectCallback

`

``

16

`+

setPromiseRejectCallback,

`

``

17

`+

triggerFatalException

`

13

18

`} = internalBinding('task_queue');

`

14

19

``

15

20

`// Must match Environment::TickInfo::Fields in src/env.h.

`

`@@ -20,6 +25,15 @@ const pendingUnhandledRejections = [];

`

20

25

`const asyncHandledRejections = [];

`

21

26

`let lastPromiseId = 0;

`

22

27

``

``

28

`+

const states = {

`

``

29

`+

none: 0,

`

``

30

`+

warn: 1,

`

``

31

`+

strict: 2,

`

``

32

`+

default: 3

`

``

33

`+

};

`

``

34

+

``

35

`+

let state;

`

``

36

+

23

37

`function setHasRejectionToWarn(value) {

`

24

38

`tickInfo[kHasRejectionToWarn] = value ? 1 : 0;

`

25

39

`}

`

`@@ -29,6 +43,10 @@ function hasRejectionToWarn() {

`

29

43

`}

`

30

44

``

31

45

`function promiseRejectHandler(type, promise, reason) {

`

``

46

`+

if (state === undefined) {

`

``

47

`+

const { getOptionValue } = require('internal/options');

`

``

48

`+

state = states[getOptionValue('--unhandled-rejections') || 'default'];

`

``

49

`+

}

`

32

50

`switch (type) {

`

33

51

`case kPromiseRejectWithNoHandler:

`

34

52

`unhandledRejection(promise, reason);

`

`@@ -59,6 +77,7 @@ function unhandledRejection(promise, reason) {

`

59

77

`uid: ++lastPromiseId,

`

60

78

`warned: false

`

61

79

`});

`

``

80

`+

// This causes the promise to be referenced at least for one tick.

`

62

81

`pendingUnhandledRejections.push(promise);

`

63

82

`setHasRejectionToWarn(true);

`

64

83

`}

`

`@@ -85,14 +104,16 @@ function handledRejection(promise) {

`

85

104

``

86

105

`const unhandledRejectionErrName = 'UnhandledPromiseRejectionWarning';

`

87

106

`function emitWarning(uid, reason) {

`

88

``

`-

// eslint-disable-next-line no-restricted-syntax

`

89

``

`-

const warning = new Error(

`

``

107

`+

if (state === states.none) {

`

``

108

`+

return;

`

``

109

`+

}

`

``

110

`+

const warning = getError(

`

``

111

`+

unhandledRejectionErrName,

`

90

112

`'Unhandled promise rejection. This error originated either by ' +

`

91

``

`-

'throwing inside of an async function without a catch block, ' +

`

92

``

`-

'or by rejecting a promise which was not handled with .catch(). ' +

`

93

``

`` -

(rejection id: ${uid})

``

``

113

`+

'throwing inside of an async function without a catch block, ' +

`

``

114

`+

'or by rejecting a promise which was not handled with .catch(). ' +

`

``

115

`` +

(rejection id: ${uid})

``

94

116

`);

`

95

``

`-

warning.name = unhandledRejectionErrName;

`

96

117

`try {

`

97

118

`if (reason instanceof Error) {

`

98

119

`warning.stack = reason.stack;

`

`@@ -108,7 +129,7 @@ function emitWarning(uid, reason) {

`

108

129

``

109

130

`let deprecationWarned = false;

`

110

131

`function emitDeprecationWarning() {

`

111

``

`-

if (!deprecationWarned) {

`

``

132

`+

if (state === states.default && !deprecationWarned) {

`

112

133

`deprecationWarned = true;

`

113

134

`process.emitWarning(

`

114

135

`'Unhandled promise rejections are deprecated. In the future, ' +

`

`@@ -133,18 +154,57 @@ function processPromiseRejections() {

`

133

154

`while (len--) {

`

134

155

`const promise = pendingUnhandledRejections.shift();

`

135

156

`const promiseInfo = maybeUnhandledPromises.get(promise);

`

136

``

`-

if (promiseInfo !== undefined) {

`

137

``

`-

promiseInfo.warned = true;

`

138

``

`-

const { reason, uid } = promiseInfo;

`

139

``

`-

if (!process.emit('unhandledRejection', reason, promise)) {

`

140

``

`-

emitWarning(uid, reason);

`

141

``

`-

}

`

142

``

`-

maybeScheduledTicks = true;

`

``

157

`+

if (promiseInfo === undefined) {

`

``

158

`+

continue;

`

``

159

`+

}

`

``

160

`+

promiseInfo.warned = true;

`

``

161

`+

const { reason, uid } = promiseInfo;

`

``

162

`+

if (state === states.strict) {

`

``

163

`+

fatalException(reason);

`

143

164

`}

`

``

165

`+

if (!process.emit('unhandledRejection', reason, promise) ||

`

``

166

`+

// Always warn in case the user requested it.

`

``

167

`+

state === states.warn) {

`

``

168

`+

emitWarning(uid, reason);

`

``

169

`+

}

`

``

170

`+

maybeScheduledTicks = true;

`

144

171

`}

`

145

172

`return maybeScheduledTicks || pendingUnhandledRejections.length !== 0;

`

146

173

`}

`

147

174

``

``

175

`+

function getError(name, message) {

`

``

176

`+

// Reset the stack to prevent any overhead.

`

``

177

`+

const tmp = Error.stackTraceLimit;

`

``

178

`+

Error.stackTraceLimit = 0;

`

``

179

`+

// eslint-disable-next-line no-restricted-syntax

`

``

180

`+

const err = new Error(message);

`

``

181

`+

Error.stackTraceLimit = tmp;

`

``

182

`+

Object.defineProperty(err, 'name', {

`

``

183

`+

value: name,

`

``

184

`+

enumerable: false,

`

``

185

`+

writable: true,

`

``

186

`+

configurable: true,

`

``

187

`+

});

`

``

188

`+

return err;

`

``

189

`+

}

`

``

190

+

``

191

`+

function fatalException(reason) {

`

``

192

`+

let err;

`

``

193

`+

if (reason instanceof Error) {

`

``

194

`+

err = reason;

`

``

195

`+

} else {

`

``

196

`+

err = getError(

`

``

197

`+

'UnhandledPromiseRejection',

`

``

198

`+

'This error originated either by ' +

`

``

199

`+

'throwing inside of an async function without a catch block, ' +

`

``

200

`+

'or by rejecting a promise which was not handled with .catch().' +

`

``

201

`` +

The promise rejected with the reason "${safeToString(reason)}".

``

``

202

`+

);

`

``

203

`+

err.code = 'ERR_UNHANDLED_REJECTION';

`

``

204

`+

}

`

``

205

`+

triggerFatalException(err, true /* fromPromise */);

`

``

206

`+

}

`

``

207

+

148

208

`function listenForRejections() {

`

149

209

`setPromiseRejectCallback(promiseRejectHandler);

`

150

210

`}

`