UNPKG

3.55 kBJavaScriptView Raw
1// create-error.js 0.3.1
2// (c) 2013 Tim Griesser
3// This source may be freely distributed under the MIT license.
4(function(factory) {
5
6"use strict";
7
8// A simple utility for subclassing the "Error"
9// object in multiple environments, while maintaining
10// relevant stack traces, messages, and prototypes.
11factory(function() {
12
13var toString = Object.prototype.toString;
14
15// Creates an new error type with a "name",
16// and any additional properties that should be set
17// on the error instance.
18return function() {
19 var args = new Array(arguments.length);
20 for (var i = 0; i < args.length; ++i) {
21 args[i] = arguments[i];
22 }
23 var name = getName(args);
24 var target = getTarget(args);
25 var properties = getProps(args);
26 function ErrorCtor(message, obj) {
27 attachProps(this, properties);
28 attachProps(this, obj);
29 this.message = (message || this.message);
30 if (message instanceof Error) {
31 this.message = message.message;
32 this.stack = message.stack;
33 } else if (Error.captureStackTrace) {
34 Error.captureStackTrace(this, this.constructor);
35 }
36 }
37 function Err() { this.constructor = ErrorCtor; }
38 Err.prototype = target['prototype'];
39 ErrorCtor.prototype = new Err();
40 ErrorCtor.prototype.name = ('' + name) || 'CustomError';
41 return ErrorCtor;
42};
43
44// Just a few helpers to clean up the function above
45// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
46function getName(args) {
47 if (args.length === 0) return '';
48 return isError(args[0]) ? (args[1] || '') : args[0];
49}
50function getTarget(args) {
51 if (args.length === 0) return Error;
52 return isError(args[0]) ? args[0] : Error;
53}
54function getProps(args) {
55 if (args.length === 0) return null;
56 return isError(args[0]) ? args[2] : args[1];
57}
58function inheritedKeys(obj) {
59 var ret = [];
60 for (var key in obj) {
61 ret.push(key);
62 }
63 return ret;
64}
65
66// Right now we're just assuming that a function in the first argument is an error.
67function isError(obj) {
68 return (typeof obj === "function");
69}
70
71// We don't need the full underscore check here, since it should either be
72// an object-literal, or nothing at all.
73function isObject(obj) {
74 return (obj && typeof obj === "object" && toString.call(obj) === "[object Object]");
75}
76
77// Used to attach attributes to the error object in the constructor.
78function attachProps(context, target) {
79 if (isObject(target)) {
80 var keys = inheritedKeys(target);
81 for (var i = 0, l = keys.length; i < l; ++i) {
82 context[keys[i]] = clone(target[keys[i]]);
83 }
84 }
85}
86
87// Don't need the full-out "clone" mechanism here, since if you're
88// trying to set things other than empty arrays/objects on your
89// sub-classed `Error` object, you're probably doing it wrong.
90function clone(target) {
91 if (target == null || typeof target !== "object") return target;
92 var cloned = target.constructor ? target.constructor() : Object.create(null);
93 for (var attr in target) {
94 if (target.hasOwnProperty(attr)) {
95 cloned[attr] = target[attr];
96 }
97 }
98 return cloned;
99}
100
101});
102
103// Boilerplate UMD definition block...
104})(function(createErrorLib) {
105 if (typeof define === "function" && define.amd) {
106 define(createErrorLib);
107 } else if (typeof exports === 'object') {
108 module.exports = createErrorLib();
109 } else {
110 var root = this;
111 var lastcreateError = root.createError;
112 var createError = root.createError = createErrorLib();
113 createError.noConflict = function() {
114 root.createError = lastcreateError;
115 return createError;
116 };
117 }
118});