| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0af4183 commit f18e08d
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,9 +2,9 @@ | |||
| 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() {} | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,17 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const { Console } = require('console'); | ||
| 4 | + const { Writable } = require('stream'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + | ||
| 7 | + const out = new Writable({ | ||
| 8 | + write: common.mustCall((chunk, enc, callback) => { | ||
| 9 | + process.nextTick(callback, new Error('foobar')); | ||
| 10 | + }) | ||
| 11 | + }); | ||
| 12 | + | ||
| 13 | + const c = new Console(out, out, true); | ||
| 14 | + | ||
| 15 | + assert.doesNotThrow(() => { | ||
| 16 | + c.log('abc'); | ||
| 17 | + }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,47 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const { Console } = require('console'); | ||
| 4 | + const { Writable } = require('stream'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + | ||
| 7 | + { | ||
| 8 | + const out = new Writable({ | ||
| 9 | + write: common.mustCall((chunk, enc, callback) => { | ||
| 10 | + callback(new Error('foobar')); | ||
| 11 | + }) | ||
| 12 | + }); | ||
| 13 | + | ||
| 14 | + const c = new Console(out, out, true); | ||
| 15 | + | ||
| 16 | + assert.doesNotThrow(() => { | ||
| 17 | + c.log('abc'); | ||
| 18 | + }); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + { | ||
| 22 | + const out = new Writable({ | ||
| 23 | + write: common.mustCall((chunk, enc, callback) => { | ||
| 24 | + throw new Error('foobar'); | ||
| 25 | + }) | ||
| 26 | + }); | ||
| 27 | + | ||
| 28 | + const c = new Console(out, out, true); | ||
| 29 | + | ||
| 30 | + assert.doesNotThrow(() => { | ||
| 31 | + c.log('abc'); | ||
| 32 | + }); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + { | ||
| 36 | + const out = new Writable({ | ||
| 37 | + write: common.mustCall((chunk, enc, callback) => { | ||
| 38 | + setImmediate(() => callback(new Error('foobar'))); | ||
| 39 | + }) | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + const c = new Console(out, out, true); | ||
| 43 | + | ||
| 44 | + assert.doesNotThrow(() => { | ||
| 45 | + c.log('abc'); | ||
| 46 | + }); | ||
| 47 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments