◐ Shell
clean mode source ↗

console: do not emit error events · nodejs/node@f18e08d

@@ -2,9 +2,9 @@

2233

const util = require('util');

445-

function Console(stdout, stderr) {

5+

function Console(stdout, stderr, ignoreErrors = true) {

66

if (!(this instanceof Console)) {

7-

return new Console(stdout, stderr);

7+

return new Console(stdout, stderr, ignoreErrors);

88

}

99

if (!stdout || typeof stdout.write !== 'function') {

1010

throw new TypeError('Console expects a writable stream instance');

@@ -24,8 +24,14 @@ function Console(stdout, stderr) {

2424

Object.defineProperty(this, '_stdout', prop);

2525

prop.value = stderr;

2626

Object.defineProperty(this, '_stderr', prop);

27+

prop.value = ignoreErrors;

28+

Object.defineProperty(this, '_ignoreErrors', prop);

2729

prop.value = new Map();

2830

Object.defineProperty(this, '_times', prop);

31+

prop.value = createWriteErrorHandler(stdout);

32+

Object.defineProperty(this, '_stdoutErrorHandler', prop);

33+

prop.value = createWriteErrorHandler(stderr);

34+

Object.defineProperty(this, '_stderrErrorHandler', prop);

29353036

// bind the prototype functions to this Console instance

3137

var keys = Object.keys(Console.prototype);

@@ -35,20 +41,60 @@ function Console(stdout, stderr) {

3541

}

3642

}

374344+

// Make a function that can serve as the callback passed to `stream.write()`.

45+

function createWriteErrorHandler(stream) {

46+

return (err) => {

47+

// This conditional evaluates to true if and only if there was an error

48+

// that was not already emitted (which happens when the _write callback

49+

// is invoked asynchronously).

50+

if (err && !stream._writableState.errorEmitted) {

51+

// If there was an error, it will be emitted on `stream` as

52+

// an `error` event. Adding a `once` listener will keep that error

53+

// from becoming an uncaught exception, but since the handler is

54+

// removed after the event, non-console.* writes won’t be affected.

55+

stream.once('error', noop);

56+

}

57+

};

58+

}

59+60+

function write(ignoreErrors, stream, string, errorhandler) {

61+

if (!ignoreErrors) return stream.write(string);

62+63+

// There may be an error occurring synchronously (e.g. for files or TTYs

64+

// on POSIX systems) or asynchronously (e.g. pipes on POSIX systems), so

65+

// handle both situations.

66+

try {

67+

// Add and later remove a noop error handler to catch synchronous errors.

68+

stream.once('error', noop);

69+70+

stream.write(string, errorhandler);

71+

} catch (e) {

72+

// Sorry, there’s no proper way to pass along the error here.

73+

} finally {

74+

stream.removeListener('error', noop);

75+

}

76+

}

77+38783979

// As of v8 5.0.71.32, the combination of rest param, template string

4080

// and .apply(null, args) benchmarks consistently faster than using

4181

// the spread operator when calling util.format.

4282

Console.prototype.log = function log(...args) {

43-

this._stdout.write(`${util.format.apply(null, args)}\n`);

83+

write(this._ignoreErrors,

84+

this._stdout,

85+

`${util.format.apply(null, args)}\n`,

86+

this._stdoutErrorHandler);

4487

};

458846894790

Console.prototype.info = Console.prototype.log;

489149925093

Console.prototype.warn = function warn(...args) {

51-

this._stderr.write(`${util.format.apply(null, args)}\n`);

94+

write(this._ignoreErrors,

95+

this._stderr,

96+

`${util.format.apply(null, args)}\n`,

97+

this._stderrErrorHandler);

5298

};

539954100

@@ -57,7 +103,7 @@ Console.prototype.error = Console.prototype.warn;

5710358104

Console.prototype.dir = function dir(object, options) {

59105

options = Object.assign({customInspect: false}, options);

60-

this._stdout.write(`${util.inspect(object, options)}\n`);

106+

write(this._ignoreErrors, this._stdout, `${util.inspect(object, options)}\n`);

61107

};

6210863109

@@ -99,3 +145,5 @@ Console.prototype.assert = function assert(expression, ...args) {

99145100146

module.exports = new Console(process.stdout, process.stderr);

101147

module.exports.Console = Console;

148+149+

function noop() {}