Skip to content

Commit

Permalink
fix: error stack missing message
Browse files Browse the repository at this point in the history
  • Loading branch information
adoyle-h committed Jun 22, 2016
1 parent 9c486ae commit 1827cd9
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 46 deletions.
69 changes: 43 additions & 26 deletions src/base_error.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,56 @@

var util = require('./util');

/**
* @private
*/
function getBaseErrorStack() {
var stackObj = this;
if (!stackObj.cache) {
stackObj.cache = stackObj.stack;
}
return stackObj.cache;
}

/**
* @private
*
* @method getBaseErrorStackFunc
* @param {Object} error
* @param {String} error.stack
* @param {Object} stackObj
* @param {String} [stackObj.stack]
* @param {String} [stackObj.stack='']
* @param {Object} [preError]
* @param {String} [preError.stack='']
* @return {Function}
*/
function getBaseErrorStackFunc(error, stackObj) {
function getBaseErrorStackFunc(stackObj, preError) {
var cache;
return function() {
var baseError = this;
if (!cache) {
cache = (stackObj.stack || '') + this.ERROR_STACK_SEPARATOR + error.stack;
if (preError) {
cache = util.get(stackObj, 'stack', '') +
baseError.ERROR_STACK_SEPARATOR +
util.get(preError, 'stack', '');
} else {
cache = util.get(stackObj, 'stack', '');
}
}
return cache;
};
}


/**
* Assign stack property to BaseError instance.
*
* @private
*
* @side_effect baseError
* @method assignStack
* @param {BaseError} baseError
* @param {Object} stackObj
* @param {String} [stackObj.stack='']
* @param {Object} [preError]
* @param {String} [preError.stack='']
* @return {undefined}
*/
function assignStack(baseError, stackObj, preError) {
Object.defineProperty(baseError, 'stack', {
configurable: true,
enumerable: true,
get: getBaseErrorStackFunc(stackObj, preError),
});
}

/**
* You should define your error class which inherits the `BaseError` class
*
Expand Down Expand Up @@ -93,13 +112,10 @@ function BaseError() {
}
}


if (self.captureStackTrace) {
Error.captureStackTrace(stackObj, self.constructor);
Object.defineProperty(self, 'stack', {
configurable: true,
enumerable: true,
get: getBaseErrorStack.bind(stackObj),
});
assignStack(self, stackObj);
}

if (error) {
Expand All @@ -114,14 +130,15 @@ function BaseError() {
}

if (error.stack) {
Object.defineProperty(self, 'stack', {
configurable: true,
enumerable: true,
get: getBaseErrorStackFunc(error, stackObj),
});
assignStack(self, stackObj, error);
}
}

// For stack takes with error message
// see https://github.com/nodejs/node/issues/5675#issuecomment-203966051
stackObj.name = this.name;
stackObj.message = message;

self.meta = meta;
self.message = message;
}
Expand Down
81 changes: 61 additions & 20 deletions test/cases/base_error.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

describe('#base_error', function() {
var BaseError = require('../../src/base_error');
var should = require('should');

function checkKeys(err) {
err.should.have.keys(['meta', 'message', 'stack']);
Expand All @@ -14,29 +13,35 @@ describe('#base_error', function() {
err.name.should.equal('BaseError');
err.meta.should.be.an.Object();
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + message).should.equal(0);
checkKeys(err);
});

it('new BaseError(message, param1, param2...paramN)', function() {
var targetMessage = 'hello! this a BaseError';
var err = new BaseError('%s! this a %s', 'hello', 'BaseError');
err.name.should.equal('BaseError');
err.message.should.equal('hello! this a BaseError');
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.message.should.equal(targetMessage);
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

it('new BaseError(meta, message)', function() {
var message = 'this a BaseError';
var meta = {a: 1};
var err = new BaseError(meta, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.equal(meta);
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

Expand All @@ -45,10 +50,13 @@ describe('#base_error', function() {
error.meta = {a: 1};
var message = 'this a BaseError';
var err = new BaseError(error, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual(error.meta);
err.message.should.equal(message);
err.stack.should.be.a.String();
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
err.stack.match(/\==== Pre-Error-Stack ====/g).length.should.equal(1);
checkKeys(err);
});
Expand All @@ -58,12 +66,14 @@ describe('#base_error', function() {
var error = new Error(_message);
error.meta = {a: 3, b: 2};
var message = 'this a BaseError';
var targetMessage = message + ' && ' + _message;
var meta = {a: 1};
var err = new BaseError(error, meta, message);
err.name.should.equal('BaseError');
err.meta.should.deepEqual({a: 1, b: 2});
err.message.should.equal(message + ' && ' + _message);
err.message.should.equal(targetMessage);
err.stack.should.be.a.String();
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
err.stack.match(/\==== Pre-Error-Stack ====/g).length.should.equal(1);
checkKeys(err);
});
Expand All @@ -73,12 +83,14 @@ describe('#base_error', function() {
var error = new Error(_message);
error.meta = {a: 3, b: 2};
var message = 'this a BaseError';
var targetMessage = message + ' && ' + _message;
var meta = {a: 1};
var err = new BaseError(meta, error, message);
err.name.should.equal('BaseError');
err.meta.should.deepEqual({a: 1, b: 2});
err.message.should.equal(message + ' && ' + _message);
err.message.should.equal(targetMessage);
err.stack.should.be.a.String();
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
err.stack.match(/\==== Pre-Error-Stack ====/g).length.should.equal(1);
checkKeys(err);
});
Expand All @@ -90,10 +102,13 @@ describe('#base_error', function() {
var message = '%s! this a %s';
var meta = {a: 1};
var err = new BaseError(meta, error, message, 'hello', 'BaseError');
var targetMessage = 'hello! this a BaseError && ' + _message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual({a: 1, b: 2});
err.message.should.equal('hello! this a BaseError && ' + _message);
err.message.should.equal(targetMessage);
err.stack.should.be.a.String();
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
err.stack.match(/\==== Pre-Error-Stack ====/g).length.should.equal(1);
checkKeys(err);
});
Expand All @@ -102,35 +117,44 @@ describe('#base_error', function() {
var error;
var message = 'this a BaseError';
var err = new BaseError(error, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual({});
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

it('new BaseError(null, message) should equal new BaseError(message)', function() {
var error = null;
var message = 'this a BaseError';
var err = new BaseError(error, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual({});
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

it('new BaseError(undefined, undefined, message) should equal new BaseError(message)', function() {
var error, meta;
var message = 'this a BaseError';
var err = new BaseError(error, meta, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual({});
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

Expand All @@ -139,11 +163,14 @@ describe('#base_error', function() {
var meta;
var message = 'this a BaseError';
var err = new BaseError(error, meta, message);
var targetMessage = message;

err.name.should.equal('BaseError');
err.meta.should.deepEqual({});
err.message.should.equal(message);
err.stack.should.be.a.String();
should.not.exist(err.stack.match(/\==== Pre-Error-Stack ====/g));
err.stack.should.be.a.String()
.and.not.containEql(/\==== Pre-Error-Stack ====/g);
err.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
checkKeys(err);
});

Expand Down Expand Up @@ -185,10 +212,24 @@ describe('#base_error', function() {
var secondErr = new BaseError(firstErr, secondMeta, 'the second error');
var thirdMeta = {b: '2', c: [3], d: true};
var thirdErr = new BaseError(thirdMeta, secondErr, '%s is %s', 'something', 'wrong');
thirdErr.message.should.equal('something is wrong && the second error && the first error');
var targetMessage = 'something is wrong && the second error && the first error';

thirdErr.message.should.equal(targetMessage);
thirdErr.meta.should.deepEqual({a: 1, b: '2', c: [3], d: true});
thirdErr.stack.should.be.a.String();
thirdErr.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
thirdErr.stack.match(/\==== Pre-Error-Stack ====/g).length.should.equal(2);
});

it('show pre error message if current error without any message', function() {
var firstErr = new Error('the first error');
var secondMeta = {a: 1, b: 3};
var secondErr = new BaseError(firstErr, secondMeta);
var targetMessage = 'the first error';

secondErr.message.should.equal(targetMessage);
secondErr.stack.should.be.a.String();
secondErr.stack.indexOf('BaseError: ' + targetMessage).should.equal(0);
});
});
});

0 comments on commit 1827cd9

Please sign in to comment.