verror.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * verror.js: richer JavaScript errors
  3. */
  4. var mod_assert = require('assert');
  5. var mod_util = require('util');
  6. var mod_extsprintf = require('extsprintf');
  7. /*
  8. * Public interface
  9. */
  10. exports.VError = VError;
  11. exports.WError = WError;
  12. exports.MultiError = MultiError;
  13. /*
  14. * Like JavaScript's built-in Error class, but supports a "cause" argument and a
  15. * printf-style message. The cause argument can be null.
  16. */
  17. function VError(options)
  18. {
  19. var args, causedBy, ctor, tailmsg;
  20. if (options instanceof Error || typeof (options) === 'object') {
  21. args = Array.prototype.slice.call(arguments, 1);
  22. } else {
  23. args = Array.prototype.slice.call(arguments, 0);
  24. options = undefined;
  25. }
  26. tailmsg = args.length > 0 ?
  27. mod_extsprintf.sprintf.apply(null, args) : '';
  28. this.jse_shortmsg = tailmsg;
  29. this.jse_summary = tailmsg;
  30. if (options) {
  31. causedBy = options.cause;
  32. if (!causedBy || !(options.cause instanceof Error))
  33. causedBy = options;
  34. if (causedBy && (causedBy instanceof Error)) {
  35. this.jse_cause = causedBy;
  36. this.jse_summary += ': ' + causedBy.message;
  37. }
  38. }
  39. this.message = this.jse_summary;
  40. Error.call(this, this.jse_summary);
  41. if (Error.captureStackTrace) {
  42. ctor = options ? options.constructorOpt : undefined;
  43. ctor = ctor || arguments.callee;
  44. Error.captureStackTrace(this, ctor);
  45. }
  46. }
  47. mod_util.inherits(VError, Error);
  48. VError.prototype.name = 'VError';
  49. VError.prototype.toString = function ve_toString()
  50. {
  51. var str = (this.hasOwnProperty('name') && this.name ||
  52. this.constructor.name || this.constructor.prototype.name);
  53. if (this.message)
  54. str += ': ' + this.message;
  55. return (str);
  56. };
  57. VError.prototype.cause = function ve_cause()
  58. {
  59. return (this.jse_cause);
  60. };
  61. /*
  62. * Represents a collection of errors for the purpose of consumers that generally
  63. * only deal with one error. Callers can extract the individual errors
  64. * contained in this object, but may also just treat it as a normal single
  65. * error, in which case a summary message will be printed.
  66. */
  67. function MultiError(errors)
  68. {
  69. mod_assert.ok(errors.length > 0);
  70. this.ase_errors = errors;
  71. VError.call(this, errors[0], 'first of %d error%s',
  72. errors.length, errors.length == 1 ? '' : 's');
  73. }
  74. mod_util.inherits(MultiError, VError);
  75. /*
  76. * Like JavaScript's built-in Error class, but supports a "cause" argument which
  77. * is wrapped, not "folded in" as with VError. Accepts a printf-style message.
  78. * The cause argument can be null.
  79. */
  80. function WError(options)
  81. {
  82. Error.call(this);
  83. var args, cause, ctor;
  84. if (typeof (options) === 'object') {
  85. args = Array.prototype.slice.call(arguments, 1);
  86. } else {
  87. args = Array.prototype.slice.call(arguments, 0);
  88. options = undefined;
  89. }
  90. if (args.length > 0) {
  91. this.message = mod_extsprintf.sprintf.apply(null, args);
  92. } else {
  93. this.message = '';
  94. }
  95. if (options) {
  96. if (options instanceof Error) {
  97. cause = options;
  98. } else {
  99. cause = options.cause;
  100. ctor = options.constructorOpt;
  101. }
  102. }
  103. Error.captureStackTrace(this, ctor || this.constructor);
  104. if (cause)
  105. this.cause(cause);
  106. }
  107. mod_util.inherits(WError, Error);
  108. WError.prototype.name = 'WError';
  109. WError.prototype.toString = function we_toString()
  110. {
  111. var str = (this.hasOwnProperty('name') && this.name ||
  112. this.constructor.name || this.constructor.prototype.name);
  113. if (this.message)
  114. str += ': ' + this.message;
  115. if (this.we_cause && this.we_cause.message)
  116. str += '; caused by ' + this.we_cause.toString();
  117. return (str);
  118. };
  119. WError.prototype.cause = function we_cause(c)
  120. {
  121. if (c instanceof Error)
  122. this.we_cause = c;
  123. return (this.we_cause);
  124. };