Skip to content

Commit a9bf665

Browse files
committed
util: use minimal object inspection with %s specifier
This improves `util.format()` by returning more meaningful results when using `%s` as specifier and any object as value. Besides that `BigInt` will also be represented with an `n` at the end to indicate that it's of type `BigInt`. PR-URL: #26927 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Yongsheng Zhang <[email protected]>
1 parent adbcda1 commit a9bf665

File tree

5 files changed

+42
-13
lines changed

5 files changed

+42
-13
lines changed

doc/api/util.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -220,15 +220,17 @@ as a `printf`-like format string which can contain zero or more format
220220
specifiers. Each specifier is replaced with the converted value from the
221221
corresponding argument. Supported specifiers are:
222222

223-
* `%s` - `String`.
224-
* `%d` - `Number` (integer or floating point value) or `BigInt`.
225-
* `%i` - Integer or `BigInt`.
226-
* `%f` - Floating point value.
227-
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument
228-
contains circular references.
229-
* `%o` - `Object`. A string representation of an object
230-
with generic JavaScript object formatting.
231-
Similar to `util.inspect()` with options
223+
* `%s` - `String` will be used to convert all values except `BigInt` and
224+
`Object`. `BigInt` values will be represented with an `n` and Objects are
225+
inspected using `util.inspect()` with options
226+
`{ depth: 0, colors: false, compact: 3 }`.
227+
* `%d` - `Number` will be used to convert all values except `BigInt`.
228+
* `%i` - `parseInt(value, 10)` is used for all values except `BigInt`.
229+
* `%f` - `parseFloat(value)` is used for all values.
230+
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument contains
231+
circular references.
232+
* `%o` - `Object`. A string representation of an object with generic JavaScript
233+
object formatting. Similar to `util.inspect()` with options
232234
`{ showHidden: true, showProxy: true }`. This will show the full object
233235
including non-enumerable properties and proxies.
234236
* `%O` - `Object`. A string representation of an object with generic JavaScript

lib/internal/util/inspect.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,20 @@ function formatWithOptions(inspectOptions, ...args) {
14461446
if (a + 1 !== args.length) {
14471447
switch (nextChar) {
14481448
case 115: // 's'
1449-
tempStr = String(args[++a]);
1449+
const tempArg = args[++a];
1450+
if (typeof tempArg === 'object' && tempArg !== null) {
1451+
tempStr = inspect(tempArg, {
1452+
...inspectOptions,
1453+
compact: 3,
1454+
colors: false,
1455+
depth: 0
1456+
});
1457+
// eslint-disable-next-line valid-typeof
1458+
} else if (typeof tempArg === 'bigint') {
1459+
tempStr = `${tempArg}n`;
1460+
} else {
1461+
tempStr = String(tempArg);
1462+
}
14501463
break;
14511464
case 106: // 'j'
14521465
tempStr = tryStringify(args[++a]);

test/parallel/test-http-response-statuscode.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const server = http.Server(common.mustCall(function(req, res) {
2929
test(res, NaN, 'NaN');
3030
break;
3131
case 3:
32-
test(res, {}, '[object Object]');
32+
test(res, {}, '{}');
3333
break;
3434
case 4:
3535
test(res, 99, '99');
@@ -47,7 +47,7 @@ const server = http.Server(common.mustCall(function(req, res) {
4747
test(res, true, 'true');
4848
break;
4949
case 9:
50-
test(res, [], '');
50+
test(res, [], '[]');
5151
break;
5252
case 10:
5353
test(res, 'this is not valid', 'this is not valid');

test/parallel/test-stream-writable-change-default-encoding.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ common.expectsError(function changeDefaultEncodingToInvalidValue() {
6363
}, {
6464
type: TypeError,
6565
code: 'ERR_UNKNOWN_ENCODING',
66-
message: 'Unknown encoding: [object Object]'
66+
message: 'Unknown encoding: {}'
6767
});
6868

6969
(function checkVairableCaseEncoding() {

test/parallel/test-util-format.js

+14
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,17 @@ assert.strictEqual(util.format('%f %f', 42), '42 %f');
123123
// String format specifier
124124
assert.strictEqual(util.format('%s'), '%s');
125125
assert.strictEqual(util.format('%s', undefined), 'undefined');
126+
assert.strictEqual(util.format('%s', null), 'null');
126127
assert.strictEqual(util.format('%s', 'foo'), 'foo');
127128
assert.strictEqual(util.format('%s', 42), '42');
128129
assert.strictEqual(util.format('%s', '42'), '42');
129130
assert.strictEqual(util.format('%s %s', 42, 43), '42 43');
130131
assert.strictEqual(util.format('%s %s', 42), '42 %s');
132+
assert.strictEqual(util.format('%s', 42n), '42n');
133+
assert.strictEqual(util.format('%s', Symbol('foo')), 'Symbol(foo)');
134+
assert.strictEqual(util.format('%s', true), 'true');
135+
assert.strictEqual(util.format('%s', { a: [1, 2, 3] }), '{ a: [Array] }');
136+
assert.strictEqual(util.format('%s', () => 5), '() => 5');
131137

132138
// JSON format specifier
133139
assert.strictEqual(util.format('%j'), '%j');
@@ -346,3 +352,11 @@ assert.strictEqual(
346352
util.format(new SharedArrayBuffer(4)),
347353
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
348354
);
355+
356+
assert.strictEqual(
357+
util.formatWithOptions(
358+
{ colors: true, compact: 3 },
359+
'%s', [ 1, { a: true }]
360+
),
361+
'[ 1, [Object] ]'
362+
);

0 commit comments

Comments
 (0)