// ISC @ Julien Fontanet 'use strict' // =================================================================== var defineProperty = Object.defineProperty // ------------------------------------------------------------------- var captureStackTrace = Error.captureStackTrace if (!captureStackTrace) { captureStackTrace = function captureStackTrace (error) { var container = new Error() defineProperty(error, 'stack', { configurable: true, get: function getStack () { var stack = container.stack // Replace property with value for faster future accesses. defineProperty(this, 'stack', { value: stack }) return stack }, set: function setStack (stack) { defineProperty(error, 'stack', { configurable: true, value: stack, writable: true }) } }) } } // ------------------------------------------------------------------- function BaseError (message) { if (message) { defineProperty(this, 'message', { configurable: true, value: message, writable: true }) } var cname = this.constructor.name if ( cname && cname !== this.name ) { defineProperty(this, 'name', { configurable: true, value: cname, writable: true }) } captureStackTrace(this, this.constructor) } BaseError.prototype = Object.create(Error.prototype, { // See: https://github.com/JsCommunity/make-error/issues/4 constructor: { configurable: true, value: BaseError, writable: true } }) // ------------------------------------------------------------------- // Sets the name of a function if possible (depends of the JS engine). var setFunctionName = (function () { function setFunctionName (fn, name) { return defineProperty(fn, 'name', { configurable: true, value: name }) } try { var f = function () {} setFunctionName(f, 'foo') if (f.name === 'foo') { return setFunctionName } } catch (_) {} })() // ------------------------------------------------------------------- function makeError (constructor, super_) { if (super_ == null || super_ === Error) { super_ = BaseError } else if (typeof super_ !== 'function') { throw new TypeError('super_ should be a function') } var name if (typeof constructor === 'string') { name = constructor constructor = function () { super_.apply(this, arguments) } // If the name can be set, do it once and for all. if (setFunctionName) { setFunctionName(constructor, name) name = null } } else if (typeof constructor !== 'function') { throw new TypeError('constructor should be either a string or a function') } // Also register the super constructor also as `constructor.super_` just // like Node's `util.inherits()`. constructor.super_ = constructor['super'] = super_ var properties = { constructor: { configurable: true, value: constructor, writable: true } } // If the name could not be set on the constructor, set it on the // prototype. if (name != null) { properties.name = { configurable: true, value: name, writable: true } } constructor.prototype = Object.create(super_.prototype, properties) return constructor } exports = module.exports = makeError exports.BaseError = BaseError