e09cb20729bebb1b972ebee47a97680ef9356614b22d7dded2376795acb81d2223676e9934dd71de08cb63a763eb9ee4934030b360d9780ea38c8eff47216e 3.9 KB

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