Skip to content

Commit 8de8372

Browse files
committed
util: remove erroneous whitespace
When inspecting nested objects some times a whitespace was added at the end of a line. This fixes this erroneous space. Besides that the `breakLength` was not followed if a single property was longer than the breakLength. It will now break a single property into the key and value in such cases. PR-URL: nodejs#20802 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
1 parent afd290d commit 8de8372

4 files changed

Lines changed: 57 additions & 53 deletions

File tree

‎lib/util.js‎

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ function getPrefix(constructor, tag) {
416416
return '';
417417
}
418418

419-
function formatValue(ctx, value, recurseTimes, ln) {
419+
function formatValue(ctx, value, recurseTimes) {
420420
// Primitive types cannot have properties
421421
if (typeof value !== 'object' && typeof value !== 'function') {
422422
return formatPrimitive(ctx.stylize, value, ctx);
@@ -582,7 +582,7 @@ function formatValue(ctx, value, recurseTimes, ln) {
582582
return ctx.stylize(dateToISOString.call(value), 'date');
583583
}
584584
// Make dates with properties first say the date
585-
base = `${dateToISOString.call(value)}`;
585+
base = dateToISOString.call(value);
586586
} else if (isError(value)) {
587587
// Make error with message first say the error
588588
base = formatError(value);
@@ -683,7 +683,7 @@ function formatValue(ctx, value, recurseTimes, ln) {
683683
}
684684
ctx.seen.pop();
685685

686-
return reduceToSingleString(ctx, output, base, braces, ln);
686+
return reduceToSingleString(ctx, output, base, braces);
687687
}
688688

689689
function formatNumber(fn, value) {
@@ -758,7 +758,23 @@ function formatNamespaceObject(ctx, value, recurseTimes, keys) {
758758
const len = keys.length;
759759
const output = new Array(len);
760760
for (var i = 0; i < len; i++) {
761-
output[i] = formatNamespaceProperty(ctx, value, recurseTimes, keys[i]);
761+
try {
762+
output[i] = formatProperty(ctx, value, recurseTimes, keys[i], 0);
763+
} catch (err) {
764+
if (!(err instanceof ReferenceError)) {
765+
throw err;
766+
}
767+
// Use the existing functionality. This makes sure the indentation and
768+
// line breaks are always correct. Otherwise it is very difficult to keep
769+
// this aligned, even though this is a hacky way of dealing with this.
770+
const tmp = { [keys[i]]: '' };
771+
output[i] = formatProperty(ctx, tmp, recurseTimes, keys[i], 0);
772+
const pos = output[i].lastIndexOf(' ');
773+
// We have to find the last whitespace and have to replace that value as
774+
// it will be visualized as a regular string.
775+
output[i] = output[i].slice(0, pos + 1) +
776+
ctx.stylize('<uninitialized>', 'special');
777+
}
762778
}
763779
return output;
764780
}
@@ -986,42 +1002,21 @@ function formatPromise(ctx, value, recurseTimes, keys) {
9861002
return output;
9871003
}
9881004

989-
function formatKey(ctx, key, enumerable) {
990-
if (typeof key === 'symbol') {
991-
return `[${ctx.stylize(key.toString(), 'symbol')}]`;
992-
}
993-
if (enumerable === false) {
994-
return `[${key}]`;
995-
}
996-
if (keyStrRegExp.test(key)) {
997-
return ctx.stylize(key, 'name');
998-
}
999-
return ctx.stylize(strEscape(key), 'string');
1000-
}
1001-
1002-
function formatNamespaceProperty(ctx, ns, recurseTimes, key) {
1003-
let value;
1004-
try {
1005-
value = formatValue(ctx, ns[key], recurseTimes, true);
1006-
} catch (err) {
1007-
if (err instanceof ReferenceError) {
1008-
value = ctx.stylize('<uninitialized>', 'special');
1009-
} else {
1010-
throw err;
1011-
}
1012-
}
1013-
1014-
return `${formatKey(ctx, key)}: ${value}`;
1015-
}
1016-
10171005
function formatProperty(ctx, value, recurseTimes, key, array) {
1018-
let str;
1006+
let name, str;
1007+
let extra = ' ';
10191008
const desc = Object.getOwnPropertyDescriptor(value, key) ||
10201009
{ value: value[key], enumerable: true };
10211010
if (desc.value !== undefined) {
10221011
const diff = array !== 0 || ctx.compact === false ? 2 : 3;
10231012
ctx.indentationLvl += diff;
1024-
str = formatValue(ctx, desc.value, recurseTimes, array === 0);
1013+
str = formatValue(ctx, desc.value, recurseTimes);
1014+
if (diff === 3) {
1015+
const len = ctx.colors ? removeColors(str).length : str.length;
1016+
if (ctx.breakLength < len) {
1017+
extra = `\n${' '.repeat(ctx.indentationLvl)}`;
1018+
}
1019+
}
10251020
ctx.indentationLvl -= diff;
10261021
} else if (desc.get !== undefined) {
10271022
if (desc.set !== undefined) {
@@ -1037,11 +1032,19 @@ function formatProperty(ctx, value, recurseTimes, key, array) {
10371032
if (array === 1) {
10381033
return str;
10391034
}
1040-
1041-
return `${formatKey(ctx, key, desc.enumerable)}: ${str}`;
1035+
if (typeof key === 'symbol') {
1036+
name = `[${ctx.stylize(key.toString(), 'symbol')}]`;
1037+
} else if (desc.enumerable === false) {
1038+
name = `[${key}]`;
1039+
} else if (keyStrRegExp.test(key)) {
1040+
name = ctx.stylize(key, 'name');
1041+
} else {
1042+
name = ctx.stylize(strEscape(key), 'string');
1043+
}
1044+
return `${name}:${extra}${str}`;
10421045
}
10431046

1044-
function reduceToSingleString(ctx, output, base, braces, addLn) {
1047+
function reduceToSingleString(ctx, output, base, braces) {
10451048
const breakLength = ctx.breakLength;
10461049
let i = 0;
10471050
if (ctx.compact === false) {
@@ -1070,11 +1073,10 @@ function reduceToSingleString(ctx, output, base, braces, addLn) {
10701073
// we need to force the first item to be on the next line or the
10711074
// items will not line up correctly.
10721075
const indentation = ' '.repeat(ctx.indentationLvl);
1073-
const extraLn = addLn === true ? `\n${indentation}` : '';
10741076
const ln = base === '' && braces[0].length === 1 ?
1075-
' ' : `${base ? ` ${base}` : base}\n${indentation} `;
1077+
' ' : `${base ? ` ${base}` : ''}\n${indentation} `;
10761078
const str = join(output, `,\n${indentation} `);
1077-
return `${extraLn}${braces[0]}${ln}${str} ${braces[1]}`;
1079+
return `${braces[0]}${ln}${str} ${braces[1]}`;
10781080
}
10791081

10801082
function isBoolean(arg) {

‎test/parallel/test-util-format.js‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ assert.strictEqual(
126126
util.format('%o', obj),
127127
'{ foo: \'bar\',\n' +
128128
' foobar: 1,\n' +
129-
' func: \n' +
129+
' func:\n' +
130130
' { [Function: func]\n' +
131131
' [length]: 0,\n' +
132132
' [name]: \'func\',\n' +
@@ -135,8 +135,8 @@ assert.strictEqual(
135135
util.format('%o', nestedObj2),
136136
'{ foo: \'bar\',\n' +
137137
' foobar: 1,\n' +
138-
' func: \n' +
139-
' [ { a: \n' +
138+
' func:\n' +
139+
' [ { a:\n' +
140140
' { [Function: a]\n' +
141141
' [length]: 0,\n' +
142142
' [name]: \'a\',\n' +
@@ -145,9 +145,9 @@ assert.strictEqual(
145145
assert.strictEqual(
146146
util.format('%o', nestedObj),
147147
'{ foo: \'bar\',\n' +
148-
' foobar: \n' +
148+
' foobar:\n' +
149149
' { foo: \'bar\',\n' +
150-
' func: \n' +
150+
' func:\n' +
151151
' { [Function: func]\n' +
152152
' [length]: 0,\n' +
153153
' [name]: \'func\',\n' +
@@ -156,14 +156,14 @@ assert.strictEqual(
156156
util.format('%o %o', obj, obj),
157157
'{ foo: \'bar\',\n' +
158158
' foobar: 1,\n' +
159-
' func: \n' +
159+
' func:\n' +
160160
' { [Function: func]\n' +
161161
' [length]: 0,\n' +
162162
' [name]: \'func\',\n' +
163163
' [prototype]: func { [constructor]: [Circular] } } }' +
164164
' { foo: \'bar\',\n' +
165165
' foobar: 1,\n' +
166-
' func: \n' +
166+
' func:\n' +
167167
' { [Function: func]\n' +
168168
' [length]: 0,\n' +
169169
' [name]: \'func\',\n' +
@@ -172,7 +172,7 @@ assert.strictEqual(
172172
util.format('%o %o', obj),
173173
'{ foo: \'bar\',\n' +
174174
' foobar: 1,\n' +
175-
' func: \n' +
175+
' func:\n' +
176176
' { [Function: func]\n' +
177177
' [length]: 0,\n' +
178178
' [name]: \'func\',\n' +

‎test/parallel/test-util-inspect.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ assert.strictEqual(util.inspect(Object.create(Date.prototype)), 'Date {}');
571571
{
572572
const x = { [util.inspect.custom]: util.inspect };
573573
assert(util.inspect(x).includes(
574-
'[Symbol(util.inspect.custom)]: \n { [Function: inspect]'));
574+
'[Symbol(util.inspect.custom)]:\n { [Function: inspect]'));
575575
}
576576

577577
// `util.inspect` should display the escaped value of a key.
@@ -1188,7 +1188,7 @@ util.inspect(process);
11881188

11891189
let out = util.inspect(o, { compact: true, depth: 5, breakLength: 80 });
11901190
let expect = [
1191-
'{ a: ',
1191+
'{ a:',
11921192
' [ 1,',
11931193
' 2,',
11941194
" [ [ 'Lorem ipsum dolor\\nsit amet,\\tconsectetur adipiscing elit, " +

‎test/parallel/test-whatwg-url-inspect.js‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const url = new URL('https://username:password@host.name:8080/path/name/?que=ry#
1616
assert.strictEqual(
1717
util.inspect(url),
1818
`URL {
19-
href: 'https://username:password@host.name:8080/path/name/?que=ry#hash',
19+
href:
20+
'https://username:password@host.name:8080/path/name/?que=ry#hash',
2021
origin: 'https://host.name:8080',
2122
protocol: 'https:',
2223
username: 'username',
@@ -32,7 +33,8 @@ assert.strictEqual(
3233
assert.strictEqual(
3334
util.inspect(url, { showHidden: true }),
3435
`URL {
35-
href: 'https://username:password@host.name:8080/path/name/?que=ry#hash',
36+
href:
37+
'https://username:password@host.name:8080/path/name/?que=ry#hash',
3638
origin: 'https://host.name:8080',
3739
protocol: 'https:',
3840
username: 'username',
@@ -46,7 +48,7 @@ assert.strictEqual(
4648
hash: '#hash',
4749
cannotBeBase: false,
4850
special: true,
49-
[Symbol(context)]:\x20
51+
[Symbol(context)]:
5052
URLContext {
5153
flags: 2032,
5254
scheme: 'https:',

0 commit comments

Comments
 (0)