console: mark special console properties as non-enumerable

This makes sure internal console properties are not visible during
default inspection. They are still visible when inspecting the
console with `showHidden` set to `true`.

These properties are confusing while working with the REPL and easily
show up.

Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>

PR-URL: https://github.com/nodejs/node/pull/33524
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
This commit is contained in:
Ruben Bridgewater 2020-05-22 14:04:51 +02:00
parent b61249e32d
commit 87629d7e7c

View File

@ -155,17 +155,25 @@ ObjectDefineProperty(Console, SymbolHasInstance, {
} }
}); });
const kColorInspectOptions = { colors: true };
const kNoColorInspectOptions = {};
ObjectDefineProperties(Console.prototype, {
[kBindStreamsEager]: {
...consolePropAttributes,
// Eager version for the Console constructor // Eager version for the Console constructor
Console.prototype[kBindStreamsEager] = function(stdout, stderr) { value: function(stdout, stderr) {
ObjectDefineProperties(this, { ObjectDefineProperties(this, {
'_stdout': { ...consolePropAttributes, value: stdout }, '_stdout': { ...consolePropAttributes, value: stdout },
'_stderr': { ...consolePropAttributes, value: stderr } '_stderr': { ...consolePropAttributes, value: stderr }
}); });
}; }
},
[kBindStreamsLazy]: {
...consolePropAttributes,
// Lazily load the stdout and stderr from an object so we don't // Lazily load the stdout and stderr from an object so we don't
// create the stdio streams when they are not even accessed // create the stdio streams when they are not even accessed
Console.prototype[kBindStreamsLazy] = function(object) { value: function(object) {
let stdout; let stdout;
let stderr; let stderr;
ObjectDefineProperties(this, { ObjectDefineProperties(this, {
@ -188,10 +196,11 @@ Console.prototype[kBindStreamsLazy] = function(object) {
set(value) { stderr = value; } set(value) { stderr = value; }
} }
}); });
}; }
},
Console.prototype[kBindProperties] = function(ignoreErrors, colorMode, [kBindProperties]: {
groupIndentation = 2) { ...consolePropAttributes,
value: function(ignoreErrors, colorMode, groupIndentation = 2) {
ObjectDefineProperties(this, { ObjectDefineProperties(this, {
'_stdoutErrorHandler': { '_stdoutErrorHandler': {
...consolePropAttributes, ...consolePropAttributes,
@ -216,30 +225,11 @@ Console.prototype[kBindProperties] = function(ignoreErrors, colorMode,
value: groupIndentation value: groupIndentation
}, },
}); });
};
// Make a function that can serve as the callback passed to `stream.write()`.
function createWriteErrorHandler(instance, streamSymbol) {
return (err) => {
// This conditional evaluates to true if and only if there was an error
// that was not already emitted (which happens when the _write callback
// is invoked asynchronously).
const stream = streamSymbol === kUseStdout ?
instance._stdout : instance._stderr;
if (err !== null && !stream._writableState.errorEmitted) {
// If there was an error, it will be emitted on `stream` as
// an `error` event. Adding a `once` listener will keep that error
// from becoming an uncaught exception, but since the handler is
// removed after the event, non-console.* writes won't be affected.
// we are only adding noop if there is no one else listening for 'error'
if (stream.listenerCount('error') === 0) {
stream.once('error', noop);
} }
} },
}; [kWriteToConsole]: {
} ...consolePropAttributes,
value: function(streamSymbol, string) {
Console.prototype[kWriteToConsole] = function(streamSymbol, string) {
const ignoreErrors = this._ignoreErrors; const ignoreErrors = this._ignoreErrors;
const groupIndent = this[kGroupIndent]; const groupIndent = this[kGroupIndent];
@ -262,25 +252,26 @@ Console.prototype[kWriteToConsole] = function(streamSymbol, string) {
// on POSIX systems) or asynchronously (e.g. pipes on POSIX systems), so // on POSIX systems) or asynchronously (e.g. pipes on POSIX systems), so
// handle both situations. // handle both situations.
try { try {
// Add and later remove a noop error handler to catch synchronous errors. // Add and later remove a noop error handler to catch synchronous
// errors.
if (stream.listenerCount('error') === 0) if (stream.listenerCount('error') === 0)
stream.once('error', noop); stream.once('error', noop);
stream.write(string, errorHandler); stream.write(string, errorHandler);
} catch (e) { } catch (e) {
// Console is a debugging utility, so it swallowing errors is not desirable // Console is a debugging utility, so it swallowing errors is not
// even in edge cases such as low stack space. // desirable even in edge cases such as low stack space.
if (isStackOverflowError(e)) if (isStackOverflowError(e))
throw e; throw e;
// Sorry, there's no proper way to pass along the error here. // Sorry, there's no proper way to pass along the error here.
} finally { } finally {
stream.removeListener('error', noop); stream.removeListener('error', noop);
} }
}; }
},
const kColorInspectOptions = { colors: true }; [kGetInspectOptions]: {
const kNoColorInspectOptions = {}; ...consolePropAttributes,
Console.prototype[kGetInspectOptions] = function(stream) { value: function(stream) {
let color = this[kColorMode]; let color = this[kColorMode];
if (color === 'auto') { if (color === 'auto') {
color = stream.isTTY && ( color = stream.isTTY && (
@ -297,17 +288,44 @@ Console.prototype[kGetInspectOptions] = function(stream) {
} }
return color ? kColorInspectOptions : kNoColorInspectOptions; return color ? kColorInspectOptions : kNoColorInspectOptions;
}; }
},
Console.prototype[kFormatForStdout] = function(args) { [kFormatForStdout]: {
...consolePropAttributes,
value: function(args) {
const opts = this[kGetInspectOptions](this._stdout); const opts = this[kGetInspectOptions](this._stdout);
return formatWithOptions(opts, ...args); return formatWithOptions(opts, ...args);
}; }
},
Console.prototype[kFormatForStderr] = function(args) { [kFormatForStderr]: {
...consolePropAttributes,
value: function(args) {
const opts = this[kGetInspectOptions](this._stderr); const opts = this[kGetInspectOptions](this._stderr);
return formatWithOptions(opts, ...args); return formatWithOptions(opts, ...args);
}
},
});
// Make a function that can serve as the callback passed to `stream.write()`.
function createWriteErrorHandler(instance, streamSymbol) {
return (err) => {
// This conditional evaluates to true if and only if there was an error
// that was not already emitted (which happens when the _write callback
// is invoked asynchronously).
const stream = streamSymbol === kUseStdout ?
instance._stdout : instance._stderr;
if (err !== null && !stream._writableState.errorEmitted) {
// If there was an error, it will be emitted on `stream` as
// an `error` event. Adding a `once` listener will keep that error
// from becoming an uncaught exception, but since the handler is
// removed after the event, non-console.* writes won't be affected.
// we are only adding noop if there is no one else listening for 'error'
if (stream.listenerCount('error') === 0) {
stream.once('error', noop);
}
}
}; };
}
const consoleMethods = { const consoleMethods = {
log(...args) { log(...args) {