148 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // ISC @ Julien Fontanet
 | |
| 
 | |
| 'use strict'
 | |
| 
 | |
| // ===================================================================
 | |
| 
 | |
| var construct = typeof Reflect !== 'undefined' ? Reflect.construct : undefined
 | |
| var defineProperty = Object.defineProperty
 | |
| 
 | |
| // -------------------------------------------------------------------
 | |
| 
 | |
| var captureStackTrace = Error.captureStackTrace
 | |
| if (captureStackTrace === undefined) {
 | |
|   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', {
 | |
|           configurable: true,
 | |
|           value: stack,
 | |
|           writable: true
 | |
|         })
 | |
| 
 | |
|         return stack
 | |
|       },
 | |
|       set: function setStack (stack) {
 | |
|         defineProperty(error, 'stack', {
 | |
|           configurable: true,
 | |
|           value: stack,
 | |
|           writable: true
 | |
|         })
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| }
 | |
| 
 | |
| // -------------------------------------------------------------------
 | |
| 
 | |
| function BaseError (message) {
 | |
|   if (message !== undefined) {
 | |
|     defineProperty(this, 'message', {
 | |
|       configurable: true,
 | |
|       value: message,
 | |
|       writable: true
 | |
|     })
 | |
|   }
 | |
| 
 | |
|   var cname = this.constructor.name
 | |
|   if (
 | |
|     cname !== undefined &&
 | |
|     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 = construct !== undefined
 | |
|       ? function () { return construct(super_, arguments, this.constructor) }
 | |
|       : function () { super_.apply(this, arguments) }
 | |
| 
 | |
|     // If the name can be set, do it once and for all.
 | |
|     if (setFunctionName !== undefined) {
 | |
|       setFunctionName(constructor, name)
 | |
|       name = undefined
 | |
|     }
 | |
|   } 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 !== undefined) {
 | |
|     properties.name = {
 | |
|       configurable: true,
 | |
|       value: name,
 | |
|       writable: true
 | |
|     }
 | |
|   }
 | |
|   constructor.prototype = Object.create(super_.prototype, properties)
 | |
| 
 | |
|   return constructor
 | |
| }
 | |
| exports = module.exports = makeError
 | |
| exports.BaseError = BaseError
 |