| Leo Repp | 58b9f11 | 2021-11-22 11:57:47 +0100 | [diff] [blame^] | 1 | var toString = Object.prototype.toString; |
| 2 | |
| 3 | module.exports = function kindOf(val) { |
| 4 | if (val === void 0) return 'undefined'; |
| 5 | if (val === null) return 'null'; |
| 6 | |
| 7 | var type = typeof val; |
| 8 | if (type === 'boolean') return 'boolean'; |
| 9 | if (type === 'string') return 'string'; |
| 10 | if (type === 'number') return 'number'; |
| 11 | if (type === 'symbol') return 'symbol'; |
| 12 | if (type === 'function') { |
| 13 | return isGeneratorFn(val) ? 'generatorfunction' : 'function'; |
| 14 | } |
| 15 | |
| 16 | if (isArray(val)) return 'array'; |
| 17 | if (isBuffer(val)) return 'buffer'; |
| 18 | if (isArguments(val)) return 'arguments'; |
| 19 | if (isDate(val)) return 'date'; |
| 20 | if (isError(val)) return 'error'; |
| 21 | if (isRegexp(val)) return 'regexp'; |
| 22 | |
| 23 | switch (ctorName(val)) { |
| 24 | case 'Symbol': return 'symbol'; |
| 25 | case 'Promise': return 'promise'; |
| 26 | |
| 27 | // Set, Map, WeakSet, WeakMap |
| 28 | case 'WeakMap': return 'weakmap'; |
| 29 | case 'WeakSet': return 'weakset'; |
| 30 | case 'Map': return 'map'; |
| 31 | case 'Set': return 'set'; |
| 32 | |
| 33 | // 8-bit typed arrays |
| 34 | case 'Int8Array': return 'int8array'; |
| 35 | case 'Uint8Array': return 'uint8array'; |
| 36 | case 'Uint8ClampedArray': return 'uint8clampedarray'; |
| 37 | |
| 38 | // 16-bit typed arrays |
| 39 | case 'Int16Array': return 'int16array'; |
| 40 | case 'Uint16Array': return 'uint16array'; |
| 41 | |
| 42 | // 32-bit typed arrays |
| 43 | case 'Int32Array': return 'int32array'; |
| 44 | case 'Uint32Array': return 'uint32array'; |
| 45 | case 'Float32Array': return 'float32array'; |
| 46 | case 'Float64Array': return 'float64array'; |
| 47 | } |
| 48 | |
| 49 | if (isGeneratorObj(val)) { |
| 50 | return 'generator'; |
| 51 | } |
| 52 | |
| 53 | // Non-plain objects |
| 54 | type = toString.call(val); |
| 55 | switch (type) { |
| 56 | case '[object Object]': return 'object'; |
| 57 | // iterators |
| 58 | case '[object Map Iterator]': return 'mapiterator'; |
| 59 | case '[object Set Iterator]': return 'setiterator'; |
| 60 | case '[object String Iterator]': return 'stringiterator'; |
| 61 | case '[object Array Iterator]': return 'arrayiterator'; |
| 62 | } |
| 63 | |
| 64 | // other |
| 65 | return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); |
| 66 | }; |
| 67 | |
| 68 | function ctorName(val) { |
| 69 | return typeof val.constructor === 'function' ? val.constructor.name : null; |
| 70 | } |
| 71 | |
| 72 | function isArray(val) { |
| 73 | if (Array.isArray) return Array.isArray(val); |
| 74 | return val instanceof Array; |
| 75 | } |
| 76 | |
| 77 | function isError(val) { |
| 78 | return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); |
| 79 | } |
| 80 | |
| 81 | function isDate(val) { |
| 82 | if (val instanceof Date) return true; |
| 83 | return typeof val.toDateString === 'function' |
| 84 | && typeof val.getDate === 'function' |
| 85 | && typeof val.setDate === 'function'; |
| 86 | } |
| 87 | |
| 88 | function isRegexp(val) { |
| 89 | if (val instanceof RegExp) return true; |
| 90 | return typeof val.flags === 'string' |
| 91 | && typeof val.ignoreCase === 'boolean' |
| 92 | && typeof val.multiline === 'boolean' |
| 93 | && typeof val.global === 'boolean'; |
| 94 | } |
| 95 | |
| 96 | function isGeneratorFn(name, val) { |
| 97 | return ctorName(name) === 'GeneratorFunction'; |
| 98 | } |
| 99 | |
| 100 | function isGeneratorObj(val) { |
| 101 | return typeof val.throw === 'function' |
| 102 | && typeof val.return === 'function' |
| 103 | && typeof val.next === 'function'; |
| 104 | } |
| 105 | |
| 106 | function isArguments(val) { |
| 107 | try { |
| 108 | if (typeof val.length === 'number' && typeof val.callee === 'function') { |
| 109 | return true; |
| 110 | } |
| 111 | } catch (err) { |
| 112 | if (err.message.indexOf('callee') !== -1) { |
| 113 | return true; |
| 114 | } |
| 115 | } |
| 116 | return false; |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * If you need to support Safari 5-7 (8-10 yr-old browser), |
| 121 | * take a look at https://github.com/feross/is-buffer |
| 122 | */ |
| 123 | |
| 124 | function isBuffer(val) { |
| 125 | if (val.constructor && typeof val.constructor.isBuffer === 'function') { |
| 126 | return val.constructor.isBuffer(val); |
| 127 | } |
| 128 | return false; |
| 129 | } |