2
2
3
3
const util = require ( 'util' ) ;
4
4
5
- function Console ( stdout , stderr ) {
5
+ function Console ( stdout , stderr , ignoreErrors = true ) {
6
6
if ( ! ( this instanceof Console ) ) {
7
- return new Console ( stdout , stderr ) ;
7
+ return new Console ( stdout , stderr , ignoreErrors ) ;
8
8
}
9
9
if ( ! stdout || typeof stdout . write !== 'function' ) {
10
10
throw new TypeError ( 'Console expects a writable stream instance' ) ;
@@ -24,8 +24,14 @@ function Console(stdout, stderr) {
24
24
Object . defineProperty ( this , '_stdout' , prop ) ;
25
25
prop . value = stderr ;
26
26
Object . defineProperty ( this , '_stderr' , prop ) ;
27
+ prop . value = ignoreErrors ;
28
+ Object . defineProperty ( this , '_ignoreErrors' , prop ) ;
27
29
prop . value = new Map ( ) ;
28
30
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 ) ;
29
35
30
36
// bind the prototype functions to this Console instance
31
37
var keys = Object . keys ( Console . prototype ) ;
@@ -35,20 +41,60 @@ function Console(stdout, stderr) {
35
41
}
36
42
}
37
43
44
+ // 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
+
38
78
39
79
// As of v8 5.0.71.32, the combination of rest param, template string
40
80
// and .apply(null, args) benchmarks consistently faster than using
41
81
// the spread operator when calling util.format.
42
82
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 ) ;
44
87
} ;
45
88
46
89
47
90
Console . prototype . info = Console . prototype . log ;
48
91
49
92
50
93
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 ) ;
52
98
} ;
53
99
54
100
@@ -57,7 +103,7 @@ Console.prototype.error = Console.prototype.warn;
57
103
58
104
Console . prototype . dir = function dir ( object , options ) {
59
105
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` ) ;
61
107
} ;
62
108
63
109
@@ -99,3 +145,5 @@ Console.prototype.assert = function assert(expression, ...args) {
99
145
100
146
module . exports = new Console ( process . stdout , process . stderr ) ;
101
147
module . exports . Console = Console ;
148
+
149
+ function noop ( ) { }
0 commit comments