Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
util: Change how Error objects are formatted
Previously, Error objects were formatted as the result of a `toString`
call bounded by square brackets. They are now formatted as the stack
trace for the given error object. The intention initially was to emulate
how browsers do `console.error` but since that would also impact
`console.warn`, `console.log`, etc, it was decided to make the change at
`util.inspect` level which is in turn used by the `console` package.

Fixes: #4452
  • Loading branch information
zeusdeux committed Jan 8, 2016
commit 006a66a4ad0551ab7825244e9683eb747a6aa361
2 changes: 1 addition & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ function formatPrimitiveNoColor(ctx, value) {


function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
return value.stack || '[' + Error.prototype.toString.call(value) + ']';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added fallback in case the error is some custom error that isn't capturing the stack correctly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a regression test for that? EDIT: Nevermind, I see BadCustomError covers that.

}


Expand Down
23 changes: 18 additions & 5 deletions test/parallel/test-util-format.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use strict';
require('../common');
var assert = require('assert');
var util = require('util');
var symbol = Symbol('foo');
const assert = require('assert');
const util = require('util');
const symbol = Symbol('foo');

assert.equal(util.format(), '');
assert.equal(util.format(''), '');
Expand Down Expand Up @@ -55,13 +55,26 @@ assert.equal(util.format('%%%s%%%%', 'hi'), '%hi%%');
})();

// Errors
assert.equal(util.format(new Error('foo')), '[Error: foo]');
const err = new Error('foo');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're working in this file, can you change the require() statements at the top to use const as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this in both test-util-format.js and test-util-inspect.js.

assert.equal(util.format(err), err.stack);
function CustomError(msg) {
Error.call(this);
Object.defineProperty(this, 'message',
{ value: msg, enumerable: false });
Object.defineProperty(this, 'name',
{ value: 'CustomError', enumerable: false });
Error.captureStackTrace(this, CustomError);
}
util.inherits(CustomError, Error);
assert.equal(util.format(new CustomError('bar')), '[CustomError: bar]');
const customError = new CustomError('bar');
assert.equal(util.format(customError), customError.stack);
// Doesn't capture stack trace
function BadCustomError(msg) {
Error.call(this);
Object.defineProperty(this, 'message',
{ value: msg, enumerable: false });
Object.defineProperty(this, 'name',
{ value: 'BadCustomError', enumerable: false });
}
util.inherits(BadCustomError, Error);
assert.equal(util.format(new BadCustomError('foo')), '[BadCustomError: foo]');
30 changes: 22 additions & 8 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';
require('../common');
var assert = require('assert');
var util = require('util');
const assert = require('assert');
const util = require('util');
const vm = require('vm');

assert.equal(util.inspect(1), '1');
Expand Down Expand Up @@ -288,19 +288,33 @@ assert.equal(util.inspect(setter, true), '{ [b]: [Setter] }');
assert.equal(util.inspect(getterAndSetter, true), '{ [c]: [Getter/Setter] }');

// exceptions should print the error message, not '{}'
assert.equal(util.inspect(new Error()), '[Error]');
assert.equal(util.inspect(new Error('FAIL')), '[Error: FAIL]');
assert.equal(util.inspect(new TypeError('FAIL')), '[TypeError: FAIL]');
assert.equal(util.inspect(new SyntaxError('FAIL')), '[SyntaxError: FAIL]');
const errors = [];
errors.push(new Error());
errors.push(new Error('FAIL'));
errors.push(new TypeError('FAIL'));
errors.push(new SyntaxError('FAIL'));
errors.forEach(function(err) {
assert.equal(util.inspect(err), err.stack);
});
try {
undef();
} catch (e) {
assert.equal(util.inspect(e), '[ReferenceError: undef is not defined]');
assert.equal(util.inspect(e), e.stack);
}
var ex = util.inspect(new Error('FAIL'), true);
assert.ok(ex.indexOf('[Error: FAIL]') != -1);
assert.ok(ex.indexOf('Error: FAIL') != -1);
assert.ok(ex.indexOf('[stack]') != -1);
assert.ok(ex.indexOf('[message]') != -1);
// Doesn't capture stack trace
function BadCustomError(msg) {
Error.call(this);
Object.defineProperty(this, 'message',
{ value: msg, enumerable: false });
Object.defineProperty(this, 'name',
{ value: 'BadCustomError', enumerable: false });
}
util.inherits(BadCustomError, Error);
assert.equal(util.inspect(new BadCustomError('foo')), '[BadCustomError: foo]');

// GH-1941
// should not throw:
Expand Down