index.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 (
  44. cname !== undefined &&
  45. cname !== this.name
  46. ) {
  47. defineProperty(this, 'name', {
  48. configurable: true,
  49. value: cname,
  50. writable: true
  51. })
  52. }
  53. captureStackTrace(this, this.constructor)
  54. }
  55. BaseError.prototype = Object.create(Error.prototype, {
  56. // See: https://github.com/JsCommunity/make-error/issues/4
  57. constructor: {
  58. configurable: true,
  59. value: BaseError,
  60. writable: true
  61. }
  62. })
  63. // -------------------------------------------------------------------
  64. // Sets the name of a function if possible (depends of the JS engine).
  65. var setFunctionName = (function () {
  66. function setFunctionName (fn, name) {
  67. return defineProperty(fn, 'name', {
  68. configurable: true,
  69. value: name
  70. })
  71. }
  72. try {
  73. var f = function () {}
  74. setFunctionName(f, 'foo')
  75. if (f.name === 'foo') {
  76. return setFunctionName
  77. }
  78. } catch (_) {}
  79. })()
  80. // -------------------------------------------------------------------
  81. function makeError (constructor, super_) {
  82. if (super_ == null || super_ === Error) {
  83. super_ = BaseError
  84. } else if (typeof super_ !== 'function') {
  85. throw new TypeError('super_ should be a function')
  86. }
  87. var name
  88. if (typeof constructor === 'string') {
  89. name = constructor
  90. constructor = construct !== undefined
  91. ? function () { return construct(super_, arguments, this.constructor) }
  92. : function () { super_.apply(this, arguments) }
  93. // If the name can be set, do it once and for all.
  94. if (setFunctionName !== undefined) {
  95. setFunctionName(constructor, name)
  96. name = undefined
  97. }
  98. } else if (typeof constructor !== 'function') {
  99. throw new TypeError('constructor should be either a string or a function')
  100. }
  101. // Also register the super constructor also as `constructor.super_` just
  102. // like Node's `util.inherits()`.
  103. constructor.super_ = constructor['super'] = super_
  104. var properties = {
  105. constructor: {
  106. configurable: true,
  107. value: constructor,
  108. writable: true
  109. }
  110. }
  111. // If the name could not be set on the constructor, set it on the
  112. // prototype.
  113. if (name !== undefined) {
  114. properties.name = {
  115. configurable: true,
  116. value: name,
  117. writable: true
  118. }
  119. }
  120. constructor.prototype = Object.create(super_.prototype, properties)
  121. return constructor
  122. }
  123. exports = module.exports = makeError
  124. exports.BaseError = BaseError