1 | 'use strict';
|
---|
2 |
|
---|
3 | var whichBoxedPrimitive = require('which-boxed-primitive');
|
---|
4 | var whichCollection = require('which-collection');
|
---|
5 | var whichTypedArray = require('which-typed-array');
|
---|
6 | var isArray = require('isarray');
|
---|
7 | var isDate = require('is-date-object');
|
---|
8 | var isRegex = require('is-regex');
|
---|
9 | var isWeakRef = require('is-weakref');
|
---|
10 | var isFinalizationRegistry = require('is-finalizationregistry');
|
---|
11 | var name = require('function.prototype.name');
|
---|
12 | var isGeneratorFunction = require('is-generator-function');
|
---|
13 | var isAsyncFunction = require('is-async-function');
|
---|
14 | var callBound = require('call-bound');
|
---|
15 | var hasToStringTag = require('has-tostringtag/shams')();
|
---|
16 | var toStringTag = hasToStringTag && Symbol.toStringTag;
|
---|
17 |
|
---|
18 | var $Object = Object;
|
---|
19 |
|
---|
20 | /** @type {undefined | ((value: ThisParameterType<typeof Promise.prototype.then>, ...args: Parameters<typeof Promise.prototype.then>) => ReturnType<typeof Promise.prototype.then>)} */
|
---|
21 | var promiseThen = callBound('Promise.prototype.then', true);
|
---|
22 | /** @type {<T = unknown>(value: unknown) => value is Promise<T>} */
|
---|
23 | var isPromise = function isPromise(value) {
|
---|
24 | if (!value || typeof value !== 'object' || !promiseThen) {
|
---|
25 | return false;
|
---|
26 | }
|
---|
27 | try {
|
---|
28 | promiseThen(value, null, function () {});
|
---|
29 | return true;
|
---|
30 | } catch (e) {}
|
---|
31 | return false;
|
---|
32 | };
|
---|
33 |
|
---|
34 | /** @type {(builtinName: unknown) => boolean} */
|
---|
35 | var isKnownBuiltin = function isKnownBuiltin(builtinName) {
|
---|
36 | return !!builtinName
|
---|
37 | // primitives
|
---|
38 | && builtinName !== 'BigInt'
|
---|
39 | && builtinName !== 'Boolean'
|
---|
40 | && builtinName !== 'Null'
|
---|
41 | && builtinName !== 'Number'
|
---|
42 | && builtinName !== 'String'
|
---|
43 | && builtinName !== 'Symbol'
|
---|
44 | && builtinName !== 'Undefined'
|
---|
45 | // namespaces
|
---|
46 | && builtinName !== 'Math'
|
---|
47 | && builtinName !== 'JSON'
|
---|
48 | && builtinName !== 'Reflect'
|
---|
49 | && builtinName !== 'Atomics'
|
---|
50 | // collections
|
---|
51 | && builtinName !== 'Map'
|
---|
52 | && builtinName !== 'Set'
|
---|
53 | && builtinName !== 'WeakMap'
|
---|
54 | && builtinName !== 'WeakSet'
|
---|
55 | // typed arrays
|
---|
56 | && builtinName !== 'BigInt64Array'
|
---|
57 | && builtinName !== 'BigUint64Array'
|
---|
58 | && builtinName !== 'Float32Array'
|
---|
59 | && builtinName !== 'Float64Array'
|
---|
60 | && builtinName !== 'Int16Array'
|
---|
61 | && builtinName !== 'Int32Array'
|
---|
62 | && builtinName !== 'Int8Array'
|
---|
63 | && builtinName !== 'Uint16Array'
|
---|
64 | && builtinName !== 'Uint32Array'
|
---|
65 | && builtinName !== 'Uint8Array'
|
---|
66 | && builtinName !== 'Uint8ClampedArray'
|
---|
67 | // checked explicitly
|
---|
68 | && builtinName !== 'Array'
|
---|
69 | && builtinName !== 'Date'
|
---|
70 | && builtinName !== 'FinalizationRegistry'
|
---|
71 | && builtinName !== 'Promise'
|
---|
72 | && builtinName !== 'RegExp'
|
---|
73 | && builtinName !== 'WeakRef'
|
---|
74 | // functions
|
---|
75 | && builtinName !== 'Function'
|
---|
76 | && builtinName !== 'GeneratorFunction'
|
---|
77 | && builtinName !== 'AsyncFunction';
|
---|
78 | };
|
---|
79 |
|
---|
80 | /** @type {import('.')} */
|
---|
81 | module.exports = function whichBuiltinType(value) {
|
---|
82 | if (value == null) {
|
---|
83 | return value;
|
---|
84 | }
|
---|
85 | // covers: primitives, {,Weak}Map/Set, typed arrays
|
---|
86 | var which = whichBoxedPrimitive($Object(value)) || whichCollection(value) || whichTypedArray(value);
|
---|
87 | if (which) {
|
---|
88 | return which;
|
---|
89 | }
|
---|
90 | if (isArray(value)) {
|
---|
91 | return 'Array';
|
---|
92 | }
|
---|
93 | if (isDate(value)) {
|
---|
94 | return 'Date';
|
---|
95 | }
|
---|
96 | if (isRegex(value)) {
|
---|
97 | return 'RegExp';
|
---|
98 | }
|
---|
99 | if (isWeakRef(value)) {
|
---|
100 | return 'WeakRef';
|
---|
101 | }
|
---|
102 | if (isFinalizationRegistry(value)) {
|
---|
103 | return 'FinalizationRegistry';
|
---|
104 | }
|
---|
105 | if (typeof value === 'function') {
|
---|
106 | if (isGeneratorFunction(value)) {
|
---|
107 | return 'GeneratorFunction';
|
---|
108 | }
|
---|
109 | if (isAsyncFunction(value)) {
|
---|
110 | return 'AsyncFunction';
|
---|
111 | }
|
---|
112 | return 'Function';
|
---|
113 | }
|
---|
114 | if (isPromise(value)) {
|
---|
115 | return 'Promise';
|
---|
116 | }
|
---|
117 | // @ts-expect-error TS can't figure out that `value` is an `object` after the `which` check above
|
---|
118 | if (toStringTag && toStringTag in value) {
|
---|
119 | var tag = value[toStringTag];
|
---|
120 | if (isKnownBuiltin(tag)) {
|
---|
121 | return tag;
|
---|
122 | }
|
---|
123 | }
|
---|
124 | if (typeof value.constructor === 'function') {
|
---|
125 | // eslint-disable-next-line no-extra-parens
|
---|
126 | var constructorName = name(/** @type {Parameters<name>[0]} */ (value.constructor));
|
---|
127 | if (isKnownBuiltin(constructorName)) {
|
---|
128 | return constructorName;
|
---|
129 | }
|
---|
130 | }
|
---|
131 | return 'Object';
|
---|
132 | };
|
---|