Skip to content

Commit f68428b

Browse files
rickyesaddaleax
authored andcommitted
console: support console constructor groupIndentation option
PR-URL: #32964 Fixes: #32947 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 38146e7 commit f68428b

File tree

3 files changed

+122
-16
lines changed

3 files changed

+122
-16
lines changed

doc/api/console.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,19 @@ const { Console } = console;
8181
### `new Console(options)`
8282
<!-- YAML
8383
changes:
84-
- version: v8.0.0
85-
pr-url: https://github.com/nodejs/node/pull/9744
86-
description: The `ignoreErrors` option was introduced.
84+
- version: REPLACEME
85+
pr-url: https://github.com/nodejs/node/pull/32964
86+
description: The `groupIndentation` option was introduced.
87+
- version: v11.7.0
88+
pr-url: https://github.com/nodejs/node/pull/24978
89+
description: The `inspectOptions` option is introduced.
8790
- version: v10.0.0
8891
pr-url: https://github.com/nodejs/node/pull/19372
8992
description: The `Console` constructor now supports an `options` argument,
9093
and the `colorMode` option was introduced.
91-
- version: v11.7.0
92-
pr-url: https://github.com/nodejs/node/pull/24978
93-
description: The `inspectOptions` option is introduced.
94+
- version: v8.0.0
95+
pr-url: https://github.com/nodejs/node/pull/9744
96+
description: The `ignoreErrors` option was introduced.
9497
-->
9598

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

111116
Creates a new `Console` with one or two writable stream instances. `stdout` is a
112117
writable stream to print log or info output. `stderr` is used for warning or
@@ -306,7 +311,8 @@ added: v8.5.0
306311

307312
* `...label` {any}
308313

309-
Increases indentation of subsequent lines by two spaces.
314+
Increases indentation of subsequent lines by spaces for `groupIndentation`
315+
length.
310316

311317
If one or more `label`s are provided, those are printed first without the
312318
additional indentation.
@@ -323,7 +329,8 @@ An alias for [`console.group()`][].
323329
added: v8.5.0
324330
-->
325331

326-
Decreases indentation of subsequent lines by two spaces.
332+
Decreases indentation of subsequent lines by spaces for `groupIndentation`
333+
length.
327334

328335
### `console.info([data][, ...args])`
329336
<!-- YAML

lib/internal/console/constructor.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const {
3232
ERR_INCOMPATIBLE_OPTION_PAIR,
3333
},
3434
} = require('internal/errors');
35+
const { validateInteger } = require('internal/validators');
3536
const { previewEntries } = internalBinding('util');
3637
const { Buffer: { isBuffer } } = require('buffer');
3738
const {
@@ -52,12 +53,14 @@ const kTraceInstant = 'n'.charCodeAt(0);
5253
const kSecond = 1000;
5354
const kMinute = 60 * kSecond;
5455
const kHour = 60 * kMinute;
56+
const kMaxGroupIndentation = 1000;
5557

5658
// Lazy loaded for startup performance.
5759
let cliTable;
5860

5961
// Track amount of indentation required via `console.group()`.
6062
const kGroupIndent = Symbol('kGroupIndent');
63+
const kGroupIndentationWidth = Symbol('kGroupIndentWidth');
6164
const kFormatForStderr = Symbol('kFormatForStderr');
6265
const kFormatForStdout = Symbol('kFormatForStdout');
6366
const kGetInspectOptions = Symbol('kGetInspectOptions');
@@ -93,7 +96,8 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
9396
stderr = stdout,
9497
ignoreErrors = true,
9598
colorMode = 'auto',
96-
inspectOptions
99+
inspectOptions,
100+
groupIndentation,
97101
} = options;
98102

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

113+
if (groupIndentation !== undefined) {
114+
validateInteger(groupIndentation, 'groupIndentation',
115+
0, kMaxGroupIndentation);
116+
}
117+
109118
if (typeof inspectOptions === 'object' && inspectOptions !== null) {
110119
if (inspectOptions.colors !== undefined &&
111120
options.colorMode !== undefined) {
@@ -130,7 +139,7 @@ function Console(options /* or: stdout, stderr, ignoreErrors = true */) {
130139
}
131140

132141
this[kBindStreamsEager](stdout, stderr);
133-
this[kBindProperties](ignoreErrors, colorMode);
142+
this[kBindProperties](ignoreErrors, colorMode, groupIndentation);
134143
}
135144

136145
const consolePropAttributes = {
@@ -181,7 +190,8 @@ Console.prototype[kBindStreamsLazy] = function(object) {
181190
});
182191
};
183192

184-
Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) {
193+
Console.prototype[kBindProperties] = function(ignoreErrors, colorMode,
194+
groupIndentation = 2) {
185195
ObjectDefineProperties(this, {
186196
'_stdoutErrorHandler': {
187197
...consolePropAttributes,
@@ -200,7 +210,11 @@ Console.prototype[kBindProperties] = function(ignoreErrors, colorMode) {
200210
[kCounts]: { ...consolePropAttributes, value: new Map() },
201211
[kColorMode]: { ...consolePropAttributes, value: colorMode },
202212
[kIsConsole]: { ...consolePropAttributes, value: true },
203-
[kGroupIndent]: { ...consolePropAttributes, value: '' }
213+
[kGroupIndent]: { ...consolePropAttributes, value: '' },
214+
[kGroupIndentationWidth]: {
215+
...consolePropAttributes,
216+
value: groupIndentation
217+
},
204218
});
205219
};
206220

@@ -403,12 +417,13 @@ const consoleMethods = {
403417
if (data.length > 0) {
404418
this.log(...data);
405419
}
406-
this[kGroupIndent] += ' ';
420+
this[kGroupIndent] += ' '.repeat(this[kGroupIndentationWidth]);
407421
},
408422

409423
groupEnd() {
410424
this[kGroupIndent] =
411-
this[kGroupIndent].slice(0, this[kGroupIndent].length - 2);
425+
this[kGroupIndent].slice(0, this[kGroupIndent].length -
426+
this[kGroupIndentationWidth]);
412427
},
413428

414429
// https://console.spec.whatwg.org/#table

test/parallel/test-console-group.js

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const Console = require('console').Console;
1212

1313
let c, stdout, stderr;
1414

15-
function setup() {
15+
function setup(groupIndentation) {
1616
stdout = '';
1717
hijackStdout(function(data) {
1818
stdout += data;
@@ -25,7 +25,8 @@ function setup() {
2525

2626
c = new Console({ stdout: process.stdout,
2727
stderr: process.stderr,
28-
colorMode: false });
28+
colorMode: false,
29+
groupIndentation: groupIndentation });
2930
}
3031

3132
function teardown() {
@@ -155,3 +156,86 @@ function teardown() {
155156
assert(!keys.includes('Symbol(groupIndent)'),
156157
'groupIndent should not be enumerable');
157158
}
159+
160+
// Check custom groupIndentation.
161+
{
162+
setup(3);
163+
const expectedOut = 'Set the groupIndentation parameter to 3\n' +
164+
'This is the outer level\n' +
165+
' Level 2\n' +
166+
' Level 3\n' +
167+
' Back to level 2\n' +
168+
'Back to the outer level\n' +
169+
'Still at the outer level\n';
170+
171+
172+
const expectedErr = ' More of level 3\n';
173+
174+
c.log('Set the groupIndentation parameter to 3');
175+
c.log('This is the outer level');
176+
c.group();
177+
c.log('Level 2');
178+
c.group();
179+
c.log('Level 3');
180+
c.warn('More of level 3');
181+
c.groupEnd();
182+
c.log('Back to level 2');
183+
c.groupEnd();
184+
c.log('Back to the outer level');
185+
c.groupEnd();
186+
c.log('Still at the outer level');
187+
188+
assert.strictEqual(stdout, expectedOut);
189+
assert.strictEqual(stderr, expectedErr);
190+
teardown();
191+
}
192+
193+
// Check the correctness of the groupIndentation parameter.
194+
{
195+
// TypeError
196+
[null, 'str', [], false, true, {}].forEach((e) => {
197+
assert.throws(
198+
() => {
199+
new Console({ stdout: process.stdout,
200+
stderr: process.stderr,
201+
groupIndentation: e });
202+
},
203+
{
204+
code: 'ERR_INVALID_ARG_TYPE',
205+
name: 'TypeError'
206+
}
207+
);
208+
});
209+
210+
// RangeError for integer
211+
[NaN, 1.01].forEach((e) => {
212+
assert.throws(
213+
() => {
214+
new Console({ stdout: process.stdout,
215+
stderr: process.stderr,
216+
groupIndentation: e });
217+
},
218+
{
219+
code: 'ERR_OUT_OF_RANGE',
220+
name: 'RangeError',
221+
message: /an integer/,
222+
}
223+
);
224+
});
225+
226+
// RangeError
227+
[-1, 1001].forEach((e) => {
228+
assert.throws(
229+
() => {
230+
new Console({ stdout: process.stdout,
231+
stderr: process.stderr,
232+
groupIndentation: e });
233+
},
234+
{
235+
code: 'ERR_OUT_OF_RANGE',
236+
name: 'RangeError',
237+
message: />= 0 && <= 1000/,
238+
}
239+
);
240+
});
241+
}

0 commit comments

Comments
 (0)