119 lines
3.5 KiB
JavaScript
119 lines
3.5 KiB
JavaScript
|
// 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;
|
||
|
};
|
||
|
}
|
||
|
});
|