makeerror.js
1 var tmpl = require('tmpl') 2 3 module.exports = makeError 4 5 function BaseError() {} 6 BaseError.prototype = new Error() 7 BaseError.prototype.toString = function() { 8 return this.message 9 } 10 11 12 /** 13 * Makes an Error function with the signature: 14 * 15 * function(message, data) 16 * 17 * You'll typically do something like: 18 * 19 * var UnknownFileTypeError = makeError( 20 * 'UnknownFileTypeError', 21 * 'The specified type is not known.' 22 * ) 23 * var er = UnknownFileTypeError() 24 * 25 * `er` will have a prototype chain that ensures: 26 * 27 * er instanceof Error 28 * er instanceof UnknownFileTypeError 29 * 30 * You can also do `var er = new UnknownFileTypeError()` if you really like the 31 * `new` keyword. 32 * 33 * @param String The name of the error. 34 * @param String The default message string. 35 * @param Object The default data object, merged with per instance data. 36 */ 37 function makeError(name, defaultMessage, defaultData) { 38 defaultMessage = tmpl(defaultMessage || '') 39 defaultData = defaultData || {} 40 if (defaultData.proto && !(defaultData.proto instanceof BaseError)) 41 throw new Error('The custom "proto" must be an Error created via makeError') 42 43 var CustomError = function(message, data) { 44 if (!(this instanceof CustomError)) return new CustomError(message, data) 45 46 if (typeof message !== 'string' && !data) { 47 data = message 48 message = null 49 } 50 51 this.name = name 52 this.data = data || defaultData 53 54 if (typeof message === 'string') { 55 this.message = tmpl(message, this.data) 56 } else { 57 this.message = defaultMessage(this.data) 58 } 59 60 var er = new Error() 61 this.stack = er.stack 62 if (this.stack) { 63 // remove TWO stack level: 64 if (typeof Components !== 'undefined') { 65 // Mozilla: 66 this.stack = this.stack.substring(this.stack.indexOf('\n') + 2) 67 } else if (typeof chrome !== 'undefined' || typeof process !== 'undefined') { 68 // Google Chrome/Node.js: 69 this.stack = this.stack.replace(/\n[^\n]*/, '') 70 this.stack = this.stack.replace(/\n[^\n]*/, '') 71 this.stack = ( 72 this.name + 73 (this.message ? (': ' + this.message) : '') + 74 this.stack.substring(5) 75 ) 76 } 77 } 78 79 if ('fileName' in er) this.fileName = er.fileName 80 if ('lineNumber' in er) this.lineNumber = er.lineNumber 81 } 82 83 CustomError.prototype = defaultData.proto || new BaseError() 84 delete defaultData.proto 85 86 return CustomError 87 }