158 lines
3.5 KiB
JavaScript
158 lines
3.5 KiB
JavaScript
|
/*
|
||
|
* verror.js: richer JavaScript errors
|
||
|
*/
|
||
|
|
||
|
var mod_assert = require('assert');
|
||
|
var mod_util = require('util');
|
||
|
|
||
|
var mod_extsprintf = require('extsprintf');
|
||
|
|
||
|
/*
|
||
|
* Public interface
|
||
|
*/
|
||
|
exports.VError = VError;
|
||
|
exports.WError = WError;
|
||
|
exports.MultiError = MultiError;
|
||
|
|
||
|
/*
|
||
|
* Like JavaScript's built-in Error class, but supports a "cause" argument and a
|
||
|
* printf-style message. The cause argument can be null.
|
||
|
*/
|
||
|
function VError(options)
|
||
|
{
|
||
|
var args, causedBy, ctor, tailmsg;
|
||
|
|
||
|
if (options instanceof Error || typeof (options) === 'object') {
|
||
|
args = Array.prototype.slice.call(arguments, 1);
|
||
|
} else {
|
||
|
args = Array.prototype.slice.call(arguments, 0);
|
||
|
options = undefined;
|
||
|
}
|
||
|
|
||
|
tailmsg = args.length > 0 ?
|
||
|
mod_extsprintf.sprintf.apply(null, args) : '';
|
||
|
this.jse_shortmsg = tailmsg;
|
||
|
this.jse_summary = tailmsg;
|
||
|
|
||
|
if (options) {
|
||
|
causedBy = options.cause;
|
||
|
|
||
|
if (!causedBy || !(options.cause instanceof Error))
|
||
|
causedBy = options;
|
||
|
|
||
|
if (causedBy && (causedBy instanceof Error)) {
|
||
|
this.jse_cause = causedBy;
|
||
|
this.jse_summary += ': ' + causedBy.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.message = this.jse_summary;
|
||
|
Error.call(this, this.jse_summary);
|
||
|
|
||
|
if (Error.captureStackTrace) {
|
||
|
ctor = options ? options.constructorOpt : undefined;
|
||
|
ctor = ctor || arguments.callee;
|
||
|
Error.captureStackTrace(this, ctor);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mod_util.inherits(VError, Error);
|
||
|
VError.prototype.name = 'VError';
|
||
|
|
||
|
VError.prototype.toString = function ve_toString()
|
||
|
{
|
||
|
var str = (this.hasOwnProperty('name') && this.name ||
|
||
|
this.constructor.name || this.constructor.prototype.name);
|
||
|
if (this.message)
|
||
|
str += ': ' + this.message;
|
||
|
|
||
|
return (str);
|
||
|
};
|
||
|
|
||
|
VError.prototype.cause = function ve_cause()
|
||
|
{
|
||
|
return (this.jse_cause);
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Represents a collection of errors for the purpose of consumers that generally
|
||
|
* only deal with one error. Callers can extract the individual errors
|
||
|
* contained in this object, but may also just treat it as a normal single
|
||
|
* error, in which case a summary message will be printed.
|
||
|
*/
|
||
|
function MultiError(errors)
|
||
|
{
|
||
|
mod_assert.ok(errors.length > 0);
|
||
|
this.ase_errors = errors;
|
||
|
|
||
|
VError.call(this, errors[0], 'first of %d error%s',
|
||
|
errors.length, errors.length == 1 ? '' : 's');
|
||
|
}
|
||
|
|
||
|
mod_util.inherits(MultiError, VError);
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Like JavaScript's built-in Error class, but supports a "cause" argument which
|
||
|
* is wrapped, not "folded in" as with VError. Accepts a printf-style message.
|
||
|
* The cause argument can be null.
|
||
|
*/
|
||
|
function WError(options)
|
||
|
{
|
||
|
Error.call(this);
|
||
|
|
||
|
var args, cause, ctor;
|
||
|
if (typeof (options) === 'object') {
|
||
|
args = Array.prototype.slice.call(arguments, 1);
|
||
|
} else {
|
||
|
args = Array.prototype.slice.call(arguments, 0);
|
||
|
options = undefined;
|
||
|
}
|
||
|
|
||
|
if (args.length > 0) {
|
||
|
this.message = mod_extsprintf.sprintf.apply(null, args);
|
||
|
} else {
|
||
|
this.message = '';
|
||
|
}
|
||
|
|
||
|
if (options) {
|
||
|
if (options instanceof Error) {
|
||
|
cause = options;
|
||
|
} else {
|
||
|
cause = options.cause;
|
||
|
ctor = options.constructorOpt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Error.captureStackTrace(this, ctor || this.constructor);
|
||
|
if (cause)
|
||
|
this.cause(cause);
|
||
|
|
||
|
}
|
||
|
|
||
|
mod_util.inherits(WError, Error);
|
||
|
WError.prototype.name = 'WError';
|
||
|
|
||
|
|
||
|
WError.prototype.toString = function we_toString()
|
||
|
{
|
||
|
var str = (this.hasOwnProperty('name') && this.name ||
|
||
|
this.constructor.name || this.constructor.prototype.name);
|
||
|
if (this.message)
|
||
|
str += ': ' + this.message;
|
||
|
if (this.we_cause && this.we_cause.message)
|
||
|
str += '; caused by ' + this.we_cause.toString();
|
||
|
|
||
|
return (str);
|
||
|
};
|
||
|
|
||
|
WError.prototype.cause = function we_cause(c)
|
||
|
{
|
||
|
if (c instanceof Error)
|
||
|
this.we_cause = c;
|
||
|
|
||
|
return (this.we_cause);
|
||
|
};
|