Skip to content

Commit

Permalink
util: use minimal object inspection with %s specifier
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
BridgeAR committed Apr 4, 2019
1 parent adbcda1 commit a9bf665
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 13 deletions.
20 changes: 11 additions & 9 deletions doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-http-response-statuscode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ common.expectsError(function changeDefaultEncodingToInvalidValue() {
}, {
type: TypeError,
code: 'ERR_UNKNOWN_ENCODING',
message: 'Unknown encoding: [object Object]'
message: 'Unknown encoding: {}'
});

(function checkVairableCaseEncoding() {
Expand Down
14 changes: 14 additions & 0 deletions test/parallel/test-util-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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.