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