Browse Source

util: show meaningful values for boxed primitives

Before, `new String('foo')` would be inspected as `"{}"` which
is simply not very helpful. Now, a more meaningful
`"[String: 'foo']"` result will be returned from `util.inspect()`.

Boxed String, Boolean, and Number types are all supported.

Closes #7047
v0.11.12-release
Nathan Rajlich 11 years ago
committed by Fedor Indutny
parent
commit
8874a31748
  1. 62
      lib/util.js
  2. 22
      test/simple/test-util-inspect.js

62
lib/util.js

@ -239,6 +239,28 @@ function formatValue(ctx, value, recurseTimes) {
keys = Object.getOwnPropertyNames(value); keys = Object.getOwnPropertyNames(value);
} }
// This could be a boxed primitive (new String(), etc.), check valueOf()
// NOTE: Avoid calling `valueOf` on `Date` instance because it will return
// a number which, when object has some additional user-stored `keys`,
// will be printed out.
var formatted;
var raw = value;
try {
// the .valueOf() call can fail for a multitude of reasons
if (!isDate(value))
raw = value.valueOf();
} catch (e) {
// ignore...
}
if (isString(raw)) {
// for boxed Strings, we have to remove the 0-n indexed entries,
// since they just noisey up the output and are redundant
keys = keys.filter(function(key) {
return !(key >= 0 && key < raw.length);
});
}
// Some type of object without properties can be shortcutted. // Some type of object without properties can be shortcutted.
if (keys.length === 0) { if (keys.length === 0) {
if (isFunction(value)) { if (isFunction(value)) {
@ -254,6 +276,19 @@ function formatValue(ctx, value, recurseTimes) {
if (isError(value)) { if (isError(value)) {
return formatError(value); return formatError(value);
} }
// now check the `raw` value to handle boxed primitives
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[String: ' + formatted + ']', 'string');
}
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Number: ' + formatted + ']', 'number');
}
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Boolean: ' + formatted + ']', 'boolean');
}
} }
var base = '', array = false, braces = ['{', '}']; var base = '', array = false, braces = ['{', '}'];
@ -285,6 +320,24 @@ function formatValue(ctx, value, recurseTimes) {
base = ' ' + formatError(value); base = ' ' + formatError(value);
} }
// Make boxed primitive Strings look like such
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[String: ' + formatted + ']';
}
// Make boxed primitive Numbers look like such
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Number: ' + formatted + ']';
}
// Make boxed primitive Booleans look like such
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Boolean: ' + formatted + ']';
}
if (keys.length === 0 && (!array || value.length == 0)) { if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1]; return braces[0] + base + braces[1];
} }
@ -338,6 +391,15 @@ function formatPrimitive(ctx, value) {
} }
function formatPrimitiveNoColor(ctx, value) {
var stylize = ctx.stylize;
ctx.stylize = stylizeNoColor;
var str = formatPrimitive(ctx, value);
ctx.stylize = stylize;
return str;
}
function formatError(value) { function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']'; return '[' + Error.prototype.toString.call(value) + ']';
} }

22
test/simple/test-util-inspect.js

@ -213,3 +213,25 @@ test_lines({
very_long_key: 'very_long_value', very_long_key: 'very_long_value',
even_longer_key: ['with even longer value in array'] even_longer_key: ['with even longer value in array']
}); });
// test boxed primitives output the correct values
assert.equal(util.inspect(new String('test')), '[String: \'test\']');
assert.equal(util.inspect(new Boolean(false)), '[Boolean: false]');
assert.equal(util.inspect(new Boolean(true)), '[Boolean: true]');
assert.equal(util.inspect(new Number(0)), '[Number: 0]');
assert.equal(util.inspect(new Number(-0)), '[Number: -0]');
assert.equal(util.inspect(new Number(-1.1)), '[Number: -1.1]');
assert.equal(util.inspect(new Number(13.37)), '[Number: 13.37]');
// test boxed primitives with own properties
var str = new String('baz');
str.foo = 'bar';
assert.equal(util.inspect(str), '{ [String: \'baz\'] foo: \'bar\' }');
var bool = new Boolean(true);
bool.foo = 'bar';
assert.equal(util.inspect(bool), '{ [Boolean: true] foo: \'bar\' }');
var num = new Number(13.37);
num.foo = 'bar';
assert.equal(util.inspect(num), '{ [Number: 13.37] foo: \'bar\' }');

Loading…
Cancel
Save