es5.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. 'use strict';
  2. var ES = require('../').ES5;
  3. var test = require('tape');
  4. var forEach = require('foreach');
  5. var is = require('object-is');
  6. var debug = require('object-inspect');
  7. var v = require('./helpers/values');
  8. test('ToPrimitive', function (t) {
  9. t.test('primitives', function (st) {
  10. var testPrimitive = function (primitive) {
  11. st.ok(is(ES.ToPrimitive(primitive), primitive), debug(primitive) + ' is returned correctly');
  12. };
  13. forEach(v.primitives, testPrimitive);
  14. st.end();
  15. });
  16. t.test('objects', function (st) {
  17. st.equal(ES.ToPrimitive(v.coercibleObject), v.coercibleObject.valueOf(), 'coercibleObject coerces to valueOf');
  18. st.equal(ES.ToPrimitive(v.coercibleObject, Number), v.coercibleObject.valueOf(), 'coercibleObject with hint Number coerces to valueOf');
  19. st.equal(ES.ToPrimitive(v.coercibleObject, String), v.coercibleObject.toString(), 'coercibleObject with hint String coerces to toString');
  20. st.equal(ES.ToPrimitive(v.coercibleFnObject), v.coercibleFnObject.toString(), 'coercibleFnObject coerces to toString');
  21. st.equal(ES.ToPrimitive(v.toStringOnlyObject), v.toStringOnlyObject.toString(), 'toStringOnlyObject returns toString');
  22. st.equal(ES.ToPrimitive(v.valueOfOnlyObject), v.valueOfOnlyObject.valueOf(), 'valueOfOnlyObject returns valueOf');
  23. st.equal(ES.ToPrimitive({}), '[object Object]', '{} with no hint coerces to Object#toString');
  24. st.equal(ES.ToPrimitive({}, String), '[object Object]', '{} with hint String coerces to Object#toString');
  25. st.equal(ES.ToPrimitive({}, Number), '[object Object]', '{} with hint Number coerces to Object#toString');
  26. st['throws'](function () { return ES.ToPrimitive(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError');
  27. st['throws'](function () { return ES.ToPrimitive(v.uncoercibleFnObject); }, TypeError, 'uncoercibleFnObject throws a TypeError');
  28. st.end();
  29. });
  30. t.end();
  31. });
  32. test('ToBoolean', function (t) {
  33. t.equal(false, ES.ToBoolean(undefined), 'undefined coerces to false');
  34. t.equal(false, ES.ToBoolean(null), 'null coerces to false');
  35. t.equal(false, ES.ToBoolean(false), 'false returns false');
  36. t.equal(true, ES.ToBoolean(true), 'true returns true');
  37. forEach([0, -0, NaN], function (falsyNumber) {
  38. t.equal(false, ES.ToBoolean(falsyNumber), 'falsy number ' + falsyNumber + ' coerces to false');
  39. });
  40. forEach([Infinity, 42, 1, -Infinity], function (truthyNumber) {
  41. t.equal(true, ES.ToBoolean(truthyNumber), 'truthy number ' + truthyNumber + ' coerces to true');
  42. });
  43. t.equal(false, ES.ToBoolean(''), 'empty string coerces to false');
  44. t.equal(true, ES.ToBoolean('foo'), 'nonempty string coerces to true');
  45. forEach(v.objects, function (obj) {
  46. t.equal(true, ES.ToBoolean(obj), 'object coerces to true');
  47. });
  48. t.equal(true, ES.ToBoolean(v.uncoercibleObject), 'uncoercibleObject coerces to true');
  49. t.end();
  50. });
  51. test('ToNumber', function (t) {
  52. t.ok(is(NaN, ES.ToNumber(undefined)), 'undefined coerces to NaN');
  53. t.ok(is(ES.ToNumber(null), 0), 'null coerces to +0');
  54. t.ok(is(ES.ToNumber(false), 0), 'false coerces to +0');
  55. t.equal(1, ES.ToNumber(true), 'true coerces to 1');
  56. t.ok(is(NaN, ES.ToNumber(NaN)), 'NaN returns itself');
  57. forEach([0, -0, 42, Infinity, -Infinity], function (num) {
  58. t.equal(num, ES.ToNumber(num), num + ' returns itself');
  59. });
  60. forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) {
  61. t.ok(is(+numString, ES.ToNumber(numString)), '"' + numString + '" coerces to ' + Number(numString));
  62. });
  63. forEach(v.objects, function (object) {
  64. t.ok(is(ES.ToNumber(object), ES.ToNumber(ES.ToPrimitive(object))), 'object ' + object + ' coerces to same as ToPrimitive of object does');
  65. });
  66. t['throws'](function () { return ES.ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  67. t.end();
  68. });
  69. test('ToInteger', function (t) {
  70. t.ok(is(0, ES.ToInteger(NaN)), 'NaN coerces to +0');
  71. forEach([0, Infinity, 42], function (num) {
  72. t.ok(is(num, ES.ToInteger(num)), num + ' returns itself');
  73. t.ok(is(-num, ES.ToInteger(-num)), '-' + num + ' returns itself');
  74. });
  75. t.equal(3, ES.ToInteger(Math.PI), 'pi returns 3');
  76. t['throws'](function () { return ES.ToInteger(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  77. t.end();
  78. });
  79. test('ToInt32', function (t) {
  80. t.ok(is(0, ES.ToInt32(NaN)), 'NaN coerces to +0');
  81. forEach([0, Infinity], function (num) {
  82. t.ok(is(0, ES.ToInt32(num)), num + ' returns +0');
  83. t.ok(is(0, ES.ToInt32(-num)), '-' + num + ' returns +0');
  84. });
  85. t['throws'](function () { return ES.ToInt32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  86. t.ok(is(ES.ToInt32(0x100000000), 0), '2^32 returns +0');
  87. t.ok(is(ES.ToInt32(0x100000000 - 1), -1), '2^32 - 1 returns -1');
  88. t.ok(is(ES.ToInt32(0x80000000), -0x80000000), '2^31 returns -2^31');
  89. t.ok(is(ES.ToInt32(0x80000000 - 1), 0x80000000 - 1), '2^31 - 1 returns 2^31 - 1');
  90. forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
  91. t.ok(is(ES.ToInt32(num), ES.ToInt32(ES.ToUint32(num))), 'ToInt32(x) === ToInt32(ToUint32(x)) for 0x' + num.toString(16));
  92. t.ok(is(ES.ToInt32(-num), ES.ToInt32(ES.ToUint32(-num))), 'ToInt32(x) === ToInt32(ToUint32(x)) for -0x' + num.toString(16));
  93. });
  94. t.end();
  95. });
  96. test('ToUint32', function (t) {
  97. t.ok(is(0, ES.ToUint32(NaN)), 'NaN coerces to +0');
  98. forEach([0, Infinity], function (num) {
  99. t.ok(is(0, ES.ToUint32(num)), num + ' returns +0');
  100. t.ok(is(0, ES.ToUint32(-num)), '-' + num + ' returns +0');
  101. });
  102. t['throws'](function () { return ES.ToUint32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  103. t.ok(is(ES.ToUint32(0x100000000), 0), '2^32 returns +0');
  104. t.ok(is(ES.ToUint32(0x100000000 - 1), 0x100000000 - 1), '2^32 - 1 returns 2^32 - 1');
  105. t.ok(is(ES.ToUint32(0x80000000), 0x80000000), '2^31 returns 2^31');
  106. t.ok(is(ES.ToUint32(0x80000000 - 1), 0x80000000 - 1), '2^31 - 1 returns 2^31 - 1');
  107. forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
  108. t.ok(is(ES.ToUint32(num), ES.ToUint32(ES.ToInt32(num))), 'ToUint32(x) === ToUint32(ToInt32(x)) for 0x' + num.toString(16));
  109. t.ok(is(ES.ToUint32(-num), ES.ToUint32(ES.ToInt32(-num))), 'ToUint32(x) === ToUint32(ToInt32(x)) for -0x' + num.toString(16));
  110. });
  111. t.end();
  112. });
  113. test('ToUint16', function (t) {
  114. t.ok(is(0, ES.ToUint16(NaN)), 'NaN coerces to +0');
  115. forEach([0, Infinity], function (num) {
  116. t.ok(is(0, ES.ToUint16(num)), num + ' returns +0');
  117. t.ok(is(0, ES.ToUint16(-num)), '-' + num + ' returns +0');
  118. });
  119. t['throws'](function () { return ES.ToUint16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  120. t.ok(is(ES.ToUint16(0x100000000), 0), '2^32 returns +0');
  121. t.ok(is(ES.ToUint16(0x100000000 - 1), 0x10000 - 1), '2^32 - 1 returns 2^16 - 1');
  122. t.ok(is(ES.ToUint16(0x80000000), 0), '2^31 returns +0');
  123. t.ok(is(ES.ToUint16(0x80000000 - 1), 0x10000 - 1), '2^31 - 1 returns 2^16 - 1');
  124. t.ok(is(ES.ToUint16(0x10000), 0), '2^16 returns +0');
  125. t.ok(is(ES.ToUint16(0x10000 - 1), 0x10000 - 1), '2^16 - 1 returns 2^16 - 1');
  126. t.end();
  127. });
  128. test('ToString', function (t) {
  129. t['throws'](function () { return ES.ToString(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
  130. t.end();
  131. });
  132. test('ToObject', function (t) {
  133. t['throws'](function () { return ES.ToObject(undefined); }, TypeError, 'undefined throws');
  134. t['throws'](function () { return ES.ToObject(null); }, TypeError, 'null throws');
  135. forEach(v.numbers, function (number) {
  136. var obj = ES.ToObject(number);
  137. t.equal(typeof obj, 'object', 'number ' + number + ' coerces to object');
  138. t.equal(true, obj instanceof Number, 'object of ' + number + ' is Number object');
  139. t.ok(is(obj.valueOf(), number), 'object of ' + number + ' coerces to ' + number);
  140. });
  141. t.end();
  142. });
  143. test('CheckObjectCoercible', function (t) {
  144. t['throws'](function () { return ES.CheckObjectCoercible(undefined); }, TypeError, 'undefined throws');
  145. t['throws'](function () { return ES.CheckObjectCoercible(null); }, TypeError, 'null throws');
  146. var checkCoercible = function (value) {
  147. t.doesNotThrow(function () { return ES.CheckObjectCoercible(value); }, debug(value) + ' does not throw');
  148. };
  149. forEach(v.objects.concat(v.nonNullPrimitives), checkCoercible);
  150. t.end();
  151. });
  152. test('IsCallable', function (t) {
  153. t.equal(true, ES.IsCallable(function () {}), 'function is callable');
  154. var nonCallables = [/a/g, {}, Object.prototype, NaN].concat(v.primitives);
  155. forEach(nonCallables, function (nonCallable) {
  156. t.equal(false, ES.IsCallable(nonCallable), debug(nonCallable) + ' is not callable');
  157. });
  158. t.end();
  159. });
  160. test('SameValue', function (t) {
  161. t.equal(true, ES.SameValue(NaN, NaN), 'NaN is SameValue as NaN');
  162. t.equal(false, ES.SameValue(0, -0), '+0 is not SameValue as -0');
  163. forEach(v.objects.concat(v.primitives), function (val) {
  164. t.equal(val === val, ES.SameValue(val, val), debug(val) + ' is SameValue to itself');
  165. });
  166. t.end();
  167. });
  168. test('Type', function (t) {
  169. t.equal(ES.Type(), 'Undefined', 'Type() is Undefined');
  170. t.equal(ES.Type(undefined), 'Undefined', 'Type(undefined) is Undefined');
  171. t.equal(ES.Type(null), 'Null', 'Type(null) is Null');
  172. t.equal(ES.Type(true), 'Boolean', 'Type(true) is Boolean');
  173. t.equal(ES.Type(false), 'Boolean', 'Type(false) is Boolean');
  174. t.equal(ES.Type(0), 'Number', 'Type(0) is Number');
  175. t.equal(ES.Type(NaN), 'Number', 'Type(NaN) is Number');
  176. t.equal(ES.Type('abc'), 'String', 'Type("abc") is String');
  177. t.equal(ES.Type(function () {}), 'Object', 'Type(function () {}) is Object');
  178. t.equal(ES.Type({}), 'Object', 'Type({}) is Object');
  179. t.end();
  180. });
  181. test('IsPropertyDescriptor', function (t) {
  182. forEach(v.primitives, function (primitive) {
  183. t.equal(ES.IsPropertyDescriptor(primitive), false, debug(primitive) + ' is not a Property Descriptor');
  184. });
  185. t.equal(ES.IsPropertyDescriptor({ invalid: true }), false, 'invalid keys not allowed on a Property Descriptor');
  186. t.equal(ES.IsPropertyDescriptor({}), true, 'empty object is an incomplete Property Descriptor');
  187. t.equal(ES.IsPropertyDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is a Property Descriptor');
  188. t.equal(ES.IsPropertyDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is a Property Descriptor');
  189. t.equal(ES.IsPropertyDescriptor(v.dataDescriptor()), true, 'data descriptor is a Property Descriptor');
  190. t.equal(ES.IsPropertyDescriptor(v.genericDescriptor()), true, 'generic descriptor is a Property Descriptor');
  191. t['throws'](
  192. function () { ES.IsPropertyDescriptor(v.bothDescriptor()); },
  193. TypeError,
  194. 'a Property Descriptor can not be both a Data and an Accessor Descriptor'
  195. );
  196. t['throws'](
  197. function () { ES.IsPropertyDescriptor(v.bothDescriptorWritable()); },
  198. TypeError,
  199. 'a Property Descriptor can not be both a Data and an Accessor Descriptor'
  200. );
  201. t.end();
  202. });
  203. test('IsAccessorDescriptor', function (t) {
  204. forEach(v.nonNullPrimitives.concat(null), function (primitive) {
  205. t['throws'](function () { ES.IsAccessorDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor');
  206. });
  207. t.equal(ES.IsAccessorDescriptor(), false, 'no value is not an Accessor Descriptor');
  208. t.equal(ES.IsAccessorDescriptor(undefined), false, 'undefined value is not an Accessor Descriptor');
  209. t.equal(ES.IsAccessorDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is an Accessor Descriptor');
  210. t.equal(ES.IsAccessorDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is an Accessor Descriptor');
  211. t.equal(ES.IsAccessorDescriptor(v.dataDescriptor()), false, 'data descriptor is not an Accessor Descriptor');
  212. t.equal(ES.IsAccessorDescriptor(v.genericDescriptor()), false, 'generic descriptor is not an Accessor Descriptor');
  213. t.end();
  214. });
  215. test('IsDataDescriptor', function (t) {
  216. forEach(v.nonNullPrimitives.concat(null), function (primitive) {
  217. t['throws'](function () { ES.IsDataDescriptor(primitive); }, TypeError, debug(primitive) + ' is not a Property Descriptor');
  218. });
  219. t.equal(ES.IsDataDescriptor(), false, 'no value is not a Data Descriptor');
  220. t.equal(ES.IsDataDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
  221. t.equal(ES.IsDataDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a Data Descriptor');
  222. t.equal(ES.IsDataDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a Data Descriptor');
  223. t.equal(ES.IsDataDescriptor(v.dataDescriptor()), true, 'data descriptor is a Data Descriptor');
  224. t.equal(ES.IsDataDescriptor(v.genericDescriptor()), false, 'generic descriptor is not a Data Descriptor');
  225. t.end();
  226. });
  227. test('IsGenericDescriptor', function (t) {
  228. forEach(v.nonNullPrimitives.concat(null), function (primitive) {
  229. t['throws'](
  230. function () { ES.IsGenericDescriptor(primitive); },
  231. TypeError,
  232. debug(primitive) + ' is not a Property Descriptor'
  233. );
  234. });
  235. t.equal(ES.IsGenericDescriptor(), false, 'no value is not a Data Descriptor');
  236. t.equal(ES.IsGenericDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
  237. t.equal(ES.IsGenericDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a generic Descriptor');
  238. t.equal(ES.IsGenericDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a generic Descriptor');
  239. t.equal(ES.IsGenericDescriptor(v.dataDescriptor()), false, 'data descriptor is not a generic Descriptor');
  240. t.equal(ES.IsGenericDescriptor(v.genericDescriptor()), true, 'generic descriptor is a generic Descriptor');
  241. t.end();
  242. });
  243. test('FromPropertyDescriptor', function (t) {
  244. t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined');
  245. t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined');
  246. forEach(v.nonNullPrimitives.concat(null), function (primitive) {
  247. t['throws'](
  248. function () { ES.FromPropertyDescriptor(primitive); },
  249. TypeError,
  250. debug(primitive) + ' is not a Property Descriptor'
  251. );
  252. });
  253. var accessor = v.accessorDescriptor();
  254. t.deepEqual(ES.FromPropertyDescriptor(accessor), {
  255. get: accessor['[[Get]]'],
  256. set: accessor['[[Set]]'],
  257. enumerable: !!accessor['[[Enumerable]]'],
  258. configurable: !!accessor['[[Configurable]]']
  259. });
  260. var mutator = v.mutatorDescriptor();
  261. t.deepEqual(ES.FromPropertyDescriptor(mutator), {
  262. get: mutator['[[Get]]'],
  263. set: mutator['[[Set]]'],
  264. enumerable: !!mutator['[[Enumerable]]'],
  265. configurable: !!mutator['[[Configurable]]']
  266. });
  267. var data = v.dataDescriptor();
  268. t.deepEqual(ES.FromPropertyDescriptor(data), {
  269. value: data['[[Value]]'],
  270. writable: data['[[Writable]]'],
  271. enumerable: !!data['[[Enumerable]]'],
  272. configurable: !!data['[[Configurable]]']
  273. });
  274. t['throws'](
  275. function () { ES.FromPropertyDescriptor(v.genericDescriptor()); },
  276. TypeError,
  277. 'a complete Property Descriptor is required'
  278. );
  279. t.end();
  280. });
  281. test('ToPropertyDescriptor', function (t) {
  282. forEach(v.nonNullPrimitives.concat(null), function (primitive) {
  283. t['throws'](
  284. function () { ES.ToPropertyDescriptor(primitive); },
  285. TypeError,
  286. debug(primitive) + ' is not an Object'
  287. );
  288. });
  289. var accessor = v.accessorDescriptor();
  290. t.deepEqual(ES.ToPropertyDescriptor({
  291. get: accessor['[[Get]]'],
  292. enumerable: !!accessor['[[Enumerable]]'],
  293. configurable: !!accessor['[[Configurable]]']
  294. }), accessor);
  295. var mutator = v.mutatorDescriptor();
  296. t.deepEqual(ES.ToPropertyDescriptor({
  297. set: mutator['[[Set]]'],
  298. enumerable: !!mutator['[[Enumerable]]'],
  299. configurable: !!mutator['[[Configurable]]']
  300. }), mutator);
  301. var data = v.descriptors.nonConfigurable(v.dataDescriptor());
  302. t.deepEqual(ES.ToPropertyDescriptor({
  303. value: data['[[Value]]'],
  304. writable: data['[[Writable]]'],
  305. configurable: !!data['[[Configurable]]']
  306. }), data);
  307. var both = v.bothDescriptor();
  308. t['throws'](
  309. function () {
  310. ES.ToPropertyDescriptor({ get: both['[[Get]]'], value: both['[[Value]]'] });
  311. },
  312. TypeError,
  313. 'data and accessor descriptors are mutually exclusive'
  314. );
  315. t['throws'](
  316. function () { ES.ToPropertyDescriptor({ get: 'not callable' }); },
  317. TypeError,
  318. '"get" must be undefined or callable'
  319. );
  320. t['throws'](
  321. function () { ES.ToPropertyDescriptor({ set: 'not callable' }); },
  322. TypeError,
  323. '"set" must be undefined or callable'
  324. );
  325. t.end();
  326. });
  327. test('Abstract Equality Comparison', function (t) {
  328. t.test('same types use ===', function (st) {
  329. forEach(v.primitives.concat(v.objects), function (value) {
  330. st.equal(ES['Abstract Equality Comparison'](value, value), value === value, debug(value) + ' is abstractly equal to itself');
  331. });
  332. st.end();
  333. });
  334. t.test('different types coerce', function (st) {
  335. var pairs = [
  336. [null, undefined],
  337. [3, '3'],
  338. [true, '3'],
  339. [true, 3],
  340. [false, 0],
  341. [false, '0'],
  342. [3, [3]],
  343. ['3', [3]],
  344. [true, [1]],
  345. [false, [0]],
  346. [String(v.coercibleObject), v.coercibleObject],
  347. [Number(String(v.coercibleObject)), v.coercibleObject],
  348. [Number(v.coercibleObject), v.coercibleObject],
  349. [String(Number(v.coercibleObject)), v.coercibleObject]
  350. ];
  351. forEach(pairs, function (pair) {
  352. var a = pair[0];
  353. var b = pair[1];
  354. // eslint-disable-next-line eqeqeq
  355. st.equal(ES['Abstract Equality Comparison'](a, b), a == b, debug(a) + ' == ' + debug(b));
  356. // eslint-disable-next-line eqeqeq
  357. st.equal(ES['Abstract Equality Comparison'](b, a), b == a, debug(b) + ' == ' + debug(a));
  358. });
  359. st.end();
  360. });
  361. t.end();
  362. });
  363. test('Strict Equality Comparison', function (t) {
  364. t.test('same types use ===', function (st) {
  365. forEach(v.primitives.concat(v.objects), function (value) {
  366. st.equal(ES['Strict Equality Comparison'](value, value), value === value, debug(value) + ' is strictly equal to itself');
  367. });
  368. st.end();
  369. });
  370. t.test('different types are not ===', function (st) {
  371. var pairs = [
  372. [null, undefined],
  373. [3, '3'],
  374. [true, '3'],
  375. [true, 3],
  376. [false, 0],
  377. [false, '0'],
  378. [3, [3]],
  379. ['3', [3]],
  380. [true, [1]],
  381. [false, [0]],
  382. [String(v.coercibleObject), v.coercibleObject],
  383. [Number(String(v.coercibleObject)), v.coercibleObject],
  384. [Number(v.coercibleObject), v.coercibleObject],
  385. [String(Number(v.coercibleObject)), v.coercibleObject]
  386. ];
  387. forEach(pairs, function (pair) {
  388. var a = pair[0];
  389. var b = pair[1];
  390. st.equal(ES['Strict Equality Comparison'](a, b), a === b, debug(a) + ' === ' + debug(b));
  391. st.equal(ES['Strict Equality Comparison'](b, a), b === a, debug(b) + ' === ' + debug(a));
  392. });
  393. st.end();
  394. });
  395. t.end();
  396. });
  397. test('Abstract Relational Comparison', function (t) {
  398. t.test('at least one operand is NaN', function (st) {
  399. st.equal(ES['Abstract Relational Comparison'](NaN, {}, true), undefined, 'LeftFirst: first is NaN, returns undefined');
  400. st.equal(ES['Abstract Relational Comparison']({}, NaN, true), undefined, 'LeftFirst: second is NaN, returns undefined');
  401. st.equal(ES['Abstract Relational Comparison'](NaN, {}, false), undefined, '!LeftFirst: first is NaN, returns undefined');
  402. st.equal(ES['Abstract Relational Comparison']({}, NaN, false), undefined, '!LeftFirst: second is NaN, returns undefined');
  403. st.end();
  404. });
  405. t.equal(ES['Abstract Relational Comparison'](3, 4, true), true, 'LeftFirst: 3 is less than 4');
  406. t.equal(ES['Abstract Relational Comparison'](4, 3, true), false, 'LeftFirst: 3 is not less than 4');
  407. t.equal(ES['Abstract Relational Comparison'](3, 4, false), true, '!LeftFirst: 3 is less than 4');
  408. t.equal(ES['Abstract Relational Comparison'](4, 3, false), false, '!LeftFirst: 3 is not less than 4');
  409. t.equal(ES['Abstract Relational Comparison']('3', '4', true), true, 'LeftFirst: "3" is less than "4"');
  410. t.equal(ES['Abstract Relational Comparison']('4', '3', true), false, 'LeftFirst: "3" is not less than "4"');
  411. t.equal(ES['Abstract Relational Comparison']('3', '4', false), true, '!LeftFirst: "3" is less than "4"');
  412. t.equal(ES['Abstract Relational Comparison']('4', '3', false), false, '!LeftFirst: "3" is not less than "4"');
  413. t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, true), true, 'LeftFirst: coercible object is less than 42');
  414. t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, true), false, 'LeftFirst: 42 is not less than coercible object');
  415. t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, false), true, '!LeftFirst: coercible object is less than 42');
  416. t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, false), false, '!LeftFirst: 42 is not less than coercible object');
  417. t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', true), false, 'LeftFirst: coercible object is not less than "3"');
  418. t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, true), false, 'LeftFirst: "3" is not less than coercible object');
  419. t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', false), false, '!LeftFirst: coercible object is not less than "3"');
  420. t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, false), false, '!LeftFirst: "3" is not less than coercible object');
  421. t.end();
  422. });
  423. test('FromPropertyDescriptor', function (t) {
  424. t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined');
  425. t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined');
  426. forEach(v.nonUndefinedPrimitives, function (primitive) {
  427. t['throws'](
  428. function () { ES.FromPropertyDescriptor(primitive); },
  429. TypeError,
  430. debug(primitive) + ' is not a Property Descriptor'
  431. );
  432. });
  433. var accessor = v.accessorDescriptor();
  434. t.deepEqual(ES.FromPropertyDescriptor(accessor), {
  435. get: accessor['[[Get]]'],
  436. set: accessor['[[Set]]'],
  437. enumerable: !!accessor['[[Enumerable]]'],
  438. configurable: !!accessor['[[Configurable]]']
  439. });
  440. var mutator = v.mutatorDescriptor();
  441. t.deepEqual(ES.FromPropertyDescriptor(mutator), {
  442. get: mutator['[[Get]]'],
  443. set: mutator['[[Set]]'],
  444. enumerable: !!mutator['[[Enumerable]]'],
  445. configurable: !!mutator['[[Configurable]]']
  446. });
  447. var data = v.dataDescriptor();
  448. t.deepEqual(ES.FromPropertyDescriptor(data), {
  449. value: data['[[Value]]'],
  450. writable: data['[[Writable]]'],
  451. enumerable: !!data['[[Enumerable]]'],
  452. configurable: !!data['[[Configurable]]']
  453. });
  454. t['throws'](
  455. function () { ES.FromPropertyDescriptor(v.genericDescriptor()); },
  456. TypeError,
  457. 'a complete Property Descriptor is required'
  458. );
  459. t.end();
  460. });