Skip to content
Permalink
Browse files

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 <targos@protonmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
  • Loading branch information...
BridgeAR committed Mar 26, 2019
1 parent adbcda1 commit a9bf6652b5353f2098d4c0cd0eb77d17e02e164d
@@ -220,15 +220,17 @@ as a `printf`-like format string which can contain zero or more format
specifiers. Each specifier is replaced with the converted value from the
corresponding argument. Supported specifiers are:

* `%s` - `String`.
* `%d` - `Number` (integer or floating point value) or `BigInt`.
* `%i` - Integer or `BigInt`.
* `%f` - Floating point value.
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument
contains circular references.
* `%o` - `Object`. A string representation of an object
with generic JavaScript object formatting.
Similar to `util.inspect()` with options
* `%s` - `String` will be used to convert all values except `BigInt` and
`Object`. `BigInt` values will be represented with an `n` and Objects are
inspected using `util.inspect()` with options
`{ depth: 0, colors: false, compact: 3 }`.
* `%d` - `Number` will be used to convert all values except `BigInt`.
* `%i` - `parseInt(value, 10)` is used for all values except `BigInt`.
* `%f` - `parseFloat(value)` is used for all values.
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument contains
circular references.
* `%o` - `Object`. A string representation of an object with generic JavaScript
object formatting. Similar to `util.inspect()` with options
`{ showHidden: true, showProxy: true }`. This will show the full object
including non-enumerable properties and proxies.
* `%O` - `Object`. A string representation of an object with generic JavaScript
@@ -1446,7 +1446,20 @@ function formatWithOptions(inspectOptions, ...args) {
if (a + 1 !== args.length) {
switch (nextChar) {
case 115: // 's'
tempStr = String(args[++a]);
const tempArg = args[++a];
if (typeof tempArg === 'object' && tempArg !== null) {
tempStr = inspect(tempArg, {
...inspectOptions,
compact: 3,
colors: false,
depth: 0
});
// eslint-disable-next-line valid-typeof
} else if (typeof tempArg === 'bigint') {
tempStr = `${tempArg}n`;
} else {
tempStr = String(tempArg);
}
break;
case 106: // 'j'
tempStr = tryStringify(args[++a]);
@@ -29,7 +29,7 @@ const server = http.Server(common.mustCall(function(req, res) {
test(res, NaN, 'NaN');
break;
case 3:
test(res, {}, '[object Object]');
test(res, {}, '{}');
break;
case 4:
test(res, 99, '99');
@@ -47,7 +47,7 @@ const server = http.Server(common.mustCall(function(req, res) {
test(res, true, 'true');
break;
case 9:
test(res, [], '');
test(res, [], '[]');
break;
case 10:
test(res, 'this is not valid', 'this is not valid');
@@ -63,7 +63,7 @@ common.expectsError(function changeDefaultEncodingToInvalidValue() {
}, {
type: TypeError,
code: 'ERR_UNKNOWN_ENCODING',
message: 'Unknown encoding: [object Object]'
message: 'Unknown encoding: {}'
});

(function checkVairableCaseEncoding() {
@@ -123,11 +123,17 @@ assert.strictEqual(util.format('%f %f', 42), '42 %f');
// String format specifier
assert.strictEqual(util.format('%s'), '%s');
assert.strictEqual(util.format('%s', undefined), 'undefined');
assert.strictEqual(util.format('%s', null), 'null');
assert.strictEqual(util.format('%s', 'foo'), 'foo');
assert.strictEqual(util.format('%s', 42), '42');
assert.strictEqual(util.format('%s', '42'), '42');
assert.strictEqual(util.format('%s %s', 42, 43), '42 43');
assert.strictEqual(util.format('%s %s', 42), '42 %s');
assert.strictEqual(util.format('%s', 42n), '42n');
assert.strictEqual(util.format('%s', Symbol('foo')), 'Symbol(foo)');
assert.strictEqual(util.format('%s', true), 'true');
assert.strictEqual(util.format('%s', { a: [1, 2, 3] }), '{ a: [Array] }');
assert.strictEqual(util.format('%s', () => 5), '() => 5');

// JSON format specifier
assert.strictEqual(util.format('%j'), '%j');
@@ -346,3 +352,11 @@ assert.strictEqual(
util.format(new SharedArrayBuffer(4)),
'SharedArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }'
);

assert.strictEqual(
util.formatWithOptions(
{ colors: true, compact: 3 },
'%s', [ 1, { a: true }]
),
'[ 1, [Object] ]'
);

0 comments on commit a9bf665

Please sign in to comment.
You can’t perform that action at this time.