b352d7cbdc1e8cd577ab4565939182ef93e9678f35d84ade1849003f329c86380bcfaefd0f5fc0a0165cd42b7695304a7b152a031c400f7e5945bf10a404a5 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. 'use strict';
  2. var test = require('tape');
  3. var inspect = require('object-inspect');
  4. var assign = require('object.assign');
  5. var forEach = require('for-each');
  6. var arrows = require('make-arrow-function').list();
  7. var generators = require('make-generator-function')();
  8. var asyncs = require('make-async-function').list();
  9. var hasSymbols = require('has-symbols')();
  10. var hasToStringTag = require('has-tostringtag/shams')();
  11. var hasBigInts = require('has-bigints')();
  12. var availableTypedArrays = require('available-typed-arrays');
  13. var which = require('../');
  14. if (typeof process !== 'undefined') {
  15. process.on('unhandledRejection', function () {});
  16. }
  17. test('nullish', function (t) {
  18. t.equal(which(null), null, 'null is null');
  19. t.equal(which(undefined), undefined, 'undefined is undefined');
  20. // @ts-expect-error
  21. t.equal(which(), undefined, 'absent is undefined');
  22. t.end();
  23. });
  24. test('non-nullish', function (t) {
  25. /** @constructor */
  26. var F = function Foo() {};
  27. var tests = {
  28. Number: [
  29. 0,
  30. -0,
  31. 42,
  32. Infinity,
  33. -Infinity,
  34. NaN,
  35. 0.5
  36. ],
  37. Boolean: [
  38. true,
  39. false
  40. ],
  41. String: [
  42. '',
  43. 'foo'
  44. ],
  45. Date: [
  46. new Date(),
  47. new Date(NaN),
  48. assign(new Date(), { constructor: Object })
  49. ],
  50. RegExp: [
  51. /(?:)/,
  52. /a/g,
  53. assign(/constructor/, { constructor: Object })
  54. ],
  55. Array: [
  56. [],
  57. [42],
  58. assign([], { constructor: Object })
  59. ],
  60. Function: [
  61. function () {},
  62. function f() {},
  63. assign(function constructor() {}, { constructor: Object })
  64. ].concat(arrows),
  65. GeneratorFunction: generators,
  66. AsyncFunction: asyncs,
  67. // eslint-disable-next-line no-extra-parens
  68. Object: /** @type {object[]} */ ([
  69. {},
  70. { constructor: null },
  71. Math
  72. ]),
  73. Symbol: hasSymbols ? [
  74. Symbol.iterator,
  75. Symbol(),
  76. Symbol('foo'),
  77. Symbol['for'] ? Symbol['for']('bar') : Symbol('no "for" support') // eslint-disable-line no-restricted-properties
  78. ] : [],
  79. BigInt: hasBigInts ? [
  80. BigInt(0),
  81. BigInt(42)
  82. ] : [],
  83. Foo: [
  84. new F()
  85. ],
  86. Map: typeof Map === 'function' ? [
  87. new Map(),
  88. new Map([[1, 2], [3, 4]]),
  89. assign(new Map(), { constructor: Object })
  90. ] : [],
  91. WeakMap: typeof WeakMap === 'function' ? [
  92. new WeakMap(),
  93. assign(new WeakMap(), { constructor: Object })
  94. ] : [],
  95. Set: typeof Set === 'function' ? [
  96. new Set(),
  97. new Set([1, 2, 3, 4]),
  98. assign(new Set(), { constructor: Object })
  99. ] : [],
  100. WeakSet: typeof WeakSet === 'function' ? [
  101. new WeakSet(),
  102. assign(new WeakSet(), { constructor: Object })
  103. ] : [],
  104. WeakRef: typeof WeakRef === 'function' ? [
  105. new WeakRef({}),
  106. assign(new WeakRef({}), { constructor: Object })
  107. ] : [],
  108. FinalizationRegistry: typeof FinalizationRegistry === 'function' ? [
  109. new FinalizationRegistry(function () {}),
  110. assign(new FinalizationRegistry(function () {}), { constructor: Object })
  111. ] : [],
  112. Promise: typeof Promise === 'function' ? [
  113. Promise.resolve(42),
  114. Promise.reject(NaN),
  115. new Promise(function () {})
  116. ] : []
  117. };
  118. forEach(availableTypedArrays(), function (TypedArray) {
  119. // @ts-expect-error not sure how to infer this as being spreaded into the above object literal
  120. tests[TypedArray] = [
  121. new global[TypedArray](0),
  122. new global[TypedArray](2)
  123. ];
  124. });
  125. forEach(tests, function (values, expected) {
  126. forEach(values, function (value) {
  127. t.equal(which(value), expected, inspect(value) + ' is ' + inspect(expected));
  128. var obj = Object(value);
  129. if (value !== obj) {
  130. t.equal(which(obj), expected, inspect(obj) + ' is ' + inspect(expected));
  131. }
  132. if (
  133. expected !== 'Object' // the fallback can't fall back
  134. && expected !== 'Foo' // not a builtin
  135. ) {
  136. if (hasToStringTag) {
  137. /** @type {{ [k in typeof Symbol.toStringTag]?: string }} */
  138. var fakerTag = {};
  139. fakerTag[Symbol.toStringTag] = expected;
  140. t.equal(
  141. which(fakerTag),
  142. 'Object',
  143. inspect(fakerTag) + ' lies and claims it is a ' + expected + ', but instead it is Object'
  144. );
  145. }
  146. /** @typedef {Exclude<typeof expected, 'GeneratorFunction' | 'AsyncFunction' | 'Foo'>} GlobalKey */
  147. var fakerConstructor = {
  148. // eslint-disable-next-line no-extra-parens
  149. constructor: global[/** @type {GlobalKey} */ (expected)] || tests[expected]
  150. };
  151. t.equal(
  152. which(fakerConstructor),
  153. 'Object',
  154. inspect(fakerConstructor) + ' lies and claims it is a ' + expected + ', but instead it is Object'
  155. );
  156. if (hasToStringTag) {
  157. /** @type {{ constructor: Function } & { [k in typeof Symbol.toStringTag]?: string }} */
  158. var fakerConstructorTag = {
  159. // eslint-disable-next-line no-extra-parens
  160. constructor: global[/** @type {GlobalKey} */ (expected)] || tests[expected]
  161. };
  162. fakerConstructorTag[Symbol.toStringTag] = expected;
  163. t.equal(
  164. which(fakerConstructorTag),
  165. 'Object',
  166. inspect(fakerConstructorTag) + ' lies with a tag and claims it is a ' + expected + ', but instead it is Object'
  167. );
  168. }
  169. }
  170. });
  171. });
  172. t.end();
  173. });