Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

console: Support for console constructor groupIndentation options #32964

Closed
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 23 additions & 8 deletions doc/api/console.md
Expand Up @@ -81,16 +81,19 @@ const { Console } = console;
### `new Console(options)`
<!-- YAML
changes:
- version: v8.0.0
pr-url: https://github.com/nodejs/node/pull/9744
description: The `ignoreErrors` option was introduced.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/32964
description: The `groupIndentation` option was introduced.
- version: v11.7.0
pr-url: https://github.com/nodejs/node/pull/24978
description: The `inspectOptions` option is introduced.
- version: v10.0.0
pr-url: https://github.com/nodejs/node/pull/19372
description: The `Console` constructor now supports an `options` argument,
and the `colorMode` option was introduced.
- version: v11.7.0
pr-url: https://github.com/nodejs/node/pull/24978
description: The `inspectOptions` option is introduced.
- version: v8.0.0
pr-url: https://github.com/nodejs/node/pull/9744
description: The `ignoreErrors` option was introduced.
-->

* `options` {Object}
Expand All @@ -107,6 +110,8 @@ changes:
**Default:** `'auto'`.
* `inspectOptions` {Object} Specifies options that are passed along to
[`util.inspect()`][].
* `groupIndentation` {number} Set group indentation.
**Default:** `2`.

Creates a new `Console` with one or two writable stream instances. `stdout` is a
writable stream to print log or info output. `stderr` is used for warning or
Expand Down Expand Up @@ -302,11 +307,16 @@ values are concatenated. See [`util.format()`][] for more information.
### `console.group([...label])`
<!-- YAML
added: v8.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/32964
description: The `groupIndentation` option was introduced.
rickyes marked this conversation as resolved.
Show resolved Hide resolved
-->

* `...label` {any}

Increases indentation of subsequent lines by two spaces.
Increases indentation of subsequent lines by spaces for `groupIndentation`
length.

If one or more `label`s are provided, those are printed first without the
additional indentation.
Expand All @@ -321,9 +331,14 @@ An alias for [`console.group()`][].
### `console.groupEnd()`
<!-- YAML
added: v8.5.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/32964
description: The `groupIndentation` option was introduced.
rickyes marked this conversation as resolved.
Show resolved Hide resolved
-->

Decreases indentation of subsequent lines by two spaces.
Decreases indentation of subsequent lines by spaces for `groupIndentation`
length.

### `console.info([data][, ...args])`
<!-- YAML
Expand Down
27 changes: 21 additions & 6 deletions lib/internal/console/constructor.js
Expand Up @@ -32,6 +32,7 @@ const {
ERR_INCOMPATIBLE_OPTION_PAIR,
},
} = require('internal/errors');
const { validateInteger } = require('internal/validators');
const { previewEntries } = internalBinding('util');
const { Buffer: { isBuffer } } = require('buffer');
const {
Expand All @@ -52,12 +53,14 @@ const kTraceInstant = 'n'.charCodeAt(0);
const kSecond = 1000;
const kMinute = 60 * kSecond;
const kHour = 60 * kMinute;
const kMaxGroupIndentation = 1000;

// Lazy loaded for startup performance.
let cliTable;

// Track amount of indentation required via `console.group()`.
const kGroupIndent = Symbol('kGroupIndent');
const kGroupIndentationWidth = Symbol('kGroupIndentWidth');
const kFormatForStderr = Symbol('kFormatForStderr');
const kFormatForStdout = Symbol('kFormatForStdout');
const kGetInspectOptions = Symbol('kGetInspectOptions');
Expand Down Expand Up @@ -93,7 +96,8 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
stderr = stdout,
ignoreErrors = true,
colorMode = 'auto',
inspectOptions
inspectOptions,
groupIndentation,
} = options;

if (!stdout || typeof stdout.write !== 'function') {
Expand All @@ -106,6 +110,11 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
if (typeof colorMode !== 'boolean' && colorMode !== 'auto')
throw new ERR_INVALID_ARG_VALUE('colorMode', colorMode);

if (groupIndentation !== undefined) {
validateInteger(groupIndentation, 'groupIndentation',
0, kMaxGroupIndentation);
}

if (typeof inspectOptions === 'object' && inspectOptions !== null) {
if (inspectOptions.colors !== undefined &&
options.colorMode !== undefined) {
Expand All @@ -130,7 +139,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
}

this[kBindStreamsEager](stdout, stderr);
this[kBindProperties](ignoreErrors, colorMode);
this[kBindProperties](ignoreErrors, colorMode, groupIndentation);
}

const consolePropAttributes = {
Expand Down Expand Up @@ -181,7 +190,8 @@ Console.prototype[kBindStreamsLazy] = function(object) {
});
};

Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) {
Console.prototype[kBindProperties] = function(ignoreErrors, colorMode,
groupIndentation = 2) {
ObjectDefineProperties(this, {
'_stdoutErrorHandler': {
...consolePropAttributes,
Expand All @@ -200,7 +210,11 @@ Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) {
[kCounts]: { ...consolePropAttributes, value: new Map() },
[kColorMode]: { ...consolePropAttributes, value: colorMode },
[kIsConsole]: { ...consolePropAttributes, value: true },
[kGroupIndent]: { ...consolePropAttributes, value: '' }
[kGroupIndent]: { ...consolePropAttributes, value: '' },
[kGroupIndentationWidth]: {
...consolePropAttributes,
value: groupIndentation
},
});
};

Expand Down Expand Up @@ -403,12 +417,13 @@ const consoleMethods = {
if (data.length > 0) {
this.log(...data);
}
this[kGroupIndent] += ' ';
this[kGroupIndent] += ' '.repeat(this[kGroupIndentationWidth]);
},

groupEnd() {
this[kGroupIndent] =
this[kGroupIndent].slice(0, this[kGroupIndent].length - 2);
this[kGroupIndent].slice(0, this[kGroupIndent].length -
this[kGroupIndentationWidth]);
},

// https://console.spec.whatwg.org/#table
Expand Down
88 changes: 86 additions & 2 deletions test/parallel/test-console-group.js
Expand Up @@ -12,7 +12,7 @@ const Console = require('console').Console;

let c, stdout, stderr;

function setup() {
function setup(groupIndentation) {
stdout = '';
hijackStdout(function(data) {
stdout += data;
Expand All @@ -25,7 +25,8 @@ function setup() {

c = new Console({ stdout: process.stdout,
stderr: process.stderr,
colorMode: false });
colorMode: false,
groupIndentation: groupIndentation });
}

function teardown() {
Expand Down Expand Up @@ -155,3 +156,86 @@ function teardown() {
assert(!keys.includes('Symbol(groupIndent)'),
'groupIndent should not be enumerable');
}

// Check custom groupIndentation.
{
setup(3);
const expectedOut = 'Set the groupIndentation parameter to 3\n' +
'This is the outer level\n' +
' Level 2\n' +
' Level 3\n' +
' Back to level 2\n' +
'Back to the outer level\n' +
'Still at the outer level\n';


const expectedErr = ' More of level 3\n';

c.log('Set the groupIndentation parameter to 3');
c.log('This is the outer level');
c.group();
c.log('Level 2');
c.group();
c.log('Level 3');
c.warn('More of level 3');
c.groupEnd();
c.log('Back to level 2');
c.groupEnd();
c.log('Back to the outer level');
c.groupEnd();
c.log('Still at the outer level');

assert.strictEqual(stdout, expectedOut);
assert.strictEqual(stderr, expectedErr);
teardown();
}

// Check the correctness of the groupIndentation parameter.
{
// TypeError
[null, 'str', [], false, true, {}].forEach((e) => {
assert.throws(
() => {
new Console({ stdout: process.stdout,
stderr: process.stderr,
groupIndentation: e });
},
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError'
}
);
});

// RangeError for integer
[NaN, 1.01].forEach((e) => {
assert.throws(
() => {
new Console({ stdout: process.stdout,
stderr: process.stderr,
groupIndentation: e });
},
{
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError',
message: /an integer/,
}
);
});

// RangeError
[-1, 1001].forEach((e) => {
assert.throws(
() => {
new Console({ stdout: process.stdout,
stderr: process.stderr,
groupIndentation: e });
},
{
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError',
message: />= 0 && <= 1000/,
}
);
});
}