util: implement %o and %O as formatting specifiers
Implementing the %o and %O formatting specifiers for util.format. Based on discussion in issue, this specifier should just call util.inspect to format the value. PR-URL: https://github.com/nodejs/node/pull/14558 Fixes: https://github.com/nodejs/node/issues/14545 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Yuta Hiroto <hello@about-hiroppy.com>
This commit is contained in:
parent
753b68f9d8
commit
211df3fe8c
@ -167,6 +167,14 @@ corresponding argument. Supported placeholders are:
|
||||
* `%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 `{ showHidden: true, depth: 4, showProxy: true }`.
|
||||
This will show the full object including non-enumerable symbols and properties.
|
||||
* `%O` - Object. A string representation of an object
|
||||
with generic JavaScript object formatting.
|
||||
Similar to `util.inspect()` without options.
|
||||
This will show the full object not including non-enumerable symbols and properties.
|
||||
* `%%` - single percent sign (`'%'`). This does not consume an argument.
|
||||
|
||||
If the placeholder does not have a corresponding argument, the placeholder is
|
||||
|
11
lib/util.js
11
lib/util.js
@ -137,6 +137,17 @@ function format(f) {
|
||||
str += f.slice(lastPos, i);
|
||||
str += String(arguments[a++]);
|
||||
break;
|
||||
case 79: // 'O'
|
||||
if (lastPos < i)
|
||||
str += f.slice(lastPos, i);
|
||||
str += inspect(arguments[a++]);
|
||||
break;
|
||||
case 111: // 'o'
|
||||
if (lastPos < i)
|
||||
str += f.slice(lastPos, i);
|
||||
str += inspect(arguments[a++],
|
||||
{ showHidden: true, depth: 4, showProxy: true });
|
||||
break;
|
||||
case 37: // '%'
|
||||
if (lastPos < i)
|
||||
str += f.slice(lastPos, i);
|
||||
|
@ -101,6 +101,84 @@ assert.strictEqual(util.format('%j', '42'), '"42"');
|
||||
assert.strictEqual(util.format('%j %j', 42, 43), '42 43');
|
||||
assert.strictEqual(util.format('%j %j', 42), '42 %j');
|
||||
|
||||
// Object format specifier
|
||||
const obj = {
|
||||
foo: 'bar',
|
||||
foobar: 1,
|
||||
func: function() {}
|
||||
};
|
||||
const nestedObj = {
|
||||
foo: 'bar',
|
||||
foobar: {
|
||||
foo: 'bar',
|
||||
func: function() {}
|
||||
}
|
||||
};
|
||||
assert.strictEqual(util.format('%o'), '%o');
|
||||
assert.strictEqual(util.format('%o', 42), '42');
|
||||
assert.strictEqual(util.format('%o', 'foo'), '\'foo\'');
|
||||
assert.strictEqual(
|
||||
util.format('%o', obj),
|
||||
'{ foo: \'bar\',\n' +
|
||||
' foobar: 1,\n' +
|
||||
' func: \n' +
|
||||
' { [Function: func]\n' +
|
||||
' [length]: 0,\n' +
|
||||
' [name]: \'func\',\n' +
|
||||
' [prototype]: func { [constructor]: [Circular] } } }');
|
||||
assert.strictEqual(
|
||||
util.format('%o', nestedObj),
|
||||
'{ foo: \'bar\',\n' +
|
||||
' foobar: \n' +
|
||||
' { foo: \'bar\',\n' +
|
||||
' func: \n' +
|
||||
' { [Function: func]\n' +
|
||||
' [length]: 0,\n' +
|
||||
' [name]: \'func\',\n' +
|
||||
' [prototype]: func { [constructor]: [Circular] } } } }');
|
||||
assert.strictEqual(
|
||||
util.format('%o %o', obj, obj),
|
||||
'{ foo: \'bar\',\n' +
|
||||
' foobar: 1,\n' +
|
||||
' func: \n' +
|
||||
' { [Function: func]\n' +
|
||||
' [length]: 0,\n' +
|
||||
' [name]: \'func\',\n' +
|
||||
' [prototype]: func { [constructor]: [Circular] } } }' +
|
||||
' { foo: \'bar\',\n' +
|
||||
' foobar: 1,\n' +
|
||||
' func: \n' +
|
||||
' { [Function: func]\n' +
|
||||
' [length]: 0,\n' +
|
||||
' [name]: \'func\',\n' +
|
||||
' [prototype]: func { [constructor]: [Circular] } } }');
|
||||
assert.strictEqual(
|
||||
util.format('%o %o', obj),
|
||||
'{ foo: \'bar\',\n' +
|
||||
' foobar: 1,\n' +
|
||||
' func: \n' +
|
||||
' { [Function: func]\n' +
|
||||
' [length]: 0,\n' +
|
||||
' [name]: \'func\',\n' +
|
||||
' [prototype]: func { [constructor]: [Circular] } } } %o');
|
||||
|
||||
assert.strictEqual(util.format('%O'), '%O');
|
||||
assert.strictEqual(util.format('%O', 42), '42');
|
||||
assert.strictEqual(util.format('%O', 'foo'), '\'foo\'');
|
||||
assert.strictEqual(
|
||||
util.format('%O', obj),
|
||||
'{ foo: \'bar\', foobar: 1, func: [Function: func] }');
|
||||
assert.strictEqual(
|
||||
util.format('%O', nestedObj),
|
||||
'{ foo: \'bar\', foobar: { foo: \'bar\', func: [Function: func] } }');
|
||||
assert.strictEqual(
|
||||
util.format('%O %O', obj, obj),
|
||||
'{ foo: \'bar\', foobar: 1, func: [Function: func] } ' +
|
||||
'{ foo: \'bar\', foobar: 1, func: [Function: func] }');
|
||||
assert.strictEqual(
|
||||
util.format('%O %O', obj),
|
||||
'{ foo: \'bar\', foobar: 1, func: [Function: func] } %O');
|
||||
|
||||
// Various format specifiers
|
||||
assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
|
||||
assert.strictEqual(util.format('%s:%s'), '%s:%s');
|
||||
@ -125,6 +203,10 @@ assert.strictEqual(util.format('%f:%f'), '%f:%f');
|
||||
assert.strictEqual(util.format('o: %j, a: %j', {}, []), 'o: {}, a: []');
|
||||
assert.strictEqual(util.format('o: %j, a: %j', {}), 'o: {}, a: %j');
|
||||
assert.strictEqual(util.format('o: %j, a: %j'), 'o: %j, a: %j');
|
||||
assert.strictEqual(util.format('o: %o, a: %O', {}, []), 'o: {}, a: []');
|
||||
assert.strictEqual(util.format('o: %o, a: %o', {}), 'o: {}, a: %o');
|
||||
assert.strictEqual(util.format('o: %O, a: %O'), 'o: %O, a: %O');
|
||||
|
||||
|
||||
// Invalid format specifiers
|
||||
assert.strictEqual(util.format('a% b', 'x'), 'a% b x');
|
||||
|
Loading…
x
Reference in New Issue
Block a user