sugar
Version:
A Javascript utility library for working with native objects.
138 lines (113 loc) • 4.19 kB
JavaScript
;
var NATIVE_TYPES = require('./NATIVE_TYPES'),
forEach = require('../internal/forEach'),
isClass = require('../internal/isClass'),
spaceSplit = require('../internal/spaceSplit'),
isPlainObject = require('../internal/isPlainObject');
var isSerializable,
isBoolean, isNumber, isString,
isDate, isRegExp, isFunction,
isArray, isSet, isMap, isError;
function buildClassChecks() {
var knownTypes = {};
function addCoreTypes() {
var names = spaceSplit(NATIVE_TYPES);
isBoolean = buildPrimitiveClassCheck(names[0]);
isNumber = buildPrimitiveClassCheck(names[1]);
isString = buildPrimitiveClassCheck(names[2]);
isDate = buildClassCheck(names[3]);
isRegExp = buildClassCheck(names[4]);
// Wanted to enhance performance here by using simply "typeof"
// but Firefox has two major issues that make this impossible,
// one fixed, the other not, so perform a full class check here.
//
// 1. Regexes can be typeof "function" in FF < 3
// https://bugzilla.mozilla.org/show_bug.cgi?id=61911 (fixed)
//
// 2. HTMLEmbedElement and HTMLObjectElement are be typeof "function"
// https://bugzilla.mozilla.org/show_bug.cgi?id=268945 (won't fix)
isFunction = buildClassCheck(names[5]);
// istanbul ignore next
isArray = Array.isArray || buildClassCheck(names[6]);
isError = buildClassCheck(names[7]);
isSet = buildClassCheck(names[8], typeof Set !== 'undefined' && Set);
isMap = buildClassCheck(names[9], typeof Map !== 'undefined' && Map);
// Add core types as known so that they can be checked by value below,
// notably excluding Functions and adding Arguments and Error.
addKnownType('Arguments');
addKnownType(names[0]);
addKnownType(names[1]);
addKnownType(names[2]);
addKnownType(names[3]);
addKnownType(names[4]);
addKnownType(names[6]);
}
function addArrayTypes() {
var types = 'Int8 Uint8 Uint8Clamped Int16 Uint16 Int32 Uint32 Float32 Float64';
forEach(spaceSplit(types), function(str) {
addKnownType(str + 'Array');
});
}
function addKnownType(className) {
var str = '[object '+ className +']';
knownTypes[str] = true;
}
function isKnownType(className) {
return knownTypes[className];
}
function buildClassCheck(className, globalObject) {
// istanbul ignore if
if (globalObject && isClass(new globalObject, 'Object')) {
return getConstructorClassCheck(globalObject);
} else {
return getToStringClassCheck(className);
}
}
// Map and Set may be [object Object] in certain IE environments.
// In this case we need to perform a check using the constructor
// instead of Object.prototype.toString.
// istanbul ignore next
function getConstructorClassCheck(obj) {
var ctorStr = String(obj);
return function(obj) {
return String(obj.constructor) === ctorStr;
};
}
function getToStringClassCheck(className) {
return function(obj, str) {
// perf: Returning up front on instanceof appears to be slower.
return isClass(obj, className, str);
};
}
function buildPrimitiveClassCheck(className) {
var type = className.toLowerCase();
return function(obj) {
var t = typeof obj;
return t === type || t === 'object' && isClass(obj, className);
};
}
addCoreTypes();
addArrayTypes();
isSerializable = function(obj, className) {
// Only known objects can be serialized. This notably excludes functions,
// host objects, Symbols (which are matched by reference), and instances
// of classes. The latter can arguably be matched by value, but
// distinguishing between these and host objects -- which should never be
// compared by value -- is very tricky so not dealing with it here.
return isKnownType(className) || isPlainObject(obj, className);
};
}
buildClassChecks();
module.exports = {
isSerializable: isSerializable,
isBoolean: isBoolean,
isNumber: isNumber,
isString: isString,
isDate: isDate,
isRegExp: isRegExp,
isFunction: isFunction,
isArray: isArray,
isSet: isSet,
isMap: isMap,
isError: isError
};