From e2f47f5698c9eff9b160572811e3804482193dfe Mon Sep 17 00:00:00 2001 From: Mudit Ameta Date: Fri, 8 Jan 2016 15:55:14 +0530 Subject: [PATCH] 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: nodejs#4452 PR-URL: https://github.com/nodejs/node/pull/4582 Reviewed-By: Ben Noordhuis Reviewed-By: Trevor Norris Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- lib/util.js | 2 +- test/parallel/test-util-format.js | 23 ++++++++++++++++++----- test/parallel/test-util-inspect.js | 30 ++++++++++++++++++++++-------- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/lib/util.js b/lib/util.js index b1a6b049e5..50cc5bc5b4 100644 --- a/lib/util.js +++ b/lib/util.js @@ -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) + ']'; } diff --git a/test/parallel/test-util-format.js b/test/parallel/test-util-format.js index 00028ddbb7..92c448578b 100644 --- a/test/parallel/test-util-format.js +++ b/test/parallel/test-util-format.js @@ -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(''), ''); @@ -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'); +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]'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 29ab8f7310..5eaea4de1e 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -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'); @@ -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: