Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
util: change %d to format a integer, add %i and %f
This change brings formatting specifiers available in `util.format` and
consequently, `console.*` closer to what is supported in all major
browsers. There is a breaking change with the `%d` specifier which
previously served a double purpose of formatting both integer and
floats. With this change, it will format only as integer.

- `%d` is being changed to format only as integer.
- `%i` is introduced as an alias to `%d`.
- `%f` is introduced to format floating point values.

When updating code, all instances of `%d` format strings that
were supplied with floats should be changed to the `%f` format string.

Fixes: #10292
  • Loading branch information
silverwind committed Mar 25, 2017
commit 04143cf603b9bfcc0d8182008837022f1d43c990
3 changes: 2 additions & 1 deletion doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ Each placeholder token is replaced with the converted value from the
corresponding argument. Supported placeholders are:

* `%s` - String.
* `%d` - Number (both integer and float).
* `%d` or `%i` - Integer.
* `%f` - Floating point value.
* `%j` - JSON. Replaced with the string `'[Circular]'` if the argument
contains circular references.
* `%%` - single percent sign (`'%'`). This does not consume an argument.
Expand Down
11 changes: 10 additions & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,20 @@ exports.format = function(f) {
if (f.charCodeAt(i) === 37/*'%'*/ && i + 1 < f.length) {
switch (f.charCodeAt(i + 1)) {
case 100: // 'd'
case 105: // 'i'
if (a >= argLen)
break;
if (lastPos < i)
str += f.slice(lastPos, i);
str += Number(arguments[a++]);
str += parseInt(arguments[a++]);
lastPos = i = i + 2;
continue;
case 102: // 'f'
if (a >= argLen)
break;
if (lastPos < i)
str += f.slice(lastPos, i);
str += parseFloat(arguments[a++]);
lastPos = i = i + 2;
continue;
case 106: // 'j'
Expand Down
44 changes: 35 additions & 9 deletions test/parallel/test-util-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,49 @@ assert.throws(function() {
util.format('%d', symbol);
}, TypeError);

// Integer format specifier
assert.strictEqual(util.format('%d'), '%d');
assert.strictEqual(util.format('%d', 42.0), '42');
assert.strictEqual(util.format('%d', 42), '42');
assert.strictEqual(util.format('%s', 42), '42');
assert.strictEqual(util.format('%j', 42), '42');

assert.strictEqual(util.format('%d', '42.0'), '42');
assert.strictEqual(util.format('%d', '42'), '42');
assert.strictEqual(util.format('%s', '42'), '42');
assert.strictEqual(util.format('%j', '42'), '"42"');
assert.strictEqual(util.format('%d', '42.0'), '42');
assert.strictEqual(util.format('%d', 1.5), '1');
assert.strictEqual(util.format('%d', -0.5), '0');
assert.strictEqual(util.format('%d', ''), 'NaN');
assert.strictEqual(util.format('%i'), '%i');
assert.strictEqual(util.format('%i', 42.0), '42');
assert.strictEqual(util.format('%i', 42), '42');
assert.strictEqual(util.format('%i', '42'), '42');
assert.strictEqual(util.format('%i', '42.0'), '42');
assert.strictEqual(util.format('%i', 1.5), '1');
assert.strictEqual(util.format('%i', -0.5), '0');
assert.strictEqual(util.format('%i', ''), 'NaN');

assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
// Float format specifier
assert.strictEqual(util.format('%f'), '%f');
assert.strictEqual(util.format('%f', 42.0), '42');
assert.strictEqual(util.format('%f', 42), '42');
assert.strictEqual(util.format('%f', '42'), '42');
assert.strictEqual(util.format('%f', '42.0'), '42');
assert.strictEqual(util.format('%f', 1.5), '1.5');
assert.strictEqual(util.format('%f', -0.5), '-0.5');
assert.strictEqual(util.format('%f', Math.PI), '3.141592653589793');
assert.strictEqual(util.format('%f', ''), 'NaN');

// String format specifier
assert.strictEqual(util.format('%s'), '%s');
assert.strictEqual(util.format('%s', undefined), 'undefined');
assert.strictEqual(util.format('%s', 'foo'), 'foo');
assert.strictEqual(util.format('%s', 42), '42');
assert.strictEqual(util.format('%s', '42'), '42');

// JSON format specifier
assert.strictEqual(util.format('%j'), '%j');
assert.strictEqual(util.format('%j', 42), '42');
assert.strictEqual(util.format('%j', '42'), '"42"');

// Various format specifiers
assert.strictEqual(util.format('%%s%s', 'foo'), '%sfoo');
assert.strictEqual(util.format('%s:%s'), '%s:%s');
assert.strictEqual(util.format('%s:%s', undefined), 'undefined:%s');
assert.strictEqual(util.format('%s:%s', 'foo'), 'foo:%s');
Expand All @@ -71,11 +99,9 @@ assert.strictEqual(util.format('%s:%s', 'foo', 'bar', 'baz'), 'foo:bar baz');
assert.strictEqual(util.format('%%%s%%', 'hi'), '%hi%');
assert.strictEqual(util.format('%%%s%%%%', 'hi'), '%hi%%');
assert.strictEqual(util.format('%sbc%%def', 'a'), 'abc%def');

assert.strictEqual(util.format('%d:%d', 12, 30), '12:30');
assert.strictEqual(util.format('%d:%d', 12), '12:%d');
assert.strictEqual(util.format('%d:%d'), '%d:%d');

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');
Expand Down