number.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. describe('Number', function () {
  2. var functionsHaveNames = (function foo() {}).name === 'foo';
  3. var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
  4. var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
  5. var integers = [5295, -5295, -9007199254740991, 9007199254740991, 0, -0];
  6. var nonIntegers = [-9007199254741992, 9007199254741992, 5.9];
  7. var infinities = [Infinity, -Infinity];
  8. var valueOfThree = { valueOf: function () { return 3; } };
  9. var valueOfNaN = { valueOf: function () { return NaN; } };
  10. var valueOfThrows = { valueOf: function () { throw Object(17); } };
  11. var toStringThrows = { toString: function () { throw Object(42); } };
  12. var toPrimitiveThrows = {
  13. valueOf: function () { throw Object(17); },
  14. toString: function () { throw Object(42); }
  15. };
  16. var nonNumbers = [
  17. undefined,
  18. true,
  19. false,
  20. null,
  21. {},
  22. [],
  23. 'str',
  24. '',
  25. valueOfThree,
  26. valueOfNaN,
  27. valueOfThrows,
  28. toStringThrows,
  29. toPrimitiveThrows,
  30. /a/g
  31. ];
  32. var expectTrue = function (item) {
  33. expect(item).to.equal(true);
  34. };
  35. var expectFalse = function (item) {
  36. expect(item).to.equal(false);
  37. };
  38. ifShimIt('is on the exported object', function () {
  39. var exported = require('../');
  40. expect(exported.Number).to.equal(Number);
  41. });
  42. describe('Number constants', function () {
  43. it('should have max safe integer', function () {
  44. expect(Number).to.have.property('MAX_SAFE_INTEGER');
  45. expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_SAFE_INTEGER')).to.equal(false);
  46. expect(Number.MAX_SAFE_INTEGER).to.equal(Math.pow(2, 53) - 1);
  47. });
  48. it('should have min safe integer', function () {
  49. expect(Number).to.have.property('MIN_SAFE_INTEGER');
  50. expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_SAFE_INTEGER')).to.equal(false);
  51. expect(Number.MIN_SAFE_INTEGER).to.equal(-Math.pow(2, 53) + 1);
  52. });
  53. it('should have epsilon', function () {
  54. expect(Number).to.have.property('EPSILON');
  55. expect(Object.prototype.propertyIsEnumerable.call(Number, 'EPSILON')).to.equal(false);
  56. expect(Number.EPSILON).to.equal(2.2204460492503130808472633361816e-16);
  57. });
  58. it('should have NaN', function () {
  59. expect(Number).to.have.property('NaN');
  60. expect(Object.prototype.propertyIsEnumerable.call(Number, 'NaN')).to.equal(false);
  61. expect(isNaN(Number.NaN)).to.equal(true);
  62. });
  63. it('should have MAX_VALUE', function () {
  64. expect(Number).to.have.property('MAX_VALUE');
  65. expect(Object.prototype.propertyIsEnumerable.call(Number, 'MAX_VALUE')).to.equal(false);
  66. expect(Number.MAX_VALUE).to.equal(1.7976931348623157e+308);
  67. });
  68. it('should have MIN_VALUE', function () {
  69. expect(Number).to.have.property('MIN_VALUE');
  70. expect(Object.prototype.propertyIsEnumerable.call(Number, 'MIN_VALUE')).to.equal(false);
  71. expect(Number.MIN_VALUE).to.equal(5e-324);
  72. });
  73. it('should have NEGATIVE_INFINITY', function () {
  74. expect(Number).to.have.property('NEGATIVE_INFINITY');
  75. expect(Object.prototype.propertyIsEnumerable.call(Number, 'NEGATIVE_INFINITY')).to.equal(false);
  76. expect(Number.NEGATIVE_INFINITY).to.equal(-Infinity);
  77. });
  78. it('should have POSITIVE_INFINITY', function () {
  79. expect(Number).to.have.property('POSITIVE_INFINITY');
  80. expect(Object.prototype.propertyIsEnumerable.call(Number, 'POSITIVE_INFINITY')).to.equal(false);
  81. expect(Number.POSITIVE_INFINITY).to.equal(Infinity);
  82. });
  83. });
  84. describe('.parseInt()', function () {
  85. if (!Object.prototype.hasOwnProperty.call(Number, 'parseInt')) {
  86. return it('exists', function () {
  87. expect(Number).to.have.property('parseInt');
  88. });
  89. }
  90. it('should work', function () {
  91. /* eslint-disable radix */
  92. expect(Number.parseInt('601')).to.equal(601);
  93. /* eslint-enable radix */
  94. });
  95. ifFunctionsHaveNamesIt('has the right name', function () {
  96. expect(Number.parseInt).to.have.property('name', 'parseInt');
  97. });
  98. it('is not enumerable', function () {
  99. expect(Number).ownPropertyDescriptor('parseInt').to.have.property('enumerable', false);
  100. });
  101. it('has the right arity', function () {
  102. // WebKit nightly had the wrong length; fixed in https://bugs.webkit.org/show_bug.cgi?id=143657
  103. expect(Number.parseInt).to.have.property('length', 2);
  104. });
  105. it('is the same object as the global parseInt', function () {
  106. // fixed in WebKit nightly in https://bugs.webkit.org/show_bug.cgi?id=143799#add_comment
  107. expect(Number.parseInt).to.equal(parseInt);
  108. });
  109. });
  110. describe('.parseFloat()', function () {
  111. if (!Object.prototype.hasOwnProperty.call(Number, 'parseFloat')) {
  112. return it('exists', function () {
  113. expect(Number).to.have.property('parseFloat');
  114. });
  115. }
  116. it('should work', function () {
  117. expect(Number.parseFloat('5.5')).to.equal(5.5);
  118. });
  119. ifFunctionsHaveNamesIt('has the right name', function () {
  120. expect(Number.parseFloat).to.have.property('name', 'parseFloat');
  121. });
  122. it('is not enumerable', function () {
  123. expect(Number).ownPropertyDescriptor('parseFloat').to.have.property('enumerable', false);
  124. });
  125. it('has the right arity', function () {
  126. expect(Number.parseFloat).to.have.property('length', 1);
  127. });
  128. });
  129. describe('.isFinite()', function () {
  130. if (!Object.prototype.hasOwnProperty.call(Number, 'isFinite')) {
  131. return it('exists', function () {
  132. expect(Number).to.have.property('isFinite');
  133. });
  134. }
  135. ifFunctionsHaveNamesIt('has the right name', function () {
  136. expect(Number.isFinite).to.have.property('name', 'isFinite');
  137. });
  138. it('is not enumerable', function () {
  139. expect(Number).ownPropertyDescriptor('isFinite').to.have.property('enumerable', false);
  140. });
  141. it('has the right arity', function () {
  142. expect(Number.isFinite).to.have.property('length', 1);
  143. });
  144. it('should work', function () {
  145. integers.map(Number.isFinite).forEach(expectTrue);
  146. infinities.map(Number.isFinite).forEach(expectFalse);
  147. expect(Number.isFinite(Infinity)).to.equal(false);
  148. expect(Number.isFinite(-Infinity)).to.equal(false);
  149. expect(Number.isFinite(NaN)).to.equal(false);
  150. expect(Number.isFinite(4)).to.equal(true);
  151. expect(Number.isFinite(4.5)).to.equal(true);
  152. expect(Number.isFinite('hi')).to.equal(false);
  153. expect(Number.isFinite('1.3')).to.equal(false);
  154. expect(Number.isFinite('51')).to.equal(false);
  155. expect(Number.isFinite(0)).to.equal(true);
  156. expect(Number.isFinite(-0)).to.equal(true);
  157. expect(Number.isFinite(valueOfThree)).to.equal(false);
  158. expect(Number.isFinite(valueOfNaN)).to.equal(false);
  159. expect(Number.isFinite(valueOfThrows)).to.equal(false);
  160. expect(Number.isFinite(toStringThrows)).to.equal(false);
  161. expect(Number.isFinite(toPrimitiveThrows)).to.equal(false);
  162. });
  163. it('should not be confused by type coercion', function () {
  164. nonNumbers.map(Number.isFinite).forEach(expectFalse);
  165. });
  166. });
  167. describe('.isInteger()', function () {
  168. if (!Object.prototype.hasOwnProperty.call(Number, 'isInteger')) {
  169. return it('exists', function () {
  170. expect(Number).to.have.property('isInteger');
  171. });
  172. }
  173. ifFunctionsHaveNamesIt('has the right name', function () {
  174. expect(Number.isInteger).to.have.property('name', 'isInteger');
  175. });
  176. it('is not enumerable', function () {
  177. expect(Number).ownPropertyDescriptor('isInteger').to.have.property('enumerable', false);
  178. });
  179. it('has the right arity', function () {
  180. expect(Number.isInteger).to.have.property('length', 1);
  181. });
  182. it('should be truthy on integers', function () {
  183. integers.map(Number.isInteger).forEach(expectTrue);
  184. expect(Number.isInteger(4)).to.equal(true);
  185. expect(Number.isInteger(4.0)).to.equal(true);
  186. expect(Number.isInteger(1801439850948)).to.equal(true);
  187. });
  188. it('should be false when the type is not number', function () {
  189. nonNumbers.forEach(function (thing) {
  190. expect(Number.isInteger(thing)).to.equal(false);
  191. });
  192. });
  193. it('should be false when NaN', function () {
  194. expect(Number.isInteger(NaN)).to.equal(false);
  195. });
  196. it('should be false when ∞', function () {
  197. expect(Number.isInteger(Infinity)).to.equal(false);
  198. expect(Number.isInteger(-Infinity)).to.equal(false);
  199. });
  200. it('should be false when number is not integer', function () {
  201. expect(Number.isInteger(3.4)).to.equal(false);
  202. expect(Number.isInteger(-3.4)).to.equal(false);
  203. });
  204. it('should be true when abs(number) is 2^53 or larger', function () {
  205. expect(Number.isInteger(Math.pow(2, 53))).to.equal(true);
  206. expect(Number.isInteger(Math.pow(2, 54))).to.equal(true);
  207. expect(Number.isInteger(-Math.pow(2, 53))).to.equal(true);
  208. expect(Number.isInteger(-Math.pow(2, 54))).to.equal(true);
  209. });
  210. it('should be true when abs(number) is less than 2^53', function () {
  211. var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
  212. safeIntegers.forEach(function (integer) {
  213. expect(Number.isInteger(integer)).to.equal(true);
  214. expect(Number.isInteger(-integer)).to.equal(true);
  215. });
  216. });
  217. });
  218. describe('.isSafeInteger()', function () {
  219. if (!Object.prototype.hasOwnProperty.call(Number, 'isSafeInteger')) {
  220. return it('exists', function () {
  221. expect(Number).to.have.property('isSafeInteger');
  222. });
  223. }
  224. ifFunctionsHaveNamesIt('has the right name', function () {
  225. expect(Number.isSafeInteger).to.have.property('name', 'isSafeInteger');
  226. });
  227. it('is not enumerable', function () {
  228. expect(Number).ownPropertyDescriptor('isSafeInteger').to.have.property('enumerable', false);
  229. });
  230. it('has the right arity', function () {
  231. expect(Number.isSafeInteger).to.have.property('length', 1);
  232. });
  233. it('should be truthy on integers', function () {
  234. integers.map(Number.isSafeInteger).forEach(expectTrue);
  235. expect(Number.isSafeInteger(4)).to.equal(true);
  236. expect(Number.isSafeInteger(4.0)).to.equal(true);
  237. expect(Number.isSafeInteger(1801439850948)).to.equal(true);
  238. });
  239. it('should be false when the type is not number', function () {
  240. nonNumbers.forEach(function (thing) {
  241. expect(Number.isSafeInteger(thing)).to.equal(false);
  242. });
  243. });
  244. it('should be false when NaN', function () {
  245. expect(Number.isSafeInteger(NaN)).to.equal(false);
  246. });
  247. it('should be false when ∞', function () {
  248. expect(Number.isSafeInteger(Infinity)).to.equal(false);
  249. expect(Number.isSafeInteger(-Infinity)).to.equal(false);
  250. });
  251. it('should be false when number is not integer', function () {
  252. expect(Number.isSafeInteger(3.4)).to.equal(false);
  253. expect(Number.isSafeInteger(-3.4)).to.equal(false);
  254. });
  255. it('should be false when abs(number) is 2^53 or larger', function () {
  256. expect(Number.isSafeInteger(Math.pow(2, 53))).to.equal(false);
  257. expect(Number.isSafeInteger(Math.pow(2, 54))).to.equal(false);
  258. expect(Number.isSafeInteger(-Math.pow(2, 53))).to.equal(false);
  259. expect(Number.isSafeInteger(-Math.pow(2, 54))).to.equal(false);
  260. });
  261. it('should be true when abs(number) is less than 2^53', function () {
  262. var safeIntegers = [0, 1, Math.pow(2, 53) - 1];
  263. safeIntegers.forEach(function (integer) {
  264. expect(Number.isSafeInteger(integer)).to.equal(true);
  265. expect(Number.isSafeInteger(-integer)).to.equal(true);
  266. });
  267. });
  268. });
  269. describe('.isNaN()', function () {
  270. if (!Object.prototype.hasOwnProperty.call(Number, 'isNaN')) {
  271. return it('exists', function () {
  272. expect(Number).to.have.property('isNaN');
  273. });
  274. }
  275. ifFunctionsHaveNamesIt('has the right name', function () {
  276. expect(Number.isNaN).to.have.property('name', 'isNaN');
  277. });
  278. it('is not enumerable', function () {
  279. expect(Number).ownPropertyDescriptor('isNaN').to.have.property('enumerable', false);
  280. });
  281. it('has the right arity', function () {
  282. expect(Number.isNaN).to.have.property('length', 1);
  283. });
  284. it('should be truthy only on NaN', function () {
  285. integers.concat(nonIntegers).map(Number.isNaN).forEach(expectFalse);
  286. nonNumbers.map(Number.isNaN).forEach(expectFalse);
  287. expect(Number.isNaN(NaN)).to.equal(true);
  288. expect(Number.isNaN(0 / 0)).to.equal(true);
  289. expect(Number.isNaN(Number('NaN'))).to.equal(true);
  290. expect(Number.isNaN(4)).to.equal(false);
  291. expect(Number.isNaN(4.5)).to.equal(false);
  292. expect(Number.isNaN('hi')).to.equal(false);
  293. expect(Number.isNaN('1.3')).to.equal(false);
  294. expect(Number.isNaN('51')).to.equal(false);
  295. expect(Number.isNaN(0)).to.equal(false);
  296. expect(Number.isNaN(-0)).to.equal(false);
  297. expect(Number.isNaN(valueOfThree)).to.equal(false);
  298. expect(Number.isNaN(valueOfNaN)).to.equal(false);
  299. expect(Number.isNaN(valueOfThrows)).to.equal(false);
  300. expect(Number.isNaN(toStringThrows)).to.equal(false);
  301. expect(Number.isNaN(toPrimitiveThrows)).to.equal(false);
  302. });
  303. });
  304. describe('constructor', function () {
  305. it('behaves like the builtin', function () {
  306. expect((1).constructor).to.equal(Number);
  307. expect(Number()).to.equal(0);
  308. });
  309. describe('strings in the constructor', function () {
  310. it('works on normal literals', function () {
  311. expect(Number('1')).to.equal(+'1');
  312. expect(Number('1.1')).to.equal(+'1.1');
  313. expect(Number('0xA')).to.equal(0xA);
  314. });
  315. });
  316. describe('when called with a receiver', function () {
  317. it('returns a primitive when called with a primitive receiver', function () {
  318. expect((1).constructor(2)).to.equal(2);
  319. expect((1).constructor.call(null, 3)).to.equal(3);
  320. expect(Object(1).constructor.call(null, 5)).to.equal(5);
  321. });
  322. it('returns a primitive when called with a different number as an object receiver', function () {
  323. expect(Object(1).constructor(6)).to.equal(6);
  324. expect(Object(1).constructor.call(Object(1), 7)).to.equal(7);
  325. });
  326. it('returns a primitive when called with the same number as an object receiver', function () {
  327. expect(Object(1).constructor.call(Object(8), 8)).to.equal(8);
  328. });
  329. });
  330. it('works with boxed primitives', function () {
  331. expect(1 instanceof Number).to.equal(false);
  332. expect(Object(1) instanceof Number).to.equal(true);
  333. });
  334. it('works with `new`', function () {
  335. /* eslint-disable no-new-wrappers */
  336. var one = new Number('1');
  337. var a = new Number('0xA');
  338. /* eslint-enable no-new-wrappers */
  339. expect(+one).to.equal(1);
  340. expect(one instanceof Number).to.equal(true);
  341. expect(+a).to.equal(0xA);
  342. expect(a instanceof Number).to.equal(true);
  343. });
  344. it('works with binary literals in string form', function () {
  345. expect(Number('0b1')).to.equal(1);
  346. expect(Number(' 0b1')).to.equal(1);
  347. expect(Number('0b1 ')).to.equal(1);
  348. expect(Number('0b10')).to.equal(2);
  349. expect(Number(' 0b10')).to.equal(2);
  350. expect(Number('0b10 ')).to.equal(2);
  351. expect(Number('0b11')).to.equal(3);
  352. expect(Number(' 0b11')).to.equal(3);
  353. expect(Number('0b11 ')).to.equal(3);
  354. expect(Number({
  355. toString: function () { return '0b100'; },
  356. valueOf: function () { return '0b101'; }
  357. })).to.equal(5);
  358. });
  359. it('works with octal literals in string form', function () {
  360. expect(Number('0o7')).to.equal(7);
  361. expect(Number('0o10')).to.equal(8);
  362. expect(Number('0o11')).to.equal(9);
  363. expect(Number({
  364. toString: function () { return '0o12'; },
  365. valueOf: function () { return '0o13'; }
  366. })).to.equal(11);
  367. });
  368. it('should produce NaN', function () {
  369. expect(String(Number('0b12'))).to.equal('NaN');
  370. expect(String(Number('0o18'))).to.equal('NaN');
  371. expect(String(Number('0x1g'))).to.equal('NaN');
  372. expect(String(Number('+0b1'))).to.equal('NaN');
  373. expect(String(Number('+0o1'))).to.equal('NaN');
  374. expect(String(Number('+0x1'))).to.equal('NaN');
  375. expect(String(Number('-0b1'))).to.equal('NaN');
  376. expect(String(Number('-0o1'))).to.equal('NaN');
  377. expect(String(Number('-0x1'))).to.equal('NaN');
  378. });
  379. it('should work with well formed and poorly formed objects', function () {
  380. expect(String(Number({}))).to.equal('NaN');
  381. expect(String(Number({ valueOf: '1.1' }))).to.equal('NaN');
  382. expect(Number({ valueOf: '1.1', toString: function () { return '2.2'; } })).to.equal(2.2);
  383. expect(Number({ valueOf: function () { return '1.1'; }, toString: '2.2' })).to.equal(1.1);
  384. expect(Number({
  385. valueOf: function () { return '1.1'; },
  386. toString: function () { return '2.2'; }
  387. })).to.equal(1.1);
  388. expect(String(Number({ valueOf: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
  389. expect(String(Number({ toString: function () { return '-0x1a2b3c'; } }))).to.equal('NaN');
  390. expect(Number({ valueOf: function () { return '0o12345'; } })).to.equal(5349);
  391. expect(Number({ toString: function () { return '0o12345'; } })).to.equal(5349);
  392. expect(Number({ valueOf: function () { return '0b101010'; } })).to.equal(42);
  393. expect(Number({ toString: function () { return '0b101010'; } })).to.equal(42);
  394. });
  395. it('should work with correct whitespaces', function () {
  396. // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
  397. var nonWhitespaces = ['\u0085', '\u200b', '\ufffe'];
  398. expect(String(Number(nonWhitespaces[0] + '0' + nonWhitespaces[0]))).to.equal('NaN');
  399. expect(String(Number(nonWhitespaces[1] + '1' + nonWhitespaces[1]))).to.equal('NaN');
  400. expect(String(Number(nonWhitespaces[2] + '2' + nonWhitespaces[2]))).to.equal('NaN');
  401. });
  402. it.skip('it works with updated unicode values', function () {
  403. var whitespace = ' \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000';
  404. expect(String(Number(whitespace + '3' + whitespace))).to.equal('3');
  405. });
  406. });
  407. });