index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // ISC @ Julien Fontanet
  2. "use strict";
  3. // ===================================================================
  4. var construct = typeof Reflect !== "undefined" ? Reflect.construct : undefined;
  5. var defineProperty = Object.defineProperty;
  6. // -------------------------------------------------------------------
  7. var captureStackTrace = Error.captureStackTrace;
  8. if (captureStackTrace === undefined) {
  9. captureStackTrace = function captureStackTrace(error) {
  10. var container = new Error();
  11. defineProperty(error, "stack", {
  12. configurable: true,
  13. get: function getStack() {
  14. var stack = container.stack;
  15. // Replace property with value for faster future accesses.
  16. defineProperty(this, "stack", {
  17. configurable: true,
  18. value: stack,
  19. writable: true,
  20. });
  21. return stack;
  22. },
  23. set: function setStack(stack) {
  24. defineProperty(error, "stack", {
  25. configurable: true,
  26. value: stack,
  27. writable: true,
  28. });
  29. },
  30. });
  31. };
  32. }
  33. // -------------------------------------------------------------------
  34. function BaseError(message) {
  35. if (message !== undefined) {
  36. defineProperty(this, "message", {
  37. configurable: true,
  38. value: message,
  39. writable: true,
  40. });
  41. }
  42. var cname = this.constructor.name;
  43. if (cname !== undefined && cname !== this.name) {
  44. defineProperty(this, "name", {
  45. configurable: true,
  46. value: cname,
  47. writable: true,
  48. });
  49. }
  50. captureStackTrace(this, this.constructor);
  51. }
  52. BaseError.prototype = Object.create(Error.prototype, {
  53. // See: https://github.com/JsCommunity/make-error/issues/4
  54. constructor: {
  55. configurable: true,
  56. value: BaseError,
  57. writable: true,
  58. },
  59. });
  60. // -------------------------------------------------------------------
  61. // Sets the name of a function if possible (depends of the JS engine).
  62. var setFunctionName = (function() {
  63. function setFunctionName(fn, name) {
  64. return defineProperty(fn, "name", {
  65. configurable: true,
  66. value: name,
  67. });
  68. }
  69. try {
  70. var f = function() {};
  71. setFunctionName(f, "foo");
  72. if (f.name === "foo") {
  73. return setFunctionName;
  74. }
  75. } catch (_) {}
  76. })();
  77. // -------------------------------------------------------------------
  78. function makeError(constructor, super_) {
  79. if (super_ == null || super_ === Error) {
  80. super_ = BaseError;
  81. } else if (typeof super_ !== "function") {
  82. throw new TypeError("super_ should be a function");
  83. }
  84. var name;
  85. if (typeof constructor === "string") {
  86. name = constructor;
  87. constructor =
  88. construct !== undefined
  89. ? function() {
  90. return construct(super_, arguments, this.constructor);
  91. }
  92. : function() {
  93. super_.apply(this, arguments);
  94. };
  95. // If the name can be set, do it once and for all.
  96. if (setFunctionName !== undefined) {
  97. setFunctionName(constructor, name);
  98. name = undefined;
  99. }
  100. } else if (typeof constructor !== "function") {
  101. throw new TypeError("constructor should be either a string or a function");
  102. }
  103. // Also register the super constructor also as `constructor.super_` just
  104. // like Node's `util.inherits()`.
  105. //
  106. // eslint-disable-next-line dot-notation
  107. constructor.super_ = constructor["super"] = super_;
  108. var properties = {
  109. constructor: {
  110. configurable: true,
  111. value: constructor,
  112. writable: true,
  113. },
  114. };
  115. // If the name could not be set on the constructor, set it on the
  116. // prototype.
  117. if (name !== undefined) {
  118. properties.name = {
  119. configurable: true,
  120. value: name,
  121. writable: true,
  122. };
  123. }
  124. constructor.prototype = Object.create(super_.prototype, properties);
  125. return constructor;
  126. }
  127. exports = module.exports = makeError;
  128. exports.BaseError = BaseError;