blob: 11f7cc69d4029c682a6b90dbe7106ce86b8c8a5c [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001'use strict';
2
3var tape = require('tape');
4
5var forEach = require('foreach');
6var debug = require('object-inspect');
7var assign = require('object.assign');
8var keys = require('object-keys');
9var has = require('has');
10var arrowFns = require('make-arrow-function').list();
11var hasStrictMode = require('has-strict-mode')();
12var functionsHaveNames = require('functions-have-names')();
13var functionsHaveConfigurableNames = require('functions-have-names').functionsHaveConfigurableNames();
14var hasBigInts = require('has-bigints')();
15
16var $getProto = require('../helpers/getProto');
17var $setProto = require('../helpers/setProto');
18var defineProperty = require('./helpers/defineProperty');
19var getInferredName = require('../helpers/getInferredName');
20var getOwnPropertyDescriptor = require('../helpers/getOwnPropertyDescriptor');
21var assertRecordTests = require('./helpers/assertRecord');
22var v = require('es-value-fixtures');
23var diffOps = require('./diffOps');
24
25var $BigInt = hasBigInts ? BigInt : null;
26
27var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;
28
29var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false
30
31// IE 9 does not throw in strict mode when writability/configurability/extensibility is violated
32var noThrowOnStrictViolation = (function () {
33 try {
34 delete [].length;
35 return true;
36 } catch (e) {
37 }
38 return false;
39}());
40
41var makeTest = function makeTest(skips) {
42 return function test(opName, maybeOpts, maybeCb) {
43 var origOpts = arguments.length > 2 ? maybeOpts : {};
44 var opts = assign(
45 {},
46 origOpts,
47 { skip: (skips && skips[opName]) || origOpts.skip }
48 );
49 var cb = arguments.length > 2 ? maybeCb : maybeOpts;
50 return tape(opName, opts, cb);
51 };
52};
53
54var leadingPoo = '\uD83D';
55var trailingPoo = '\uDCA9';
56var wholePoo = leadingPoo + trailingPoo;
57
58var getArraySubclassWithSpeciesConstructor = function getArraySubclass(speciesConstructor) {
59 var Bar = function Bar() {
60 var inst = [];
61 Object.setPrototypeOf(inst, Bar.prototype);
62 defineProperty(inst, 'constructor', { value: Bar });
63 return inst;
64 };
65 Bar.prototype = Object.create(Array.prototype);
66 Object.setPrototypeOf(Bar, Array);
67 defineProperty(Bar, Symbol.species, { value: speciesConstructor });
68
69 return Bar;
70};
71
72var testIterator = function (t, iterator, expected) {
73 var resultCount = 0;
74 var result;
75 while (result = iterator.next(), !result.done) { // eslint-disable-line no-sequences
76 t.deepEqual(result, { done: false, value: expected[resultCount] }, 'result ' + resultCount);
77 resultCount += 1;
78 }
79 t.equal(resultCount, expected.length, 'expected ' + expected.length + ', got ' + resultCount);
80};
81
82var hasSpecies = v.hasSymbols && Symbol.species;
83
84var hasLastIndex = 'lastIndex' in (/a/).exec('a'); // IE 8
85var hasGroups = 'groups' in (/a/).exec('a'); // modern engines
86var kludgeMatch = function kludgeMatch(R, matchObject) {
87 if (hasGroups) {
88 assign(matchObject, { groups: matchObject.groups });
89 }
90 if (hasLastIndex) {
91 assign(matchObject, { lastIndex: R.lastIndex });
92 }
93 return matchObject;
94};
95
96var testEnumerableOwnNames = function (t, enumerableOwnNames) {
97 forEach(v.primitives, function (nonObject) {
98 t['throws'](
99 function () { enumerableOwnNames(nonObject); },
100 debug(nonObject) + ' is not an Object'
101 );
102 });
103
104 var Child = function Child() {
105 this.own = {};
106 };
107 Child.prototype = {
108 inherited: {}
109 };
110
111 var obj = new Child();
112
113 t.equal('own' in obj, true, 'has "own"');
114 t.equal(has(obj, 'own'), true, 'has own "own"');
115 t.equal(Object.prototype.propertyIsEnumerable.call(obj, 'own'), true, 'has enumerable "own"');
116
117 t.equal('inherited' in obj, true, 'has "inherited"');
118 t.equal(has(obj, 'inherited'), false, 'has non-own "inherited"');
119 t.equal(has(Child.prototype, 'inherited'), true, 'Child.prototype has own "inherited"');
120 t.equal(Child.prototype.inherited, obj.inherited, 'Child.prototype.inherited === obj.inherited');
121 t.equal(Object.prototype.propertyIsEnumerable.call(Child.prototype, 'inherited'), true, 'has enumerable "inherited"');
122
123 t.equal('toString' in obj, true, 'has "toString"');
124 t.equal(has(obj, 'toString'), false, 'has non-own "toString"');
125 t.equal(has(Object.prototype, 'toString'), true, 'Object.prototype has own "toString"');
126 t.equal(Object.prototype.toString, obj.toString, 'Object.prototype.toString === obj.toString');
127 // eslint-disable-next-line no-useless-call
128 t.equal(Object.prototype.propertyIsEnumerable.call(Object.prototype, 'toString'), false, 'has non-enumerable "toString"');
129
130 return obj;
131};
132
133var testToNumber = function (t, ES, ToNumber) {
134 t.equal(NaN, ToNumber(undefined), 'undefined coerces to NaN');
135 t.equal(ToNumber(null), 0, 'null coerces to +0');
136 t.equal(ToNumber(false), 0, 'false coerces to +0');
137 t.equal(1, ToNumber(true), 'true coerces to 1');
138
139 t.test('numbers', function (st) {
140 st.equal(NaN, ToNumber(NaN), 'NaN returns itself');
141 forEach(v.zeroes.concat(v.infinities, 42), function (num) {
142 st.equal(num, ToNumber(num), num + ' returns itself');
143 });
144 forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) {
145 st.equal(+numString, ToNumber(numString), '"' + numString + '" coerces to ' + Number(numString));
146 });
147 st.end();
148 });
149
150 t.test('objects', function (st) {
151 forEach(v.objects, function (object) {
152 st.equal(ToNumber(object), ToNumber(ES.ToPrimitive(object)), 'object ' + object + ' coerces to same as ToPrimitive of object does');
153 });
154 st['throws'](function () { return ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
155 st.end();
156 });
157
158 // TODO: check if this applies to ES5
159 t.test('binary literals', function (st) {
160 st.equal(ToNumber('0b10'), 2, '0b10 is 2');
161 st.equal(ToNumber({ toString: function () { return '0b11'; } }), 3, 'Object that toStrings to 0b11 is 3');
162
163 st.equal(ToNumber('0b12'), NaN, '0b12 is NaN');
164 st.equal(ToNumber({ toString: function () { return '0b112'; } }), NaN, 'Object that toStrings to 0b112 is NaN');
165 st.end();
166 });
167
168 // TODO: check if this applies to ES5
169 t.test('octal literals', function (st) {
170 st.equal(ToNumber('0o10'), 8, '0o10 is 8');
171 st.equal(ToNumber({ toString: function () { return '0o11'; } }), 9, 'Object that toStrings to 0o11 is 9');
172
173 st.equal(ToNumber('0o18'), NaN, '0o18 is NaN');
174 st.equal(ToNumber({ toString: function () { return '0o118'; } }), NaN, 'Object that toStrings to 0o118 is NaN');
175 st.end();
176 });
177
178 // TODO: check if this applies to ES5
179 t.test('signed hex numbers', function (st) {
180 st.equal(ToNumber('-0xF'), NaN, '-0xF is NaN');
181 st.equal(ToNumber(' -0xF '), NaN, 'space-padded -0xF is NaN');
182 st.equal(ToNumber('+0xF'), NaN, '+0xF is NaN');
183 st.equal(ToNumber(' +0xF '), NaN, 'space-padded +0xF is NaN');
184
185 st.end();
186 });
187
188 // TODO: check if this applies to ES5
189 t.test('trimming of whitespace and non-whitespace characters', function (st) {
190 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';
191 st.equal(0, ToNumber(whitespace + 0 + whitespace), 'whitespace is trimmed');
192
193 // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
194 var nonWhitespaces = {
195 '\\u0085': '\u0085',
196 '\\u200b': '\u200b',
197 '\\ufffe': '\ufffe'
198 };
199
200 forEach(nonWhitespaces, function (desc, nonWS) {
201 st.equal(ToNumber(nonWS + 0 + nonWS), NaN, 'non-whitespace ' + desc + ' not trimmed');
202 });
203
204 st.end();
205 });
206
207 // TODO: skip for ES5
208 forEach(v.symbols, function (symbol) {
209 t['throws'](
210 function () { ToNumber(symbol); },
211 TypeError,
212 'Symbols can’t be converted to a Number: ' + debug(symbol)
213 );
214 });
215
216 // TODO: check if this applies to ES5
217 t.test('dates', function (st) {
218 var invalid = new Date(NaN);
219 st.equal(ToNumber(invalid), NaN, 'invalid Date coerces to NaN');
220 var now = +new Date();
221 st.equal(ToNumber(new Date(now)), now, 'Date coerces to timestamp');
222 st.end();
223 });
224};
225
226var es5 = function ES5(ES, ops, expectedMissing, skips) {
227 var test = makeTest(skips);
228
229 test('has expected operations', function (t) {
230 var diff = diffOps(ES, ops, expectedMissing);
231
232 t.deepEqual(diff.extra, [], 'no extra ops');
233
234 t.deepEqual(diff.missing, [], 'no unexpected missing ops');
235
236 t.deepEqual(diff.extraMissing, [], 'no unexpected "expected missing" ops');
237
238 t.end();
239 });
240
241 test('ToPrimitive', function (t) {
242 t.test('primitives', function (st) {
243 var testPrimitive = function (primitive) {
244 st.equal(ES.ToPrimitive(primitive), primitive, debug(primitive) + ' is returned correctly');
245 };
246 forEach(v.primitives, testPrimitive);
247 st.end();
248 });
249
250 t.test('objects', function (st) {
251 st.equal(ES.ToPrimitive(v.coercibleObject), 3, 'coercibleObject with no hint coerces to valueOf');
252 st.equal(ES.ToPrimitive({}), '[object Object]', '{} with no hint coerces to Object#toString');
253 st.equal(ES.ToPrimitive(v.coercibleObject, Number), 3, 'coercibleObject with hint Number coerces to valueOf');
254 st.equal(ES.ToPrimitive({}, Number), '[object Object]', '{} with hint Number coerces to NaN');
255 st.equal(ES.ToPrimitive(v.coercibleObject, String), 42, 'coercibleObject with hint String coerces to nonstringified toString');
256 st.equal(ES.ToPrimitive({}, String), '[object Object]', '{} with hint String coerces to Object#toString');
257 st.equal(ES.ToPrimitive(v.coercibleFnObject), v.coercibleFnObject.toString(), 'coercibleFnObject coerces to toString');
258 st.equal(ES.ToPrimitive(v.toStringOnlyObject), 7, 'toStringOnlyObject returns non-stringified toString');
259 st.equal(ES.ToPrimitive(v.valueOfOnlyObject), 4, 'valueOfOnlyObject returns valueOf');
260 st['throws'](function () { return ES.ToPrimitive(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError');
261 st['throws'](function () { return ES.ToPrimitive(v.uncoercibleFnObject); }, TypeError, 'uncoercibleFnObject throws a TypeError');
262 st.end();
263 });
264
265 t.test('dates', function (st) {
266 var invalid = new Date(NaN);
267 st.equal(ES.ToPrimitive(invalid), Date.prototype.toString.call(invalid), 'invalid Date coerces to Date#toString');
268 var now = new Date();
269 st.equal(ES.ToPrimitive(now), Date.prototype.toString.call(now), 'Date coerces to Date#toString');
270 st.end();
271 });
272
273 t.end();
274 });
275
276 test('ToBoolean', function (t) {
277 t.equal(false, ES.ToBoolean(undefined), 'undefined coerces to false');
278 t.equal(false, ES.ToBoolean(null), 'null coerces to false');
279 t.equal(false, ES.ToBoolean(false), 'false returns false');
280 t.equal(true, ES.ToBoolean(true), 'true returns true');
281
282 t.test('numbers', function (st) {
283 forEach(v.zeroes.concat(NaN), function (falsyNumber) {
284 st.equal(false, ES.ToBoolean(falsyNumber), 'falsy number ' + falsyNumber + ' coerces to false');
285 });
286 forEach(v.infinities.concat([42, 1]), function (truthyNumber) {
287 st.equal(true, ES.ToBoolean(truthyNumber), 'truthy number ' + truthyNumber + ' coerces to true');
288 });
289
290 st.end();
291 });
292
293 t.equal(false, ES.ToBoolean(''), 'empty string coerces to false');
294 t.equal(true, ES.ToBoolean('foo'), 'nonempty string coerces to true');
295
296 t.test('objects', function (st) {
297 forEach(v.objects, function (obj) {
298 st.equal(true, ES.ToBoolean(obj), 'object coerces to true');
299 });
300 st.equal(true, ES.ToBoolean(v.uncoercibleObject), 'uncoercibleObject coerces to true');
301
302 st.end();
303 });
304
305 t.end();
306 });
307
308 test('ToNumber', function (t) {
309 t.equal(NaN, ES.ToNumber(undefined), 'undefined coerces to NaN');
310 t.equal(ES.ToNumber(null), 0, 'null coerces to +0');
311 t.equal(ES.ToNumber(false), 0, 'false coerces to +0');
312 t.equal(1, ES.ToNumber(true), 'true coerces to 1');
313
314 t.test('numbers', function (st) {
315 st.equal(NaN, ES.ToNumber(NaN), 'NaN returns itself');
316 forEach(v.zeroes.concat(v.infinities, 42), function (num) {
317 st.equal(num, ES.ToNumber(num), num + ' returns itself');
318 });
319 forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) {
320 st.equal(+numString, ES.ToNumber(numString), '"' + numString + '" coerces to ' + Number(numString));
321 });
322 st.end();
323 });
324
325 t.test('objects', function (st) {
326 forEach(v.objects, function (object) {
327 st.equal(ES.ToNumber(object), ES.ToNumber(ES.ToPrimitive(object)), 'object ' + object + ' coerces to same as ToPrimitive of object does');
328 });
329 st['throws'](function () { return ES.ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
330 st.end();
331 });
332
333 t.test('binary literals', function (st) {
334 st.equal(ES.ToNumber('0b10'), NaN, '0b10 is NaN');
335 st.equal(ES.ToNumber({ toString: function () { return '0b11'; } }), NaN, 'Object that toStrings to 0b11 is NaN');
336
337 st.equal(ES.ToNumber('0b12'), NaN, '0b12 is NaN');
338 st.equal(ES.ToNumber({ toString: function () { return '0b112'; } }), NaN, 'Object that toStrings to 0b112 is NaN');
339 st.end();
340 });
341
342 t.test('octal literals', function (st) {
343 st.equal(ES.ToNumber('0o10'), NaN, '0o10 is NaN');
344 st.equal(ES.ToNumber({ toString: function () { return '0o11'; } }), NaN, 'Object that toStrings to 0o11 is NaN');
345
346 st.equal(ES.ToNumber('0o18'), NaN, '0o18 is NaN');
347 st.equal(ES.ToNumber({ toString: function () { return '0o118'; } }), NaN, 'Object that toStrings to 0o118 is NaN');
348 st.end();
349 });
350
351 t.test('signed hex numbers', function (st) {
352 st.equal(ES.ToNumber('-0xF'), NaN, '-0xF is NaN');
353 st.equal(ES.ToNumber(' -0xF '), NaN, 'space-padded -0xF is NaN');
354 st.equal(ES.ToNumber('+0xF'), NaN, '+0xF is NaN');
355 st.equal(ES.ToNumber(' +0xF '), NaN, 'space-padded +0xF is NaN');
356
357 st.end();
358 });
359
360 // TODO: check if this applies to ES5
361 t.test('trimming of whitespace and non-whitespace characters', function (st) {
362 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\u0085';
363 st.equal(ES.ToNumber(whitespace + 0 + whitespace), 0, 'whitespace is trimmed');
364
365 // Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
366 var nonWhitespaces = {
367 '\\u200b': '\u200b',
368 '\\ufffe': '\ufffe'
369 };
370
371 forEach(nonWhitespaces, function (desc, nonWS) {
372 st.equal(ES.ToNumber(nonWS + 0 + nonWS), NaN, 'non-whitespace ' + desc + ' not trimmed');
373 });
374
375 st.end();
376 });
377
378 t.test('dates', function (st) {
379 var invalid = new Date(NaN);
380 st.equal(ES.ToNumber(invalid), NaN, 'invalid Date coerces to NaN');
381 var now = +new Date();
382 st.equal(ES.ToNumber(new Date(now)), now, 'Date coerces to timestamp');
383 st.end();
384 });
385
386 t.end();
387 });
388
389 test('ToInteger', function (t) {
390 forEach([NaN], function (num) {
391 t.equal(0, ES.ToInteger(num), debug(num) + ' returns +0');
392 });
393 forEach(v.zeroes.concat(v.infinities, 42), function (num) {
394 t.equal(num, ES.ToInteger(num), debug(num) + ' returns itself');
395 t.equal(-num, ES.ToInteger(-num), '-' + debug(num) + ' returns itself');
396 });
397 t.equal(3, ES.ToInteger(Math.PI), 'pi returns 3');
398 t['throws'](function () { return ES.ToInteger(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
399 t.end();
400 });
401
402 test('ToInt32', function (t) {
403 t.equal(ES.ToInt32(NaN), 0, 'NaN coerces to +0');
404 forEach(v.zeroes.concat(v.infinities), function (num) {
405 t.equal(ES.ToInt32(num), 0, num + ' returns +0');
406 t.equal(ES.ToInt32(-num), 0, '-' + num + ' returns +0');
407 });
408 t['throws'](function () { return ES.ToInt32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
409 t.equal(ES.ToInt32(0x100000000), 0, '2^32 returns +0');
410 t.equal(ES.ToInt32(0x100000000 - 1), -1, '2^32 - 1 returns -1');
411 t.equal(ES.ToInt32(0x80000000), -0x80000000, '2^31 returns -2^31');
412 t.equal(ES.ToInt32(0x80000000 - 1), 0x80000000 - 1, '2^31 - 1 returns 2^31 - 1');
413 forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
414 t.equal(ES.ToInt32(num), ES.ToInt32(ES.ToUint32(num)), 'ToInt32(x) === ToInt32(ToUint32(x)) for 0x' + num.toString(16));
415 t.equal(ES.ToInt32(-num), ES.ToInt32(ES.ToUint32(-num)), 'ToInt32(x) === ToInt32(ToUint32(x)) for -0x' + num.toString(16));
416 });
417 t.end();
418 });
419
420 test('ToUint32', function (t) {
421 t.equal(0, ES.ToUint32(NaN), 'NaN coerces to +0');
422 forEach([0, Infinity], function (num) {
423 t.equal(0, ES.ToUint32(num), num + ' returns +0');
424 t.equal(0, ES.ToUint32(-num), '-' + num + ' returns +0');
425 });
426 t['throws'](function () { return ES.ToUint32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
427 t.equal(ES.ToUint32(0x100000000), 0, '2^32 returns +0');
428 t.equal(ES.ToUint32(0x100000000 - 1), 0x100000000 - 1, '2^32 - 1 returns 2^32 - 1');
429 t.equal(ES.ToUint32(0x80000000), 0x80000000, '2^31 returns 2^31');
430 t.equal(ES.ToUint32(0x80000000 - 1), 0x80000000 - 1, '2^31 - 1 returns 2^31 - 1');
431 forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
432 t.equal(ES.ToUint32(num), ES.ToUint32(ES.ToInt32(num)), 'ToUint32(x) === ToUint32(ToInt32(x)) for 0x' + num.toString(16));
433 t.equal(ES.ToUint32(-num), ES.ToUint32(ES.ToInt32(-num)), 'ToUint32(x) === ToUint32(ToInt32(x)) for -0x' + num.toString(16));
434 });
435 t.end();
436 });
437
438 test('ToUint16', function (t) {
439 t.equal(0, ES.ToUint16(NaN), 'NaN coerces to +0');
440 forEach([0, Infinity], function (num) {
441 t.equal(0, ES.ToUint16(num), num + ' returns +0');
442 t.equal(0, ES.ToUint16(-num), '-' + num + ' returns +0');
443 });
444 t['throws'](function () { return ES.ToUint16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
445 t.equal(ES.ToUint16(0x100000000), 0, '2^32 returns +0');
446 t.equal(ES.ToUint16(0x100000000 - 1), 0x10000 - 1, '2^32 - 1 returns 2^16 - 1');
447 t.equal(ES.ToUint16(0x80000000), 0, '2^31 returns +0');
448 t.equal(ES.ToUint16(0x80000000 - 1), 0x10000 - 1, '2^31 - 1 returns 2^16 - 1');
449 t.equal(ES.ToUint16(0x10000), 0, '2^16 returns +0');
450 t.equal(ES.ToUint16(0x10000 - 1), 0x10000 - 1, '2^16 - 1 returns 2^16 - 1');
451 t.end();
452 });
453
454 test('ToString', function (t) {
455 forEach(v.objects.concat(v.nonSymbolPrimitives), function (item) {
456 t.equal(ES.ToString(item), String(item), 'ES.ToString(' + debug(item) + ') ToStrings to String(' + debug(item) + ')');
457 });
458
459 t['throws'](function () { return ES.ToString(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
460
461 t.end();
462 });
463
464 test('ToObject', function (t) {
465 t['throws'](function () { return ES.ToObject(undefined); }, TypeError, 'undefined throws');
466 t['throws'](function () { return ES.ToObject(null); }, TypeError, 'null throws');
467 forEach(v.numbers, function (number) {
468 var obj = ES.ToObject(number);
469 t.equal(typeof obj, 'object', 'number ' + number + ' coerces to object');
470 t.equal(true, obj instanceof Number, 'object of ' + number + ' is Number object');
471 t.equal(obj.valueOf(), number, 'object of ' + number + ' coerces to ' + number);
472 });
473 t.end();
474 });
475
476 test('CheckObjectCoercible', function (t) {
477 t['throws'](function () { return ES.CheckObjectCoercible(undefined); }, TypeError, 'undefined throws');
478 t['throws'](function () { return ES.CheckObjectCoercible(null); }, TypeError, 'null throws');
479 var checkCoercible = function (value) {
480 t.doesNotThrow(function () { return ES.CheckObjectCoercible(value); }, debug(value) + ' does not throw');
481 };
482 forEach(v.objects.concat(v.nonNullPrimitives), checkCoercible);
483 t.end();
484 });
485
486 test('IsCallable', function (t) {
487 t.equal(true, ES.IsCallable(function () {}), 'function is callable');
488 var nonCallables = [/a/g, {}, Object.prototype, NaN].concat(v.nonFunctions);
489 forEach(nonCallables, function (nonCallable) {
490 t.equal(false, ES.IsCallable(nonCallable), debug(nonCallable) + ' is not callable');
491 });
492 t.end();
493 });
494
495 test('SameValue', function (t) {
496 t.equal(true, ES.SameValue(NaN, NaN), 'NaN is SameValue as NaN');
497 t.equal(false, ES.SameValue(0, -0), '+0 is not SameValue as -0');
498 forEach(v.objects.concat(v.primitives), function (val) {
499 t.equal(val === val, ES.SameValue(val, val), debug(val) + ' is SameValue to itself');
500 });
501 t.end();
502 });
503
504 test('Type', function (t) {
505 t.equal(ES.Type(), 'Undefined', 'Type() is Undefined');
506 t.equal(ES.Type(undefined), 'Undefined', 'Type(undefined) is Undefined');
507 t.equal(ES.Type(null), 'Null', 'Type(null) is Null');
508 t.equal(ES.Type(true), 'Boolean', 'Type(true) is Boolean');
509 t.equal(ES.Type(false), 'Boolean', 'Type(false) is Boolean');
510 t.equal(ES.Type(0), 'Number', 'Type(0) is Number');
511 t.equal(ES.Type(NaN), 'Number', 'Type(NaN) is Number');
512 t.equal(ES.Type('abc'), 'String', 'Type("abc") is String');
513 t.equal(ES.Type(function () {}), 'Object', 'Type(function () {}) is Object');
514 t.equal(ES.Type({}), 'Object', 'Type({}) is Object');
515
516 t.end();
517 });
518
519 assertRecordTests(ES, test);
520
521 test('IsAccessorDescriptor', function (t) {
522 forEach(v.nonUndefinedPrimitives, function (primitive) {
523 t['throws'](
524 function () { ES.IsAccessorDescriptor(primitive); },
525 TypeError,
526 debug(primitive) + ' is not a Property Descriptor'
527 );
528 });
529
530 t.equal(ES.IsAccessorDescriptor(), false, 'no value is not an Accessor Descriptor');
531 t.equal(ES.IsAccessorDescriptor(undefined), false, 'undefined value is not an Accessor Descriptor');
532
533 t.equal(ES.IsAccessorDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is an Accessor Descriptor');
534 t.equal(ES.IsAccessorDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is an Accessor Descriptor');
535 t.equal(ES.IsAccessorDescriptor(v.dataDescriptor()), false, 'data descriptor is not an Accessor Descriptor');
536 t.equal(ES.IsAccessorDescriptor(v.genericDescriptor()), false, 'generic descriptor is not an Accessor Descriptor');
537
538 t.end();
539 });
540
541 test('IsDataDescriptor', function (t) {
542 forEach(v.nonUndefinedPrimitives, function (primitive) {
543 t['throws'](
544 function () { ES.IsDataDescriptor(primitive); },
545 TypeError,
546 debug(primitive) + ' is not a Property Descriptor'
547 );
548 });
549
550 t.equal(ES.IsDataDescriptor(), false, 'no value is not a Data Descriptor');
551 t.equal(ES.IsDataDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
552
553 t.equal(ES.IsDataDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a Data Descriptor');
554 t.equal(ES.IsDataDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a Data Descriptor');
555 t.equal(ES.IsDataDescriptor(v.dataDescriptor()), true, 'data descriptor is a Data Descriptor');
556 t.equal(ES.IsDataDescriptor(v.genericDescriptor()), false, 'generic descriptor is not a Data Descriptor');
557
558 t.end();
559 });
560
561 test('IsGenericDescriptor', function (t) {
562 forEach(v.nonUndefinedPrimitives, function (primitive) {
563 t['throws'](
564 function () { ES.IsGenericDescriptor(primitive); },
565 TypeError,
566 debug(primitive) + ' is not a Property Descriptor'
567 );
568 });
569
570 t.equal(ES.IsGenericDescriptor(), false, 'no value is not a Data Descriptor');
571 t.equal(ES.IsGenericDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
572
573 t.equal(ES.IsGenericDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a generic Descriptor');
574 t.equal(ES.IsGenericDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a generic Descriptor');
575 t.equal(ES.IsGenericDescriptor(v.dataDescriptor()), false, 'data descriptor is not a generic Descriptor');
576
577 t.equal(ES.IsGenericDescriptor(v.genericDescriptor()), true, 'generic descriptor is a generic Descriptor');
578
579 t.end();
580 });
581
582 test('FromPropertyDescriptor', function (t) {
583 t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined');
584 t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined');
585
586 forEach(v.nonNullPrimitives.concat(null), function (primitive) {
587 t['throws'](
588 function () { ES.FromPropertyDescriptor(primitive); },
589 TypeError,
590 debug(primitive) + ' is not a Property Descriptor'
591 );
592 });
593
594 var accessor = v.accessorDescriptor();
595 t.deepEqual(ES.FromPropertyDescriptor(accessor), {
596 get: accessor['[[Get]]'],
597 set: accessor['[[Set]]'],
598 enumerable: !!accessor['[[Enumerable]]'],
599 configurable: !!accessor['[[Configurable]]']
600 });
601
602 var mutator = v.mutatorDescriptor();
603 t.deepEqual(ES.FromPropertyDescriptor(mutator), {
604 get: mutator['[[Get]]'],
605 set: mutator['[[Set]]'],
606 enumerable: !!mutator['[[Enumerable]]'],
607 configurable: !!mutator['[[Configurable]]']
608 });
609 var data = v.dataDescriptor();
610 t.deepEqual(ES.FromPropertyDescriptor(data), {
611 value: data['[[Value]]'],
612 writable: data['[[Writable]]'],
613 enumerable: !!data['[[Enumerable]]'],
614 configurable: !!data['[[Configurable]]']
615 });
616
617 t['throws'](
618 function () { ES.FromPropertyDescriptor(v.genericDescriptor()); },
619 TypeError,
620 'a complete Property Descriptor is required'
621 );
622
623 t.end();
624 });
625
626 test('ToPropertyDescriptor', function (t) {
627 forEach(v.nonUndefinedPrimitives, function (primitive) {
628 t['throws'](
629 function () { ES.ToPropertyDescriptor(primitive); },
630 TypeError,
631 debug(primitive) + ' is not an Object'
632 );
633 });
634
635 var accessor = v.accessorDescriptor();
636 t.deepEqual(ES.ToPropertyDescriptor({
637 get: accessor['[[Get]]'],
638 enumerable: !!accessor['[[Enumerable]]'],
639 configurable: !!accessor['[[Configurable]]']
640 }), accessor);
641
642 var mutator = v.mutatorDescriptor();
643 t.deepEqual(ES.ToPropertyDescriptor({
644 set: mutator['[[Set]]'],
645 enumerable: !!mutator['[[Enumerable]]'],
646 configurable: !!mutator['[[Configurable]]']
647 }), mutator);
648
649 var data = v.descriptors.nonConfigurable(v.dataDescriptor());
650 t.deepEqual(ES.ToPropertyDescriptor({
651 value: data['[[Value]]'],
652 writable: data['[[Writable]]'],
653 configurable: !!data['[[Configurable]]']
654 }), data);
655
656 var both = v.bothDescriptor();
657 t['throws'](
658 function () {
659 ES.ToPropertyDescriptor({ get: both['[[Get]]'], value: both['[[Value]]'] });
660 },
661 TypeError,
662 'data and accessor descriptors are mutually exclusive'
663 );
664
665 t['throws'](
666 function () { ES.ToPropertyDescriptor({ get: 'not callable' }); },
667 TypeError,
668 '"get" must be undefined or callable'
669 );
670
671 t['throws'](
672 function () { ES.ToPropertyDescriptor({ set: 'not callable' }); },
673 TypeError,
674 '"set" must be undefined or callable'
675 );
676
677 forEach(v.nonFunctions, function (nonFunction) {
678 if (typeof nonFunction !== 'undefined') {
679 t['throws'](
680 function () { ES.ToPropertyDescriptor({ get: nonFunction }); },
681 TypeError,
682 '`.get` has ' + debug(nonFunction) + ', which is not a Function'
683 );
684 t['throws'](
685 function () { ES.ToPropertyDescriptor({ set: nonFunction }); },
686 TypeError,
687 '`.set` has ' + debug(nonFunction) + ', which is not a Function'
688 );
689 }
690 });
691
692 forEach(['get', 'set'], function (accessorName) {
693 forEach(['value', 'writable'], function (dataName) {
694 var o = {};
695 o[accessorName] = undefined;
696 o[dataName] = undefined;
697
698 t['throws'](
699 function () { ES.ToPropertyDescriptor(o); },
700 TypeError,
701 accessorName + ' + ' + dataName + ' is invalid'
702 );
703 });
704 });
705
706 t.end();
707 });
708
709 test('Abstract Equality Comparison', function (t) {
710 t.test('same types use ===', function (st) {
711 forEach(v.primitives.concat(v.objects), function (value) {
712 st.equal(ES['Abstract Equality Comparison'](value, value), value === value, debug(value) + ' is abstractly equal to itself');
713 });
714 st.end();
715 });
716
717 t.test('different types coerce', function (st) {
718 var pairs = [
719 [null, undefined],
720 [3, '3'],
721 [true, '3'],
722 [true, 3],
723 [false, 0],
724 [false, '0'],
725 [3, [3]],
726 ['3', [3]],
727 [true, [1]],
728 [false, [0]],
729 [String(v.coercibleObject), v.coercibleObject],
730 [Number(String(v.coercibleObject)), v.coercibleObject],
731 [Number(v.coercibleObject), v.coercibleObject],
732 [String(Number(v.coercibleObject)), v.coercibleObject]
733 ];
734 forEach(pairs, function (pair) {
735 var a = pair[0];
736 var b = pair[1];
737 // eslint-disable-next-line eqeqeq
738 st.equal(ES['Abstract Equality Comparison'](a, b), a == b, debug(a) + ' == ' + debug(b));
739 // eslint-disable-next-line eqeqeq
740 st.equal(ES['Abstract Equality Comparison'](b, a), b == a, debug(b) + ' == ' + debug(a));
741 });
742 st.end();
743 });
744
745 t.end();
746 });
747
748 test('Strict Equality Comparison', function (t) {
749 t.test('same types use ===', function (st) {
750 forEach(v.primitives.concat(v.objects), function (value) {
751 st.equal(ES['Strict Equality Comparison'](value, value), value === value, debug(value) + ' is strictly equal to itself');
752 });
753 st.end();
754 });
755
756 t.test('different types are not ===', function (st) {
757 var pairs = [
758 [null, undefined],
759 [3, '3'],
760 [true, '3'],
761 [true, 3],
762 [false, 0],
763 [false, '0'],
764 [3, [3]],
765 ['3', [3]],
766 [true, [1]],
767 [false, [0]],
768 [String(v.coercibleObject), v.coercibleObject],
769 [Number(String(v.coercibleObject)), v.coercibleObject],
770 [Number(v.coercibleObject), v.coercibleObject],
771 [String(Number(v.coercibleObject)), v.coercibleObject]
772 ];
773 forEach(pairs, function (pair) {
774 var a = pair[0];
775 var b = pair[1];
776 st.equal(ES['Strict Equality Comparison'](a, b), a === b, debug(a) + ' === ' + debug(b));
777 st.equal(ES['Strict Equality Comparison'](b, a), b === a, debug(b) + ' === ' + debug(a));
778 });
779 st.end();
780 });
781
782 t.end();
783 });
784
785 test('Abstract Relational Comparison', function (t) {
786 t.test('at least one operand is NaN', function (st) {
787 st.equal(ES['Abstract Relational Comparison'](NaN, {}, true), undefined, 'LeftFirst: first is NaN, returns undefined');
788 st.equal(ES['Abstract Relational Comparison']({}, NaN, true), undefined, 'LeftFirst: second is NaN, returns undefined');
789 st.equal(ES['Abstract Relational Comparison'](NaN, {}, false), undefined, '!LeftFirst: first is NaN, returns undefined');
790 st.equal(ES['Abstract Relational Comparison']({}, NaN, false), undefined, '!LeftFirst: second is NaN, returns undefined');
791 st.end();
792 });
793
794 forEach(v.nonBooleans, function (nonBoolean) {
795 t['throws'](
796 function () { ES['Abstract Relational Comparison'](3, 4, nonBoolean); },
797 TypeError,
798 debug(nonBoolean) + ' is not a Boolean'
799 );
800 });
801
802 forEach(v.zeroes, function (zero) {
803 t.equal(ES['Abstract Relational Comparison'](zero, 1, true), true, 'LeftFirst: ' + debug(zero) + ' is less than 1');
804 t.equal(ES['Abstract Relational Comparison'](zero, 1, false), true, '!LeftFirst: ' + debug(zero) + ' is less than 1');
805 t.equal(ES['Abstract Relational Comparison'](1, zero, true), false, 'LeftFirst: 1 is not less than ' + debug(zero));
806 t.equal(ES['Abstract Relational Comparison'](1, zero, false), false, '!LeftFirst: 1 is not less than ' + debug(zero));
807
808 t.equal(ES['Abstract Relational Comparison'](zero, zero, true), false, 'LeftFirst: ' + debug(zero) + ' is not less than ' + debug(zero));
809 t.equal(ES['Abstract Relational Comparison'](zero, zero, false), false, '!LeftFirst: ' + debug(zero) + ' is not less than ' + debug(zero));
810 });
811
812 t.equal(ES['Abstract Relational Comparison'](Infinity, -Infinity, true), false, 'LeftFirst: ∞ is not less than -∞');
813 t.equal(ES['Abstract Relational Comparison'](Infinity, -Infinity, false), false, '!LeftFirst: ∞ is not less than -∞');
814 t.equal(ES['Abstract Relational Comparison'](-Infinity, Infinity, true), true, 'LeftFirst: -∞ is less than ∞');
815 t.equal(ES['Abstract Relational Comparison'](-Infinity, Infinity, false), true, '!LeftFirst: -∞ is less than ∞');
816 t.equal(ES['Abstract Relational Comparison'](-Infinity, 0, true), true, 'LeftFirst: -∞ is less than +0');
817 t.equal(ES['Abstract Relational Comparison'](-Infinity, 0, false), true, '!LeftFirst: -∞ is less than +0');
818 t.equal(ES['Abstract Relational Comparison'](0, -Infinity, true), false, 'LeftFirst: +0 is not less than -∞');
819 t.equal(ES['Abstract Relational Comparison'](0, -Infinity, false), false, '!LeftFirst: +0 is not less than -∞');
820
821 t.equal(ES['Abstract Relational Comparison'](3, 4, true), true, 'LeftFirst: 3 is less than 4');
822 t.equal(ES['Abstract Relational Comparison'](4, 3, true), false, 'LeftFirst: 3 is not less than 4');
823 t.equal(ES['Abstract Relational Comparison'](3, 4, false), true, '!LeftFirst: 3 is less than 4');
824 t.equal(ES['Abstract Relational Comparison'](4, 3, false), false, '!LeftFirst: 3 is not less than 4');
825
826 t.equal(ES['Abstract Relational Comparison']('3', '4', true), true, 'LeftFirst: "3" is less than "4"');
827 t.equal(ES['Abstract Relational Comparison']('4', '3', true), false, 'LeftFirst: "3" is not less than "4"');
828 t.equal(ES['Abstract Relational Comparison']('3', '4', false), true, '!LeftFirst: "3" is less than "4"');
829 t.equal(ES['Abstract Relational Comparison']('4', '3', false), false, '!LeftFirst: "3" is not less than "4"');
830
831 t.equal(ES['Abstract Relational Comparison']('a', 'abc', true), true, 'LeftFirst: "a" is less than "abc"');
832 t.equal(ES['Abstract Relational Comparison']('abc', 'a', true), false, 'LeftFirst: "abc" is not less than "a"');
833 t.equal(ES['Abstract Relational Comparison']('a', 'abc', false), true, '!LeftFirst: "a" is less than "abc"');
834 t.equal(ES['Abstract Relational Comparison']('abc', 'a', false), false, '!LeftFirst: "abc" is not less than "a"');
835
836 t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, true), true, 'LeftFirst: coercible object is less than 42');
837 t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, true), false, 'LeftFirst: 42 is not less than coercible object');
838 t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, false), true, '!LeftFirst: coercible object is less than 42');
839 t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, false), false, '!LeftFirst: 42 is not less than coercible object');
840
841 t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', true), false, 'LeftFirst: coercible object is not less than "3"');
842 t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, true), false, 'LeftFirst: "3" is not less than coercible object');
843 t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', false), false, '!LeftFirst: coercible object is not less than "3"');
844 t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, false), false, '!LeftFirst: "3" is not less than coercible object');
845
846 t.end();
847 });
848
849 test('SecFromTime', function (t) {
850 var now = new Date();
851 t.equal(ES.SecFromTime(now.getTime()), now.getUTCSeconds(), 'second from Date timestamp matches getUTCSeconds');
852 t.end();
853 });
854
855 test('MinFromTime', function (t) {
856 var now = new Date();
857 t.equal(ES.MinFromTime(now.getTime()), now.getUTCMinutes(), 'minute from Date timestamp matches getUTCMinutes');
858 t.end();
859 });
860
861 test('HourFromTime', function (t) {
862 var now = new Date();
863 t.equal(ES.HourFromTime(now.getTime()), now.getUTCHours(), 'hour from Date timestamp matches getUTCHours');
864 t.end();
865 });
866
867 test('msFromTime', function (t) {
868 var now = new Date();
869 t.equal(ES.msFromTime(now.getTime()), now.getUTCMilliseconds(), 'ms from Date timestamp matches getUTCMilliseconds');
870 t.end();
871 });
872
873 var msPerSecond = 1e3;
874 var msPerMinute = 60 * msPerSecond;
875 var msPerHour = 60 * msPerMinute;
876 var msPerDay = 24 * msPerHour;
877
878 test('Day', function (t) {
879 var time = Date.UTC(2019, 8, 10, 2, 3, 4, 5);
880 var add = 2.5;
881 var later = new Date(time + (add * msPerDay));
882
883 t.equal(ES.Day(later.getTime()), ES.Day(time) + Math.floor(add), 'adding 2.5 days worth of ms, gives a Day delta of 2');
884 t.end();
885 });
886
887 test('DayFromYear', function (t) {
888 t.equal(ES.DayFromYear(2021) - ES.DayFromYear(2020), 366, '2021 is a leap year, has 366 days');
889 t.equal(ES.DayFromYear(2020) - ES.DayFromYear(2019), 365, '2020 is not a leap year, has 365 days');
890 t.equal(ES.DayFromYear(2019) - ES.DayFromYear(2018), 365, '2019 is not a leap year, has 365 days');
891 t.equal(ES.DayFromYear(2018) - ES.DayFromYear(2017), 365, '2018 is not a leap year, has 365 days');
892 t.equal(ES.DayFromYear(2017) - ES.DayFromYear(2016), 366, '2017 is a leap year, has 366 days');
893
894 t.end();
895 });
896
897 test('TimeWithinDay', function (t) {
898 var time = Date.UTC(2019, 8, 10, 2, 3, 4, 5);
899 var add = 2.5;
900 var later = new Date(time + (add * msPerDay));
901
902 t.equal(ES.TimeWithinDay(later.getTime()), ES.TimeWithinDay(time) + (0.5 * msPerDay), 'adding 2.5 days worth of ms, gives a TimeWithinDay delta of +0.5');
903 t.end();
904 });
905
906 test('TimeFromYear', function (t) {
907 for (var i = 1900; i < 2100; i += 1) {
908 t.equal(ES.TimeFromYear(i), Date.UTC(i, 0, 1), 'TimeFromYear matches a Date object’s year: ' + i);
909 }
910 t.end();
911 });
912
913 test('YearFromTime', function (t) {
914 for (var i = 1900; i < 2100; i += 1) {
915 t.equal(ES.YearFromTime(Date.UTC(i, 0, 1)), i, 'YearFromTime matches a Date object’s year on 1/1: ' + i);
916 t.equal(ES.YearFromTime(Date.UTC(i, 10, 1)), i, 'YearFromTime matches a Date object’s year on 10/1: ' + i);
917 }
918 t.end();
919 });
920
921 test('WeekDay', function (t) {
922 var now = new Date();
923 var today = now.getUTCDay();
924 for (var i = 0; i < 7; i += 1) {
925 var weekDay = ES.WeekDay(now.getTime() + (i * msPerDay));
926 t.equal(weekDay, (today + i) % 7, i + ' days after today (' + today + '), WeekDay is ' + weekDay);
927 }
928 t.end();
929 });
930
931 test('DaysInYear', function (t) {
932 t.equal(ES.DaysInYear(2021), 365, '2021 is not a leap year');
933 t.equal(ES.DaysInYear(2020), 366, '2020 is a leap year');
934 t.equal(ES.DaysInYear(2019), 365, '2019 is not a leap year');
935 t.equal(ES.DaysInYear(2018), 365, '2018 is not a leap year');
936 t.equal(ES.DaysInYear(2017), 365, '2017 is not a leap year');
937 t.equal(ES.DaysInYear(2016), 366, '2016 is a leap year');
938 t.equal(ES.DaysInYear(2000), 366, '2000 is a leap year');
939 t.equal(ES.DaysInYear(1900), 365, '1900 is not a leap year');
940
941 t.end();
942 });
943
944 test('InLeapYear', function (t) {
945 t.equal(ES.InLeapYear(Date.UTC(2021, 0, 1)), 0, '2021 is not a leap year');
946 t.equal(ES.InLeapYear(Date.UTC(2020, 0, 1)), 1, '2020 is a leap year');
947 t.equal(ES.InLeapYear(Date.UTC(2019, 0, 1)), 0, '2019 is not a leap year');
948 t.equal(ES.InLeapYear(Date.UTC(2018, 0, 1)), 0, '2018 is not a leap year');
949 t.equal(ES.InLeapYear(Date.UTC(2017, 0, 1)), 0, '2017 is not a leap year');
950 t.equal(ES.InLeapYear(Date.UTC(2016, 0, 1)), 1, '2016 is a leap year');
951
952 t.end();
953 });
954
955 test('DayWithinYear', function (t) {
956 t.equal(ES.DayWithinYear(Date.UTC(2019, 0, 1)), 0, '1/1 is the 1st day');
957 t.equal(ES.DayWithinYear(Date.UTC(2019, 11, 31)), 364, '12/31 is the 365th day in a non leap year');
958 t.equal(ES.DayWithinYear(Date.UTC(2016, 11, 31)), 365, '12/31 is the 366th day in a leap year');
959
960 t.end();
961 });
962
963 test('MonthFromTime', function (t) {
964 t.equal(ES.MonthFromTime(Date.UTC(2019, 0, 1)), 0, 'non-leap: 1/1 gives January');
965 t.equal(ES.MonthFromTime(Date.UTC(2019, 0, 31)), 0, 'non-leap: 1/31 gives January');
966 t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 1)), 1, 'non-leap: 2/1 gives February');
967 t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 28)), 1, 'non-leap: 2/28 gives February');
968 t.equal(ES.MonthFromTime(Date.UTC(2019, 1, 29)), 2, 'non-leap: 2/29 gives March');
969 t.equal(ES.MonthFromTime(Date.UTC(2019, 2, 1)), 2, 'non-leap: 3/1 gives March');
970 t.equal(ES.MonthFromTime(Date.UTC(2019, 2, 31)), 2, 'non-leap: 3/31 gives March');
971 t.equal(ES.MonthFromTime(Date.UTC(2019, 3, 1)), 3, 'non-leap: 4/1 gives April');
972 t.equal(ES.MonthFromTime(Date.UTC(2019, 3, 30)), 3, 'non-leap: 4/30 gives April');
973 t.equal(ES.MonthFromTime(Date.UTC(2019, 4, 1)), 4, 'non-leap: 5/1 gives May');
974 t.equal(ES.MonthFromTime(Date.UTC(2019, 4, 31)), 4, 'non-leap: 5/31 gives May');
975 t.equal(ES.MonthFromTime(Date.UTC(2019, 5, 1)), 5, 'non-leap: 6/1 gives June');
976 t.equal(ES.MonthFromTime(Date.UTC(2019, 5, 30)), 5, 'non-leap: 6/30 gives June');
977 t.equal(ES.MonthFromTime(Date.UTC(2019, 6, 1)), 6, 'non-leap: 7/1 gives July');
978 t.equal(ES.MonthFromTime(Date.UTC(2019, 6, 31)), 6, 'non-leap: 7/31 gives July');
979 t.equal(ES.MonthFromTime(Date.UTC(2019, 7, 1)), 7, 'non-leap: 8/1 gives August');
980 t.equal(ES.MonthFromTime(Date.UTC(2019, 7, 30)), 7, 'non-leap: 8/30 gives August');
981 t.equal(ES.MonthFromTime(Date.UTC(2019, 8, 1)), 8, 'non-leap: 9/1 gives September');
982 t.equal(ES.MonthFromTime(Date.UTC(2019, 8, 30)), 8, 'non-leap: 9/30 gives September');
983 t.equal(ES.MonthFromTime(Date.UTC(2019, 9, 1)), 9, 'non-leap: 10/1 gives October');
984 t.equal(ES.MonthFromTime(Date.UTC(2019, 9, 31)), 9, 'non-leap: 10/31 gives October');
985 t.equal(ES.MonthFromTime(Date.UTC(2019, 10, 1)), 10, 'non-leap: 11/1 gives November');
986 t.equal(ES.MonthFromTime(Date.UTC(2019, 10, 30)), 10, 'non-leap: 11/30 gives November');
987 t.equal(ES.MonthFromTime(Date.UTC(2019, 11, 1)), 11, 'non-leap: 12/1 gives December');
988 t.equal(ES.MonthFromTime(Date.UTC(2019, 11, 31)), 11, 'non-leap: 12/31 gives December');
989
990 t.equal(ES.MonthFromTime(Date.UTC(2016, 0, 1)), 0, 'leap: 1/1 gives January');
991 t.equal(ES.MonthFromTime(Date.UTC(2016, 0, 31)), 0, 'leap: 1/31 gives January');
992 t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 1)), 1, 'leap: 2/1 gives February');
993 t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 28)), 1, 'leap: 2/28 gives February');
994 t.equal(ES.MonthFromTime(Date.UTC(2016, 1, 29)), 1, 'leap: 2/29 gives February');
995 t.equal(ES.MonthFromTime(Date.UTC(2016, 2, 1)), 2, 'leap: 3/1 gives March');
996 t.equal(ES.MonthFromTime(Date.UTC(2016, 2, 31)), 2, 'leap: 3/31 gives March');
997 t.equal(ES.MonthFromTime(Date.UTC(2016, 3, 1)), 3, 'leap: 4/1 gives April');
998 t.equal(ES.MonthFromTime(Date.UTC(2016, 3, 30)), 3, 'leap: 4/30 gives April');
999 t.equal(ES.MonthFromTime(Date.UTC(2016, 4, 1)), 4, 'leap: 5/1 gives May');
1000 t.equal(ES.MonthFromTime(Date.UTC(2016, 4, 31)), 4, 'leap: 5/31 gives May');
1001 t.equal(ES.MonthFromTime(Date.UTC(2016, 5, 1)), 5, 'leap: 6/1 gives June');
1002 t.equal(ES.MonthFromTime(Date.UTC(2016, 5, 30)), 5, 'leap: 6/30 gives June');
1003 t.equal(ES.MonthFromTime(Date.UTC(2016, 6, 1)), 6, 'leap: 7/1 gives July');
1004 t.equal(ES.MonthFromTime(Date.UTC(2016, 6, 31)), 6, 'leap: 7/31 gives July');
1005 t.equal(ES.MonthFromTime(Date.UTC(2016, 7, 1)), 7, 'leap: 8/1 gives August');
1006 t.equal(ES.MonthFromTime(Date.UTC(2016, 7, 30)), 7, 'leap: 8/30 gives August');
1007 t.equal(ES.MonthFromTime(Date.UTC(2016, 8, 1)), 8, 'leap: 9/1 gives September');
1008 t.equal(ES.MonthFromTime(Date.UTC(2016, 8, 30)), 8, 'leap: 9/30 gives September');
1009 t.equal(ES.MonthFromTime(Date.UTC(2016, 9, 1)), 9, 'leap: 10/1 gives October');
1010 t.equal(ES.MonthFromTime(Date.UTC(2016, 9, 31)), 9, 'leap: 10/31 gives October');
1011 t.equal(ES.MonthFromTime(Date.UTC(2016, 10, 1)), 10, 'leap: 11/1 gives November');
1012 t.equal(ES.MonthFromTime(Date.UTC(2016, 10, 30)), 10, 'leap: 11/30 gives November');
1013 t.equal(ES.MonthFromTime(Date.UTC(2016, 11, 1)), 11, 'leap: 12/1 gives December');
1014 t.equal(ES.MonthFromTime(Date.UTC(2016, 11, 31)), 11, 'leap: 12/31 gives December');
1015 t.end();
1016 });
1017
1018 test('DateFromTime', function (t) {
1019 var i;
1020 for (i = 1; i <= 28; i += 1) {
1021 t.equal(ES.DateFromTime(Date.UTC(2019, 1, i)), i, '2019.02.' + i + ' is date ' + i);
1022 }
1023 for (i = 1; i <= 29; i += 1) {
1024 t.equal(ES.DateFromTime(Date.UTC(2016, 1, i)), i, '2016.02.' + i + ' is date ' + i);
1025 }
1026 for (i = 1; i <= 30; i += 1) {
1027 t.equal(ES.DateFromTime(Date.UTC(2019, 2, i)), i, '2019.03.' + i + ' is date ' + i);
1028 t.equal(ES.DateFromTime(Date.UTC(2019, 3, i)), i, '2019.04.' + i + ' is date ' + i);
1029 t.equal(ES.DateFromTime(Date.UTC(2019, 5, i)), i, '2019.06.' + i + ' is date ' + i);
1030 t.equal(ES.DateFromTime(Date.UTC(2019, 7, i)), i, '2019.08.' + i + ' is date ' + i);
1031 t.equal(ES.DateFromTime(Date.UTC(2019, 8, i)), i, '2019.09.' + i + ' is date ' + i);
1032 t.equal(ES.DateFromTime(Date.UTC(2019, 10, i)), i, '2019.11.' + i + ' is date ' + i);
1033 }
1034 for (i = 1; i <= 31; i += 1) {
1035 t.equal(ES.DateFromTime(Date.UTC(2019, 0, i)), i, '2019.01.' + i + ' is date ' + i);
1036 t.equal(ES.DateFromTime(Date.UTC(2019, 4, i)), i, '2019.05.' + i + ' is date ' + i);
1037 t.equal(ES.DateFromTime(Date.UTC(2019, 6, i)), i, '2019.07.' + i + ' is date ' + i);
1038 t.equal(ES.DateFromTime(Date.UTC(2019, 9, i)), i, '2019.10.' + i + ' is date ' + i);
1039 t.equal(ES.DateFromTime(Date.UTC(2019, 11, i)), i, '2019.12.' + i + ' is date ' + i);
1040 }
1041 t.end();
1042 });
1043
1044 test('MakeDay', function (t) {
1045 forEach([NaN, Infinity, -Infinity], function (nonFiniteNumber) {
1046 t.equal(ES.MakeDay(nonFiniteNumber, 0, 0), NaN, 'year: ' + debug(nonFiniteNumber) + ' is not finite');
1047 t.equal(ES.MakeDay(0, nonFiniteNumber, 0), NaN, 'month: ' + debug(nonFiniteNumber) + ' is not finite');
1048 t.equal(ES.MakeDay(0, 0, nonFiniteNumber), NaN, 'date: ' + debug(nonFiniteNumber) + ' is not finite');
1049 });
1050
1051 var day2015 = 16687;
1052 t.equal(ES.MakeDay(2015, 8, 9), day2015, '2015.09.09 is day 16687');
1053 var day2016 = day2015 + 366; // 2016 is a leap year
1054 t.equal(ES.MakeDay(2016, 8, 9), day2016, '2015.09.09 is day 17053');
1055 var day2017 = day2016 + 365;
1056 t.equal(ES.MakeDay(2017, 8, 9), day2017, '2017.09.09 is day 17418');
1057 var day2018 = day2017 + 365;
1058 t.equal(ES.MakeDay(2018, 8, 9), day2018, '2018.09.09 is day 17783');
1059 var day2019 = day2018 + 365;
1060 t.equal(ES.MakeDay(2019, 8, 9), day2019, '2019.09.09 is day 18148');
1061
1062 t.end();
1063 });
1064
1065 test('MakeDate', function (t) {
1066 forEach(v.infinities.concat(NaN), function (nonFiniteNumber) {
1067 t.equal(ES.MakeDate(nonFiniteNumber, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `day`');
1068 t.equal(ES.MakeDate(0, nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `time`');
1069 });
1070 t.equal(ES.MakeDate(0, 0), 0, 'zero day and zero time is zero date');
1071 t.equal(ES.MakeDate(0, 123), 123, 'zero day and nonzero time is a date of the "time"');
1072 t.equal(ES.MakeDate(1, 0), msPerDay, 'day of 1 and zero time is a date of "ms per day"');
1073 t.equal(ES.MakeDate(3, 0), 3 * msPerDay, 'day of 3 and zero time is a date of thrice "ms per day"');
1074 t.equal(ES.MakeDate(1, 123), msPerDay + 123, 'day of 1 and nonzero time is a date of "ms per day" plus the "time"');
1075 t.equal(ES.MakeDate(3, 123), (3 * msPerDay) + 123, 'day of 3 and nonzero time is a date of thrice "ms per day" plus the "time"');
1076
1077 t.end();
1078 });
1079
1080 test('MakeTime', function (t) {
1081 forEach(v.infinities.concat(NaN), function (nonFiniteNumber) {
1082 t.equal(ES.MakeTime(nonFiniteNumber, 0, 0, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `hour`');
1083 t.equal(ES.MakeTime(0, nonFiniteNumber, 0, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `min`');
1084 t.equal(ES.MakeTime(0, 0, nonFiniteNumber, 0), NaN, debug(nonFiniteNumber) + ' is not a finite `sec`');
1085 t.equal(ES.MakeTime(0, 0, 0, nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `ms`');
1086 });
1087
1088 t.equal(
1089 ES.MakeTime(1.2, 2.3, 3.4, 4.5),
1090 (1 * msPerHour) + (2 * msPerMinute) + (3 * msPerSecond) + 4,
1091 'all numbers are converted to integer, multiplied by the right number of ms, and summed'
1092 );
1093
1094 t.end();
1095 });
1096
1097 test('TimeClip', function (t) {
1098 forEach(v.infinities.concat(NaN), function (nonFiniteNumber) {
1099 t.equal(ES.TimeClip(nonFiniteNumber), NaN, debug(nonFiniteNumber) + ' is not a finite `time`');
1100 });
1101 t.equal(ES.TimeClip(8.64e15 + 1), NaN, '8.64e15 is the largest magnitude considered "finite"');
1102 t.equal(ES.TimeClip(-8.64e15 - 1), NaN, '-8.64e15 is the largest magnitude considered "finite"');
1103
1104 forEach(v.zeroes.concat([-10, 10, +new Date()]), function (time) {
1105 t.looseEqual(ES.TimeClip(time), time, debug(time) + ' is a time of ' + debug(time));
1106 });
1107
1108 t.end();
1109 });
1110
1111 test('modulo', function (t) {
1112 t.equal(3 % 2, 1, '+3 % 2 is +1');
1113 t.equal(ES.modulo(3, 2), 1, '+3 mod 2 is +1');
1114
1115 t.equal(-3 % 2, -1, '-3 % 2 is -1');
1116 t.equal(ES.modulo(-3, 2), 1, '-3 mod 2 is +1');
1117 t.end();
1118 });
1119};
1120
1121var es2015 = function ES2015(ES, ops, expectedMissing, skips) {
1122 es5(ES, ops, expectedMissing, assign(assign({}, skips), {
1123 CheckObjectCoercible: true,
1124 FromPropertyDescriptor: true,
1125 ToNumber: true,
1126 ToString: true,
1127 Type: true
1128 }));
1129 var test = makeTest(skips);
1130
1131 var getNamelessFunction = function () {
1132 var f = Object(function () {});
1133 try {
1134 delete f.name;
1135 } catch (e) { /**/ }
1136 return f;
1137 };
1138
1139 test('AdvanceStringIndex', function (t) {
1140 forEach(v.nonStrings, function (nonString) {
1141 t['throws'](
1142 function () { ES.AdvanceStringIndex(nonString); },
1143 TypeError,
1144 '"S" argument must be a String; ' + debug(nonString) + ' is not'
1145 );
1146 });
1147
1148 var notInts = v.nonNumbers.concat(
1149 v.nonIntegerNumbers,
1150 v.infinities,
1151 [NaN, [], new Date(), Math.pow(2, 53), -1]
1152 );
1153 forEach(notInts, function (nonInt) {
1154 t['throws'](
1155 function () { ES.AdvanceStringIndex('abc', nonInt); },
1156 TypeError,
1157 '"index" argument must be an integer, ' + debug(nonInt) + ' is not.'
1158 );
1159 });
1160
1161 forEach(v.nonBooleans, function (nonBoolean) {
1162 t['throws'](
1163 function () { ES.AdvanceStringIndex('abc', 0, nonBoolean); },
1164 TypeError,
1165 debug(nonBoolean) + ' is not a Boolean'
1166 );
1167 });
1168
1169 var str = 'a' + wholePoo + 'c';
1170
1171 t.test('non-unicode mode', function (st) {
1172 for (var i = 0; i < str.length + 2; i += 1) {
1173 st.equal(ES.AdvanceStringIndex(str, i, false), i + 1, i + ' advances to ' + (i + 1));
1174 }
1175
1176 st.end();
1177 });
1178
1179 t.test('unicode mode', function (st) {
1180 st.equal(ES.AdvanceStringIndex(str, 0, true), 1, '0 advances to 1');
1181 st.equal(ES.AdvanceStringIndex(str, 1, true), 3, '1 advances to 3');
1182 st.equal(ES.AdvanceStringIndex(str, 2, true), 3, '2 advances to 3');
1183 st.equal(ES.AdvanceStringIndex(str, 3, true), 4, '3 advances to 4');
1184 st.equal(ES.AdvanceStringIndex(str, 4, true), 5, '4 advances to 5');
1185
1186 st.end();
1187 });
1188
1189 t.test('lone surrogates', function (st) {
1190 var halfPoo = 'a' + leadingPoo + 'c';
1191
1192 st.equal(ES.AdvanceStringIndex(halfPoo, 0, true), 1, '0 advances to 1');
1193 st.equal(ES.AdvanceStringIndex(halfPoo, 1, true), 2, '1 advances to 2');
1194 st.equal(ES.AdvanceStringIndex(halfPoo, 2, true), 3, '2 advances to 3');
1195 st.equal(ES.AdvanceStringIndex(halfPoo, 3, true), 4, '3 advances to 4');
1196
1197 st.end();
1198 });
1199
1200 t.test('surrogate pairs', function (st) {
1201 var lowestPair = String.fromCharCode('0xD800') + String.fromCharCode('0xDC00');
1202 var highestPair = String.fromCharCode('0xDBFF') + String.fromCharCode('0xDFFF');
1203
1204 st.equal(ES.AdvanceStringIndex(lowestPair, 0, true), 2, 'lowest surrogate pair, 0 -> 2');
1205 st.equal(ES.AdvanceStringIndex(highestPair, 0, true), 2, 'highest surrogate pair, 0 -> 2');
1206 st.equal(ES.AdvanceStringIndex(wholePoo, 0, true), 2, 'poop, 0 -> 2');
1207
1208 st.end();
1209 });
1210
1211 t.end();
1212 });
1213
1214 test('ArrayCreate', function (t) {
1215 forEach(v.nonIntegerNumbers.concat([-1]), function (nonIntegerNumber) {
1216 t['throws'](
1217 function () { ES.ArrayCreate(nonIntegerNumber); },
1218 TypeError,
1219 'length must be an integer number >= 0'
1220 );
1221 });
1222
1223 t['throws'](
1224 function () { ES.ArrayCreate(Math.pow(2, 32)); },
1225 RangeError,
1226 'length must be < 2**32'
1227 );
1228
1229 t.deepEqual(ES.ArrayCreate(-0), [], 'length of -0 creates an empty array');
1230 t.deepEqual(ES.ArrayCreate(0), [], 'length of +0 creates an empty array');
1231 // eslint-disable-next-line no-sparse-arrays, comma-spacing
1232 t.deepEqual(ES.ArrayCreate(1), [,], 'length of 1 creates a sparse array of length 1');
1233 // eslint-disable-next-line no-sparse-arrays, comma-spacing
1234 t.deepEqual(ES.ArrayCreate(2), [,,], 'length of 2 creates a sparse array of length 2');
1235
1236 t.test('proto argument', { skip: !$setProto }, function (st) {
1237 var fakeProto = {
1238 push: { toString: function () { return 'not array push'; } }
1239 };
1240 st.equal(ES.ArrayCreate(0, fakeProto).push, fakeProto.push, 'passing the proto argument works');
1241 st.end();
1242 });
1243
1244 t.end();
1245 });
1246
1247 test('ArraySetLength', function (t) {
1248 forEach(v.primitives.concat(v.objects), function (nonArray) {
1249 t['throws'](
1250 function () { ES.ArraySetLength(nonArray, { '[[Value]]': 0 }); },
1251 TypeError,
1252 'A: ' + debug(nonArray) + ' is not an Array'
1253 );
1254 });
1255
1256 forEach(v.nonUndefinedPrimitives, function (primitive) {
1257 t['throws'](
1258 function () { ES.ArraySetLength([], primitive); },
1259 TypeError,
1260 'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
1261 );
1262 });
1263
1264 t.test('making length nonwritable', { skip: !getOwnPropertyDescriptor }, function (st) {
1265 var a = [];
1266 ES.ArraySetLength(a, { '[[Writable]]': false });
1267 st.deepEqual(
1268 getOwnPropertyDescriptor(a, 'length'),
1269 {
1270 configurable: false,
1271 enumerable: false,
1272 value: 0,
1273 writable: false
1274 },
1275 'without a value, length becomes nonwritable'
1276 );
1277 st.end();
1278 });
1279
1280 forEach([-1, Math.pow(2, 32)].concat(v.nonIntegerNumbers), function (nonLength) {
1281 t['throws'](
1282 function () { ES.ArraySetLength([], { '[[Value]]': nonLength }); },
1283 RangeError,
1284 'a non-integer, negative, or > (2**31 - 1) is not a valid length: ' + debug(nonLength)
1285 );
1286 });
1287
1288 var arr = [];
1289 ES.ArraySetLength(arr, { '[[Value]]': 7 });
1290 t.equal(arr.length, 7, 'array now has a length of 7');
1291
1292 t.end();
1293 });
1294
1295 test('ArraySpeciesCreate', function (t) {
1296 t.test('errors', function (st) {
1297 var testNonNumber = function (nonNumber) {
1298 st['throws'](
1299 function () { ES.ArraySpeciesCreate([], nonNumber); },
1300 TypeError,
1301 debug(nonNumber) + ' is not a number'
1302 );
1303 };
1304 forEach(v.nonNumbers, testNonNumber);
1305
1306 st['throws'](
1307 function () { ES.ArraySpeciesCreate([], -1); },
1308 TypeError,
1309 '-1 is not >= 0'
1310 );
1311 st['throws'](
1312 function () { ES.ArraySpeciesCreate([], -Infinity); },
1313 TypeError,
1314 '-Infinity is not >= 0'
1315 );
1316
1317 var testNonIntegers = function (nonInteger) {
1318 st['throws'](
1319 function () { ES.ArraySpeciesCreate([], nonInteger); },
1320 TypeError,
1321 debug(nonInteger) + ' is not an integer'
1322 );
1323 };
1324 forEach(v.nonIntegerNumbers, testNonIntegers);
1325
1326 st.end();
1327 });
1328
1329 t.test('works with a non-array', function (st) {
1330 forEach(v.objects.concat(v.primitives), function (nonArray) {
1331 var arr = ES.ArraySpeciesCreate(nonArray, 0);
1332 st.ok(ES.IsArray(arr), 'is an array');
1333 st.equal(arr.length, 0, 'length is correct');
1334 st.equal(arr.constructor, Array, 'constructor is correct');
1335 });
1336
1337 st.end();
1338 });
1339
1340 t.test('works with a normal array', function (st) {
1341 var len = 2;
1342 var orig = [1, 2, 3];
1343 var arr = ES.ArraySpeciesCreate(orig, len);
1344
1345 st.ok(ES.IsArray(arr), 'is an array');
1346 st.equal(arr.length, len, 'length is correct');
1347 st.equal(arr.constructor, orig.constructor, 'constructor is correct');
1348
1349 st.end();
1350 });
1351
1352 t.test('-0 length produces +0 length', function (st) {
1353 var len = -0;
1354 st.equal(len, -0, '-0 is negative zero');
1355 st.notEqual(len, 0, '-0 is not positive zero');
1356
1357 var orig = [1, 2, 3];
1358 var arr = ES.ArraySpeciesCreate(orig, len);
1359
1360 st.equal(ES.IsArray(arr), true);
1361 st.equal(arr.length, 0);
1362 st.equal(arr.constructor, orig.constructor);
1363
1364 st.end();
1365 });
1366
1367 t.test('works with species construtor', { skip: !hasSpecies }, function (st) {
1368 var sentinel = {};
1369 var Foo = function Foo(len) {
1370 this.length = len;
1371 this.sentinel = sentinel;
1372 };
1373 var Bar = getArraySubclassWithSpeciesConstructor(Foo);
1374 var bar = new Bar();
1375
1376 st.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1377
1378 var arr = ES.ArraySpeciesCreate(bar, 3);
1379 st.equal(arr.constructor, Foo, 'result used species constructor');
1380 st.equal(arr.length, 3, 'length property is correct');
1381 st.equal(arr.sentinel, sentinel, 'Foo constructor was exercised');
1382
1383 st.end();
1384 });
1385
1386 t.test('works with null species constructor', { skip: !hasSpecies }, function (st) {
1387 var Bar = getArraySubclassWithSpeciesConstructor(null);
1388 var bar = new Bar();
1389
1390 st.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1391
1392 var arr = ES.ArraySpeciesCreate(bar, 3);
1393 st.equal(arr.constructor, Array, 'result used default constructor');
1394 st.equal(arr.length, 3, 'length property is correct');
1395
1396 st.end();
1397 });
1398
1399 t.test('works with undefined species constructor', { skip: !hasSpecies }, function (st) {
1400 var Bar = getArraySubclassWithSpeciesConstructor();
1401 var bar = new Bar();
1402
1403 st.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1404
1405 var arr = ES.ArraySpeciesCreate(bar, 3);
1406 st.equal(arr.constructor, Array, 'result used default constructor');
1407 st.equal(arr.length, 3, 'length property is correct');
1408
1409 st.end();
1410 });
1411
1412 t.test('throws with object non-construtor species constructor', { skip: !hasSpecies }, function (st) {
1413 forEach(v.objects, function (obj) {
1414 var Bar = getArraySubclassWithSpeciesConstructor(obj);
1415 var bar = new Bar();
1416
1417 st.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1418
1419 st['throws'](
1420 function () { ES.ArraySpeciesCreate(bar, 3); },
1421 TypeError,
1422 debug(obj) + ' is not a constructor'
1423 );
1424 });
1425
1426 st.end();
1427 });
1428
1429 t.end();
1430 });
1431
1432 test('Call', function (t) {
1433 var receiver = {};
1434 var notFuncs = v.nonFunctions.concat([/a/g, new RegExp('a', 'g')]);
1435 t.plan(notFuncs.length + v.nonArrays.length + 5);
1436
1437 forEach(notFuncs, function (notFunc) {
1438 t['throws'](
1439 function () { return ES.Call(notFunc, receiver); },
1440 TypeError,
1441 debug(notFunc) + ' (' + typeof notFunc + ') is not callable'
1442 );
1443 });
1444
1445 forEach(v.nonArrays, function (nonArray) {
1446 t['throws'](
1447 function () { ES.Call(Function.prototype, null, nonArray); },
1448 TypeError,
1449 debug(nonArray) + ' is not an array'
1450 );
1451 });
1452
1453 ES.Call(
1454 function (a, b) {
1455 t.equal(this, receiver, 'context matches expected');
1456 t.deepEqual([a, b], [1, 2], 'named args are correct');
1457 t.equal(arguments.length, 3, 'extra argument was passed');
1458 t.equal(arguments[2], 3, 'extra argument was correct');
1459 },
1460 receiver,
1461 [1, 2, 3]
1462 );
1463
1464 t.test('Call doesn’t use func.apply', function (st) {
1465 st.plan(4);
1466
1467 var bad = function (a, b) {
1468 st.equal(this, receiver, 'context matches expected');
1469 st.deepEqual([a, b], [1, 2], 'named args are correct');
1470 st.equal(arguments.length, 3, 'extra argument was passed');
1471 st.equal(arguments[2], 3, 'extra argument was correct');
1472 };
1473
1474 defineProperty(bad, 'apply', {
1475 value: function () {
1476 st.fail('bad.apply shouldn’t get called');
1477 }
1478 });
1479
1480 ES.Call(bad, receiver, [1, 2, 3]);
1481 st.end();
1482 });
1483
1484 t.end();
1485 });
1486
1487 test('CanonicalNumericIndexString', function (t) {
1488 var throwsOnNonString = function (notString) {
1489 t['throws'](
1490 function () { return ES.CanonicalNumericIndexString(notString); },
1491 TypeError,
1492 debug(notString) + ' is not a string'
1493 );
1494 };
1495 forEach(v.objects.concat(v.numbers), throwsOnNonString);
1496 t.equal(ES.CanonicalNumericIndexString('-0'), -0, '"-0" returns -0');
1497 for (var i = -50; i < 50; i += 10) {
1498 t.equal(i, ES.CanonicalNumericIndexString(String(i)), '"' + i + '" returns ' + i);
1499 t.equal(undefined, ES.CanonicalNumericIndexString(String(i) + 'a'), '"' + i + 'a" returns undefined');
1500 }
1501 t.end();
1502 });
1503
1504 test('CompletePropertyDescriptor', function (t) {
1505 forEach(v.nonUndefinedPrimitives, function (primitive) {
1506 t['throws'](
1507 function () { ES.CompletePropertyDescriptor(primitive); },
1508 TypeError,
1509 debug(primitive) + ' is not a Property Descriptor'
1510 );
1511 });
1512
1513 var generic = v.genericDescriptor();
1514 t.deepEqual(
1515 ES.CompletePropertyDescriptor(generic),
1516 {
1517 '[[Configurable]]': !!generic['[[Configurable]]'],
1518 '[[Enumerable]]': !!generic['[[Enumerable]]'],
1519 '[[Value]]': undefined,
1520 '[[Writable]]': false
1521 },
1522 'completes a Generic Descriptor'
1523 );
1524
1525 var data = v.dataDescriptor();
1526 t.deepEqual(
1527 ES.CompletePropertyDescriptor(data),
1528 {
1529 '[[Configurable]]': !!data['[[Configurable]]'],
1530 '[[Enumerable]]': false,
1531 '[[Value]]': data['[[Value]]'],
1532 '[[Writable]]': !!data['[[Writable]]']
1533 },
1534 'completes a Data Descriptor'
1535 );
1536
1537 var accessor = v.accessorDescriptor();
1538 t.deepEqual(
1539 ES.CompletePropertyDescriptor(accessor),
1540 {
1541 '[[Get]]': accessor['[[Get]]'],
1542 '[[Enumerable]]': !!accessor['[[Enumerable]]'],
1543 '[[Configurable]]': !!accessor['[[Configurable]]'],
1544 '[[Set]]': undefined
1545 },
1546 'completes an Accessor Descriptor'
1547 );
1548
1549 var mutator = v.mutatorDescriptor();
1550 t.deepEqual(
1551 ES.CompletePropertyDescriptor(mutator),
1552 {
1553 '[[Set]]': mutator['[[Set]]'],
1554 '[[Enumerable]]': !!mutator['[[Enumerable]]'],
1555 '[[Configurable]]': !!mutator['[[Configurable]]'],
1556 '[[Get]]': undefined
1557 },
1558 'completes a mutator Descriptor'
1559 );
1560
1561 t['throws'](
1562 function () { ES.CompletePropertyDescriptor(v.bothDescriptor()); },
1563 TypeError,
1564 'data and accessor descriptors are mutually exclusive'
1565 );
1566
1567 t.end();
1568 });
1569
1570 test('CreateDataProperty', function (t) {
1571 forEach(v.primitives, function (primitive) {
1572 t['throws'](
1573 function () { ES.CreateDataProperty(primitive); },
1574 TypeError,
1575 debug(primitive) + ' is not an object'
1576 );
1577 });
1578
1579 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1580 t['throws'](
1581 function () { ES.CreateDataProperty({}, nonPropertyKey); },
1582 TypeError,
1583 debug(nonPropertyKey) + ' is not a property key'
1584 );
1585 });
1586
1587 var sentinel = { id: 'sentinel' };
1588 var secondSentinel = { id: 'second sentinel' };
1589 forEach(v.propertyKeys, function (propertyKey) {
1590 var obj = {};
1591 var status = ES.CreateDataProperty(obj, propertyKey, sentinel);
1592 t.equal(status, true, 'status is true');
1593 t.equal(
1594 obj[propertyKey],
1595 sentinel,
1596 debug(sentinel) + ' is installed on "' + debug(propertyKey) + '" on the object'
1597 );
1598 var secondStatus = ES.CreateDataProperty(obj, propertyKey, secondSentinel);
1599 t.equal(secondStatus, true, 'second status is true');
1600 t.equal(
1601 obj[propertyKey],
1602 secondSentinel,
1603 debug(secondSentinel) + ' is installed on "' + debug(propertyKey) + '" on the object'
1604 );
1605
1606 t.test('with defineProperty', { skip: !defineProperty.oDP }, function (st) {
1607 var nonWritable = defineProperty({}, propertyKey, { configurable: true, writable: false });
1608
1609 var nonWritableStatus = ES.CreateDataProperty(nonWritable, propertyKey, sentinel);
1610 st.equal(nonWritableStatus, false, 'create data property failed');
1611 st.notEqual(
1612 nonWritable[propertyKey],
1613 sentinel,
1614 debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object when key is nonwritable'
1615 );
1616
1617 var nonConfigurable = defineProperty({}, propertyKey, { configurable: false, writable: true });
1618
1619 var nonConfigurableStatus = ES.CreateDataProperty(nonConfigurable, propertyKey, sentinel);
1620 st.equal(nonConfigurableStatus, false, 'create data property failed');
1621 st.notEqual(
1622 nonConfigurable[propertyKey],
1623 sentinel,
1624 debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object when key is nonconfigurable'
1625 );
1626 st.end();
1627 });
1628 });
1629
1630 t.end();
1631 });
1632
1633 test('CreateDataPropertyOrThrow', function (t) {
1634 forEach(v.primitives, function (primitive) {
1635 t['throws'](
1636 function () { ES.CreateDataPropertyOrThrow(primitive); },
1637 TypeError,
1638 debug(primitive) + ' is not an object'
1639 );
1640 });
1641
1642 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1643 t['throws'](
1644 function () { ES.CreateDataPropertyOrThrow({}, nonPropertyKey); },
1645 TypeError,
1646 debug(nonPropertyKey) + ' is not a property key'
1647 );
1648 });
1649
1650 var sentinel = {};
1651 forEach(v.propertyKeys, function (propertyKey) {
1652 var obj = {};
1653 var status = ES.CreateDataPropertyOrThrow(obj, propertyKey, sentinel);
1654 t.equal(status, true, 'status is true');
1655 t.equal(
1656 obj[propertyKey],
1657 sentinel,
1658 debug(sentinel) + ' is installed on "' + debug(propertyKey) + '" on the object'
1659 );
1660
1661 if (typeof Object.preventExtensions === 'function') {
1662 var notExtensible = {};
1663 Object.preventExtensions(notExtensible);
1664
1665 t['throws'](
1666 function () { ES.CreateDataPropertyOrThrow(notExtensible, propertyKey, sentinel); },
1667 TypeError,
1668 'can not install ' + debug(propertyKey) + ' on non-extensible object'
1669 );
1670 t.notEqual(
1671 notExtensible[propertyKey],
1672 sentinel,
1673 debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object'
1674 );
1675 }
1676 });
1677
1678 t.end();
1679 });
1680
1681 test('CreateListFromArrayLike', function (t) {
1682 forEach(v.primitives, function (nonObject) {
1683 t['throws'](
1684 function () { ES.CreateListFromArrayLike(nonObject); },
1685 TypeError,
1686 debug(nonObject) + ' is not an Object'
1687 );
1688 });
1689 forEach(v.nonArrays, function (nonArray) {
1690 t['throws'](
1691 function () { ES.CreateListFromArrayLike({}, nonArray); },
1692 TypeError,
1693 debug(nonArray) + ' is not an Array'
1694 );
1695 });
1696
1697 t.deepEqual(
1698 ES.CreateListFromArrayLike({ length: 2, 0: 'a', 1: 'b', 2: 'c' }),
1699 ['a', 'b'],
1700 'arraylike stops at the length'
1701 );
1702
1703 t.end();
1704 });
1705
1706 test('CreateHTML', function (t) {
1707 forEach(v.nonStrings, function (nonString) {
1708 t['throws'](
1709 function () { ES.CreateHTML('', nonString, '', ''); },
1710 TypeError,
1711 'tag: ' + debug(nonString) + ' is not a String'
1712 );
1713 t['throws'](
1714 function () { ES.CreateHTML('', '', nonString, ''); },
1715 TypeError,
1716 'attribute: ' + debug(nonString) + ' is not a String'
1717 );
1718 });
1719
1720 t.equal(
1721 ES.CreateHTML(
1722 { toString: function () { return 'the string'; } },
1723 'some HTML tag!',
1724 ''
1725 ),
1726 '<some HTML tag!>the string</some HTML tag!>',
1727 'works with an empty string attribute value'
1728 );
1729
1730 t.equal(
1731 ES.CreateHTML(
1732 { toString: function () { return 'the string'; } },
1733 'some HTML tag!',
1734 'attr',
1735 'value "with quotes"'
1736 ),
1737 '<some HTML tag! attr="value &quot;with quotes&quot;">the string</some HTML tag!>',
1738 'works with an attribute, and a value with quotes'
1739 );
1740
1741 t.end();
1742 });
1743
1744 test('CreateMethodProperty', function (t) {
1745 forEach(v.primitives, function (primitive) {
1746 t['throws'](
1747 function () { ES.CreateMethodProperty(primitive, 'key'); },
1748 TypeError,
1749 'O must be an Object'
1750 );
1751 });
1752
1753 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1754 t['throws'](
1755 function () { ES.CreateMethodProperty({}, nonPropertyKey); },
1756 TypeError,
1757 debug(nonPropertyKey) + ' is not a Property Key'
1758 );
1759 });
1760
1761 t.test('defines correctly', function (st) {
1762 var obj = {};
1763 var key = 'the key';
1764 var value = { foo: 'bar' };
1765
1766 st.equal(ES.CreateMethodProperty(obj, key, value), true, 'defines property successfully');
1767 st.test('property descriptor', { skip: !getOwnPropertyDescriptor }, function (s2t) {
1768 s2t.deepEqual(
1769 getOwnPropertyDescriptor(obj, key),
1770 {
1771 configurable: true,
1772 enumerable: false,
1773 value: value,
1774 writable: true
1775 },
1776 'sets the correct property descriptor'
1777 );
1778
1779 s2t.end();
1780 });
1781 st.equal(obj[key], value, 'sets the correct value');
1782
1783 st.end();
1784 });
1785
1786 t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1787 var obj = Object.freeze({ foo: 'bar' });
1788 st['throws'](
1789 function () { ES.CreateMethodProperty(obj, 'foo', { value: 'baz' }); },
1790 TypeError,
1791 'nonconfigurable key can not be defined'
1792 );
1793
1794 st.end();
1795 });
1796
1797 t.test('fails as expected on a function with a nonconfigurable name', { skip: !functionsHaveNames || functionsHaveConfigurableNames }, function (st) {
1798 st['throws'](
1799 function () { ES.CreateMethodProperty(function () {}, 'name', { value: 'baz' }); },
1800 TypeError,
1801 'nonconfigurable function name can not be defined'
1802 );
1803 st.end();
1804 });
1805
1806 t.end();
1807 });
1808
1809 test('CreateIterResultObject', function (t) {
1810 forEach(v.nonBooleans, function (nonBoolean) {
1811 t['throws'](
1812 function () { ES.CreateIterResultObject({}, nonBoolean); },
1813 TypeError,
1814 '"done" argument must be a boolean; ' + debug(nonBoolean) + ' is not'
1815 );
1816 });
1817
1818 var value = {};
1819 t.deepEqual(
1820 ES.CreateIterResultObject(value, true),
1821 { value: value, done: true },
1822 'creates a "done" iteration result'
1823 );
1824 t.deepEqual(
1825 ES.CreateIterResultObject(value, false),
1826 { value: value, done: false },
1827 'creates a "not done" iteration result'
1828 );
1829
1830 t.end();
1831 });
1832
1833 test('DefinePropertyOrThrow', function (t) {
1834 forEach(v.primitives, function (primitive) {
1835 t['throws'](
1836 function () { ES.DefinePropertyOrThrow(primitive, 'key', {}); },
1837 TypeError,
1838 'O must be an Object'
1839 );
1840 });
1841
1842 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1843 t['throws'](
1844 function () { ES.DefinePropertyOrThrow({}, nonPropertyKey, {}); },
1845 TypeError,
1846 debug(nonPropertyKey) + ' is not a Property Key'
1847 );
1848 });
1849
1850 t.test('defines correctly', function (st) {
1851 var obj = {};
1852 var key = 'the key';
1853 var descriptor = {
1854 configurable: true,
1855 enumerable: false,
1856 value: { foo: 'bar' },
1857 writable: true
1858 };
1859
1860 st.equal(ES.DefinePropertyOrThrow(obj, key, descriptor), true, 'defines property successfully');
1861 st.test('property descriptor', { skip: !getOwnPropertyDescriptor }, function (s2t) {
1862 s2t.deepEqual(
1863 getOwnPropertyDescriptor(obj, key),
1864 descriptor,
1865 'sets the correct property descriptor'
1866 );
1867
1868 s2t.end();
1869 });
1870 st.deepEqual(obj[key], descriptor.value, 'sets the correct value');
1871
1872 st.end();
1873 });
1874
1875 t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1876 var obj = Object.freeze({ foo: 'bar' });
1877 st['throws'](
1878 function () {
1879 ES.DefinePropertyOrThrow(obj, 'foo', { configurable: true, value: 'baz' });
1880 },
1881 TypeError,
1882 'nonconfigurable key can not be defined'
1883 );
1884
1885 st.end();
1886 });
1887
1888 t.test('fails as expected on a function with a nonconfigurable name', { skip: !functionsHaveNames || functionsHaveConfigurableNames }, function (st) {
1889 st['throws'](
1890 function () {
1891 ES.DefinePropertyOrThrow(function () {}, 'name', { configurable: true, value: 'baz' });
1892 },
1893 TypeError,
1894 'nonconfigurable function name can not be defined'
1895 );
1896 st.end();
1897 });
1898
1899 t.end();
1900 });
1901
1902 test('DeletePropertyOrThrow', function (t) {
1903 forEach(v.primitives, function (primitive) {
1904 t['throws'](
1905 function () { ES.DeletePropertyOrThrow(primitive, 'key', {}); },
1906 TypeError,
1907 'O must be an Object'
1908 );
1909 });
1910
1911 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1912 t['throws'](
1913 function () { ES.DeletePropertyOrThrow({}, nonPropertyKey, {}); },
1914 TypeError,
1915 debug(nonPropertyKey) + ' is not a Property Key'
1916 );
1917 });
1918
1919 t.test('defines correctly', function (st) {
1920 var obj = { 'the key': 42 };
1921 var key = 'the key';
1922
1923 st.equal(ES.DeletePropertyOrThrow(obj, key), true, 'deletes property successfully');
1924 st.equal(key in obj, false, 'key is no longer in the object');
1925
1926 st.end();
1927 });
1928
1929 t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1930 var obj = Object.freeze({ foo: 'bar' });
1931 st['throws'](
1932 function () { ES.DeletePropertyOrThrow(obj, 'foo'); },
1933 TypeError,
1934 'nonconfigurable key can not be deleted'
1935 );
1936
1937 st.end();
1938 });
1939
1940 t.test('fails as expected on a function with a nonconfigurable name', { skip: !functionsHaveNames || functionsHaveConfigurableNames }, function (st) {
1941 st['throws'](
1942 function () { ES.DeletePropertyOrThrow(function () {}, 'name'); },
1943 TypeError,
1944 'nonconfigurable function name can not be deleted'
1945 );
1946 st.end();
1947 });
1948
1949 t.end();
1950 });
1951
1952 test('EnumerableOwnNames', function (t) {
1953 var obj = testEnumerableOwnNames(t, function (O) { return ES.EnumerableOwnNames(O); });
1954
1955 t.deepEqual(
1956 ES.EnumerableOwnNames(obj),
1957 ['own'],
1958 'returns enumerable own names'
1959 );
1960
1961 t.end();
1962 });
1963
1964 test('FromPropertyDescriptor', function (t) {
1965 t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined');
1966 t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined');
1967
1968 forEach(v.nonUndefinedPrimitives, function (primitive) {
1969 t['throws'](
1970 function () { ES.FromPropertyDescriptor(primitive); },
1971 TypeError,
1972 debug(primitive) + ' is not a Property Descriptor'
1973 );
1974 });
1975
1976 var accessor = v.accessorDescriptor();
1977 t.deepEqual(ES.FromPropertyDescriptor(accessor), {
1978 get: accessor['[[Get]]'],
1979 enumerable: !!accessor['[[Enumerable]]'],
1980 configurable: !!accessor['[[Configurable]]']
1981 });
1982
1983 var mutator = v.mutatorDescriptor();
1984 t.deepEqual(ES.FromPropertyDescriptor(mutator), {
1985 set: mutator['[[Set]]'],
1986 enumerable: !!mutator['[[Enumerable]]'],
1987 configurable: !!mutator['[[Configurable]]']
1988 });
1989 var data = v.dataDescriptor();
1990 t.deepEqual(ES.FromPropertyDescriptor(data), {
1991 value: data['[[Value]]'],
1992 writable: data['[[Writable]]']
1993 });
1994
1995 t.deepEqual(ES.FromPropertyDescriptor(v.genericDescriptor()), {
1996 enumerable: false,
1997 configurable: true
1998 });
1999
2000 var both = v.bothDescriptor();
2001 t['throws'](
2002 function () {
2003 ES.FromPropertyDescriptor({ get: both['[[Get]]'], value: both['[[Value]]'] });
2004 },
2005 TypeError,
2006 'data and accessor descriptors are mutually exclusive'
2007 );
2008
2009 t.end();
2010 });
2011
2012 test('Get', function (t) {
2013 t['throws'](function () { return ES.Get('a', 'a'); }, TypeError, 'Throws a TypeError if `O` is not an Object');
2014 t['throws'](function () { return ES.Get({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
2015
2016 var value = {};
2017 t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
2018 var sym = Symbol('sym');
2019 var obj = {};
2020 obj[sym] = value;
2021 st.equal(ES.Get(obj, sym), value, 'returns property `P` if it exists on object `O`');
2022 st.end();
2023 });
2024 t.equal(ES.Get({ a: value }, 'a'), value, 'returns property `P` if it exists on object `O`');
2025 t.end();
2026 });
2027
2028 test('GetIterator', function (t) {
2029 var arr = [1, 2];
2030 testIterator(t, ES.GetIterator(arr), arr);
2031
2032 testIterator(t, ES.GetIterator('abc'), 'abc'.split(''));
2033
2034 var sentinel = {};
2035 forEach(v.primitives, function (nonObject) {
2036 var method = function () {
2037 return nonObject;
2038 };
2039 t['throws'](
2040 function () { ES.GetIterator(sentinel, method); },
2041 TypeError,
2042 debug(nonObject) + ' is not an Object; iterator method must return an Object'
2043 );
2044 });
2045
2046 var i = 0;
2047 var manualMethod = function () {
2048 t.equal(this, sentinel, 'receiver is expected object');
2049 return {
2050 next: function () {
2051 var value = arr[i];
2052 i += 1;
2053 return {
2054 done: i > arr.length,
2055 value: value // eslint-disable-line no-plusplus
2056 };
2057 }
2058 };
2059 };
2060 testIterator(t, ES.GetIterator(sentinel, manualMethod), arr);
2061
2062 t.test('Symbol.iterator', { skip: !v.hasSymbols }, function (st) {
2063 var m = new Map();
2064 m.set(1, 'a');
2065 m.set(2, 'b');
2066
2067 testIterator(st, ES.GetIterator(m), [[1, 'a'], [2, 'b']]);
2068
2069 forEach(v.primitives, function (nonObject) {
2070 var badIterable = {};
2071 badIterable[Symbol.iterator] = function () {
2072 return nonObject;
2073 };
2074 st['throws'](
2075 function () { return ES.GetIterator(badIterable); },
2076 TypeError,
2077 debug(nonObject) + ' is not an Object; iterator method must return an Object'
2078 );
2079 });
2080
2081 st.end();
2082 });
2083
2084 t.end();
2085 });
2086
2087 test('GetMethod', function (t) {
2088 t['throws'](function () { return ES.GetMethod({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
2089 t.equal(ES.GetMethod({}, 'a'), undefined, 'returns undefined in property is undefined');
2090 t.equal(ES.GetMethod({ a: null }, 'a'), undefined, 'returns undefined if property is null');
2091 t.equal(ES.GetMethod({ a: undefined }, 'a'), undefined, 'returns undefined if property is undefined');
2092 var obj = { a: function () {} };
2093 t['throws'](function () { ES.GetMethod({ a: 'b' }, 'a'); }, TypeError, 'throws TypeError if property exists and is not callable');
2094 t.equal(ES.GetMethod(obj, 'a'), obj.a, 'returns property if it is callable');
2095 t.end();
2096 });
2097
2098 test('GetOwnPropertyKeys', function (t) {
2099 forEach(v.primitives, function (primitive) {
2100 t['throws'](
2101 function () { ES.GetOwnPropertyKeys(primitive, 'String'); },
2102 TypeError,
2103 'O: ' + debug(primitive) + ' is not an Object'
2104 );
2105 });
2106
2107 t['throws'](
2108 function () { ES.GetOwnPropertyKeys({}, 'not string or symbol'); },
2109 TypeError,
2110 'Type: must be "String" or "Symbol"'
2111 );
2112
2113 t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
2114 var O = { a: 1 };
2115 O[Symbol.iterator] = true;
2116 var s = Symbol('test');
2117 defineProperty(O, s, { enumerable: false, value: true });
2118
2119 st.deepEqual(
2120 ES.GetOwnPropertyKeys(O, 'Symbol'),
2121 [Symbol.iterator, s],
2122 'works with Symbols, enumerable or not'
2123 );
2124
2125 st.end();
2126 });
2127
2128 t.test('non-enumerable names', { skip: !defineProperty.oDP }, function (st) {
2129 var O = { a: 1 };
2130 defineProperty(O, 'b', { enumerable: false, value: 2 });
2131 if (v.hasSymbols) {
2132 O[Symbol.iterator] = true;
2133 }
2134
2135 st.deepEqual(
2136 ES.GetOwnPropertyKeys(O, 'String').sort(),
2137 ['a', 'b'].sort(),
2138 'works with Strings, enumerable or not'
2139 );
2140
2141 st.end();
2142 });
2143
2144 t.deepEqual(
2145 ES.GetOwnPropertyKeys({ a: 1, b: 2 }, 'String').sort(),
2146 ['a', 'b'].sort(),
2147 'works with enumerable keys'
2148 );
2149
2150 t.end();
2151 });
2152
2153 test('GetPrototypeFromConstructor', function (t) {
2154 forEach(v.nonFunctions, function (nonFunction) {
2155 t['throws'](
2156 function () { ES.GetPrototypeFromConstructor(nonFunction, '%Array%'); },
2157 TypeError,
2158 debug(nonFunction) + ' is not a constructor'
2159 );
2160 });
2161
2162 forEach(arrowFns, function (arrowFn) {
2163 t['throws'](
2164 function () { ES.GetPrototypeFromConstructor(arrowFn, '%Array%'); },
2165 TypeError,
2166 debug(arrowFn) + ' is not a constructor'
2167 );
2168 });
2169
2170 var f = function () {};
2171 t.equal(
2172 ES.GetPrototypeFromConstructor(f, '%Array.prototype%'),
2173 f.prototype,
2174 'function with normal `prototype` property returns it'
2175 );
2176 forEach([true, 'foo', 42], function (truthyPrimitive) {
2177 f.prototype = truthyPrimitive;
2178 t.equal(
2179 ES.GetPrototypeFromConstructor(f, '%Array.prototype%'),
2180 Array.prototype,
2181 'function with non-object `prototype` property (' + debug(truthyPrimitive) + ') returns default intrinsic'
2182 );
2183 });
2184
2185 t.end();
2186 });
2187
2188 test('GetSubstitution', function (t) {
2189 forEach(v.nonStrings, function (nonString) {
2190 t['throws'](
2191 function () { ES.GetSubstitution(nonString, '', 0, [], ''); },
2192 TypeError,
2193 '`matched`: ' + debug(nonString) + ' is not a String'
2194 );
2195
2196 t['throws'](
2197 function () { ES.GetSubstitution('', nonString, 0, [], ''); },
2198 TypeError,
2199 '`str`: ' + debug(nonString) + ' is not a String'
2200 );
2201
2202 t['throws'](
2203 function () { ES.GetSubstitution('', '', 0, [], nonString); },
2204 TypeError,
2205 '`replacement`: ' + debug(nonString) + ' is not a String'
2206 );
2207
2208 if (canDistinguishSparseFromUndefined || typeof nonString !== 'undefined') {
2209 t['throws'](
2210 function () { ES.GetSubstitution('', '', 0, [nonString], ''); },
2211 TypeError,
2212 '`captures`: ' + debug([nonString]) + ' is not an Array of strings'
2213 );
2214 }
2215 });
2216
2217 forEach(v.notNonNegativeIntegers, function (nonNonNegativeInteger) {
2218 t['throws'](
2219 function () { ES.GetSubstitution('', '', nonNonNegativeInteger, [], ''); },
2220 TypeError,
2221 '`position`: ' + debug(nonNonNegativeInteger) + ' is not a non-negative integer'
2222 );
2223 });
2224
2225 forEach(v.nonArrays, function (nonArray) {
2226 t['throws'](
2227 function () { ES.GetSubstitution('', '', 0, nonArray, ''); },
2228 TypeError,
2229 '`captures`: ' + debug(nonArray) + ' is not an Array'
2230 );
2231 });
2232
2233 t.equal(
2234 ES.GetSubstitution('def', 'abcdefghi', 3, [], '123'),
2235 '123',
2236 'returns the substitution'
2237 );
2238 t.equal(
2239 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '$$2$'),
2240 '$2$',
2241 'supports $$, and trailing $'
2242 );
2243
2244 t.equal(
2245 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$&<'),
2246 '>abcdef<',
2247 'supports $&'
2248 );
2249
2250 t.equal(
2251 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$`<'),
2252 '><',
2253 'supports $` at position 0'
2254 );
2255 t.equal(
2256 ES.GetSubstitution('def', 'abcdefghi', 3, [], '>$`<'),
2257 '>ab<',
2258 'supports $` at position > 0'
2259 );
2260
2261 t.equal(
2262 ES.GetSubstitution('def', 'abcdefghi', 7, [], ">$'<"),
2263 '><',
2264 "supports $' at a position where there's less than `matched.length` chars left"
2265 );
2266 t.equal(
2267 ES.GetSubstitution('def', 'abcdefghi', 3, [], ">$'<"),
2268 '>ghi<',
2269 "supports $' at a position where there's more than `matched.length` chars left"
2270 );
2271
2272 for (var i = 0; i < 100; i += 1) {
2273 var captures = [];
2274 captures[i] = 'test';
2275 if (i > 0) {
2276 t.equal(
2277 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$' + i + '<'),
2278 '>undefined<',
2279 'supports $' + i + ' with no captures'
2280 );
2281 t.equal(
2282 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$' + i),
2283 '>undefined',
2284 'supports $' + i + ' at the end of the replacement, with no captures'
2285 );
2286 t.equal(
2287 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$' + i + '<'),
2288 '><',
2289 'supports $' + i + ' with a capture at that index'
2290 );
2291 t.equal(
2292 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$' + i),
2293 '>',
2294 'supports $' + i + ' at the end of the replacement, with a capture at that index'
2295 );
2296 }
2297 if (i < 10) {
2298 t.equal(
2299 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$0' + i + '<'),
2300 i === 0 ? '><' : '>undefined<',
2301 'supports $0' + i + ' with no captures'
2302 );
2303 t.equal(
2304 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$0' + i),
2305 i === 0 ? '>' : '>undefined',
2306 'supports $0' + i + ' at the end of the replacement, with no captures'
2307 );
2308 t.equal(
2309 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$0' + i + '<'),
2310 '><',
2311 'supports $0' + i + ' with a capture at that index'
2312 );
2313 t.equal(
2314 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$0' + i),
2315 '>',
2316 'supports $0' + i + ' at the end of the replacement, with a capture at that index'
2317 );
2318 }
2319 }
2320
2321 t.end();
2322 });
2323
2324 test('GetV', function (t) {
2325 t['throws'](function () { return ES.GetV({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
2326 var obj = { a: function () {} };
2327 t.equal(ES.GetV(obj, 'a'), obj.a, 'returns property if it exists');
2328 t.equal(ES.GetV(obj, 'b'), undefined, 'returns undefiend if property does not exist');
2329 t.end();
2330 });
2331
2332 test('HasOwnProperty', function (t) {
2333 forEach(v.primitives, function (primitive) {
2334 t['throws'](
2335 function () { ES.HasOwnProperty(primitive, 'key'); },
2336 TypeError,
2337 debug(primitive) + ' is not an Object'
2338 );
2339 });
2340
2341 forEach(v.nonPropertyKeys, function (nonKey) {
2342 t['throws'](
2343 function () { ES.HasOwnProperty({}, nonKey); },
2344 TypeError,
2345 debug(nonKey) + ' is not a Property Key'
2346 );
2347 });
2348
2349 t.equal(ES.HasOwnProperty({}, 'toString'), false, 'inherited properties are not own');
2350 t.equal(
2351 ES.HasOwnProperty({ toString: 1 }, 'toString'),
2352 true,
2353 'shadowed inherited own properties are own'
2354 );
2355 t.equal(ES.HasOwnProperty({ a: 1 }, 'a'), true, 'own properties are own');
2356
2357 t.end();
2358 });
2359
2360 test('HasProperty', function (t) {
2361 forEach(v.primitives, function (primitive) {
2362 t['throws'](
2363 function () { ES.HasProperty(primitive, 'key'); },
2364 TypeError,
2365 debug(primitive) + ' is not an Object'
2366 );
2367 });
2368
2369 forEach(v.nonPropertyKeys, function (nonKey) {
2370 t['throws'](
2371 function () { ES.HasProperty({}, nonKey); },
2372 TypeError,
2373 debug(nonKey) + ' is not a Property Key'
2374 );
2375 });
2376
2377 t.equal(ES.HasProperty({}, 'nope'), false, 'object does not have nonexistent properties');
2378 t.equal(ES.HasProperty({}, 'toString'), true, 'object has inherited properties');
2379 t.equal(
2380 ES.HasProperty({ toString: 1 }, 'toString'),
2381 true,
2382 'object has shadowed inherited own properties'
2383 );
2384 t.equal(ES.HasProperty({ a: 1 }, 'a'), true, 'object has own properties');
2385
2386 t.end();
2387 });
2388
2389 test('InstanceofOperator', function (t) {
2390 forEach(v.primitives, function (primitive) {
2391 t['throws'](
2392 function () { ES.InstanceofOperator(primitive, function () {}); },
2393 TypeError,
2394 debug(primitive) + ' is not an object'
2395 );
2396 });
2397
2398 forEach(v.nonFunctions, function (nonFunction) {
2399 t['throws'](
2400 function () { ES.InstanceofOperator({}, nonFunction); },
2401 TypeError,
2402 debug(nonFunction) + ' is not callable'
2403 );
2404 });
2405
2406 var C = function C() {};
2407 var D = function D() {};
2408
2409 t.equal(ES.InstanceofOperator(new C(), C), true, 'constructor function has an instance of itself');
2410 t.equal(ES.InstanceofOperator(new D(), C), false, 'constructor/instance mismatch is false');
2411 t.equal(ES.InstanceofOperator(new C(), D), false, 'instance/constructor mismatch is false');
2412 t.equal(ES.InstanceofOperator({}, C), false, 'plain object is not an instance of a constructor');
2413 t.equal(ES.InstanceofOperator({}, Object), true, 'plain object is an instance of Object');
2414
2415 t.test('Symbol.hasInstance', { skip: !v.hasSymbols || !Symbol.hasInstance }, function (st) {
2416 st.plan(5);
2417
2418 var O = {};
2419 var C2 = function () {};
2420 st.equal(ES.InstanceofOperator(O, C2), false, 'O is not an instance of C2');
2421
2422 defineProperty(C2, Symbol.hasInstance, {
2423 configurable: true,
2424 value: function (obj) {
2425 st.equal(this, C2, 'hasInstance receiver is C2');
2426 st.equal(obj, O, 'hasInstance argument is O');
2427
2428 return {}; // testing coercion to boolean
2429 }
2430 });
2431
2432 st.equal(ES.InstanceofOperator(O, C2), true, 'O is now an instance of C2');
2433
2434 defineProperty(C2, Symbol.hasInstance, {
2435 configurable: true,
2436 value: undefined
2437 });
2438
2439 st.equal(ES.InstanceofOperator(O, C2), false, 'O is no longer an instance of C2');
2440
2441 st.end();
2442 });
2443
2444 t.end();
2445 });
2446
2447 test('Invoke', function (t) {
2448 forEach(v.nonPropertyKeys, function (nonKey) {
2449 t['throws'](
2450 function () { ES.Invoke({}, nonKey); },
2451 TypeError,
2452 debug(nonKey) + ' is not a Property Key'
2453 );
2454 });
2455
2456 t['throws'](
2457 function () { ES.Invoke({ o: false }, 'o'); },
2458 TypeError,
2459 'fails on a non-function'
2460 );
2461
2462 forEach(v.nonArrays, function (nonArray) {
2463 t['throws'](
2464 function () { ES.Invoke({}, '', nonArray); },
2465 TypeError,
2466 debug(nonArray) + ' is not an Array'
2467 );
2468 });
2469
2470 t.test('invoked callback', function (st) {
2471 var aValue = {};
2472 var bValue = {};
2473 var obj = {
2474 f: function (a) {
2475 st.equal(arguments.length, 2, '2 args passed');
2476 st.equal(a, aValue, 'first arg is correct');
2477 st.equal(arguments[1], bValue, 'second arg is correct');
2478 }
2479 };
2480 st.plan(3);
2481 ES.Invoke(obj, 'f', [aValue, bValue]);
2482 });
2483
2484 t.end();
2485 });
2486
2487 test('IsArray', function (t) {
2488 t.equal(true, ES.IsArray([]), '[] is array');
2489 t.equal(false, ES.IsArray({}), '{} is not array');
2490 t.equal(false, ES.IsArray({ length: 1, 0: true }), 'arraylike object is not array');
2491 forEach(v.objects.concat(v.primitives), function (value) {
2492 t.equal(false, ES.IsArray(value), debug(value) + ' is not array');
2493 });
2494 t.end();
2495 });
2496
2497 test('IsConcatSpreadable', function (t) {
2498 forEach(v.primitives, function (primitive) {
2499 t.equal(ES.IsConcatSpreadable(primitive), false, debug(primitive) + ' is not an Object');
2500 });
2501
2502 var hasSymbolConcatSpreadable = v.hasSymbols && Symbol.isConcatSpreadable;
2503 t.test('Symbol.isConcatSpreadable', { skip: !hasSymbolConcatSpreadable }, function (st) {
2504 forEach(v.falsies, function (falsy) {
2505 var obj = {};
2506 obj[Symbol.isConcatSpreadable] = falsy;
2507 st.equal(
2508 ES.IsConcatSpreadable(obj),
2509 false,
2510 'an object with ' + debug(falsy) + ' as Symbol.isConcatSpreadable is not concat spreadable'
2511 );
2512 });
2513
2514 forEach(v.truthies, function (truthy) {
2515 var obj = {};
2516 obj[Symbol.isConcatSpreadable] = truthy;
2517 st.equal(
2518 ES.IsConcatSpreadable(obj),
2519 true,
2520 'an object with ' + debug(truthy) + ' as Symbol.isConcatSpreadable is concat spreadable'
2521 );
2522 });
2523
2524 st.end();
2525 });
2526
2527 forEach(v.objects, function (object) {
2528 t.equal(
2529 ES.IsConcatSpreadable(object),
2530 false,
2531 'non-array without Symbol.isConcatSpreadable is not concat spreadable'
2532 );
2533 });
2534
2535 t.equal(ES.IsConcatSpreadable([]), true, 'arrays are concat spreadable');
2536
2537 t.end();
2538 });
2539
2540 test('IsConstructor', function (t) {
2541 t.equal(true, ES.IsConstructor(function () {}), 'function is constructor');
2542 t.equal(false, ES.IsConstructor(/a/g), 'regex is not constructor');
2543 forEach(v.objects, function (object) {
2544 t.equal(false, ES.IsConstructor(object), object + ' object is not constructor');
2545 });
2546
2547 try {
2548 var arrow = Function('return () => {}')(); // eslint-disable-line no-new-func
2549 t.equal(ES.IsConstructor(arrow), false, 'arrow function is not constructor');
2550 } catch (e) {
2551 t.comment('SKIP: arrow function syntax not supported.');
2552 }
2553
2554 try {
2555 var foo = Function('return class Foo {}')(); // eslint-disable-line no-new-func
2556 t.equal(ES.IsConstructor(foo), true, 'class is constructor');
2557 } catch (e) {
2558 t.comment('SKIP: class syntax not supported.');
2559 }
2560
2561 if (typeof Reflect !== 'object' || typeof Proxy !== 'function' || has(Proxy, 'prototype')) {
2562 t.comment('SKIP: Proxy is constructor');
2563 } else {
2564 t.equal(ES.IsConstructor(Proxy), true, 'Proxy is constructor');
2565 }
2566
2567 t.end();
2568 });
2569
2570 test('IsExtensible', function (t) {
2571 forEach(v.objects, function (object) {
2572 t.equal(true, ES.IsExtensible(object), debug(object) + ' object is extensible');
2573 });
2574 forEach(v.primitives, function (primitive) {
2575 t.equal(false, ES.IsExtensible(primitive), debug(primitive) + ' is not extensible');
2576 });
2577 if (Object.preventExtensions) {
2578 t.equal(false, ES.IsExtensible(Object.preventExtensions({})), 'object with extensions prevented is not extensible');
2579 }
2580 t.end();
2581 });
2582
2583 test('IsPromise', { skip: typeof Promise !== 'function' }, function (t) {
2584 forEach(v.objects.concat(v.primitives), function (nonPromise) {
2585 t.equal(ES.IsPromise(nonPromise), false, debug(nonPromise) + ' is not a Promise');
2586 });
2587
2588 var thenable = { then: Promise.prototype.then };
2589 t.equal(ES.IsPromise(thenable), false, 'generic thenable is not a Promise');
2590
2591 t.equal(ES.IsPromise(Promise.resolve()), true, 'Promise is a Promise');
2592
2593 t.end();
2594 });
2595
2596 test('IsPropertyDescriptor', function (t) {
2597 forEach(v.primitives, function (primitive) {
2598 t.equal(
2599 ES.IsPropertyDescriptor(primitive),
2600 false,
2601 debug(primitive) + ' is not a Property Descriptor'
2602 );
2603 });
2604
2605 t.equal(ES.IsPropertyDescriptor({ invalid: true }), false, 'invalid keys not allowed on a Property Descriptor');
2606
2607 t.equal(ES.IsPropertyDescriptor({}), true, 'empty object is an incomplete Property Descriptor');
2608
2609 t.equal(ES.IsPropertyDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is a Property Descriptor');
2610 t.equal(ES.IsPropertyDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is a Property Descriptor');
2611 t.equal(ES.IsPropertyDescriptor(v.dataDescriptor()), true, 'data descriptor is a Property Descriptor');
2612 t.equal(ES.IsPropertyDescriptor(v.genericDescriptor()), true, 'generic descriptor is a Property Descriptor');
2613
2614 t['throws'](
2615 function () { ES.IsPropertyDescriptor(v.bothDescriptor()); },
2616 TypeError,
2617 'a Property Descriptor can not be both a Data and an Accessor Descriptor'
2618 );
2619
2620 t['throws'](
2621 function () { ES.IsPropertyDescriptor(v.bothDescriptorWritable()); },
2622 TypeError,
2623 'a Property Descriptor can not be both a Data and an Accessor Descriptor'
2624 );
2625
2626 t.end();
2627 });
2628
2629 test('IsPropertyKey', function (t) {
2630 forEach(v.numbers.concat(v.objects), function (notKey) {
2631 t.equal(false, ES.IsPropertyKey(notKey), debug(notKey) + ' is not property key');
2632 });
2633
2634 t.equal(true, ES.IsPropertyKey('foo'), 'string is property key');
2635
2636 forEach(v.symbols, function (symbol) {
2637 t.equal(true, ES.IsPropertyKey(symbol), debug(symbol) + ' is property key');
2638 });
2639 t.end();
2640 });
2641
2642 test('IsRegExp', function (t) {
2643 forEach([/a/g, new RegExp('a', 'g')], function (regex) {
2644 t.equal(true, ES.IsRegExp(regex), regex + ' is regex');
2645 });
2646
2647 forEach(v.objects.concat(v.primitives), function (nonRegex) {
2648 t.equal(false, ES.IsRegExp(nonRegex), debug(nonRegex) + ' is not regex');
2649 });
2650
2651 t.test('Symbol.match', { skip: !v.hasSymbols || !Symbol.match }, function (st) {
2652 var obj = {};
2653 obj[Symbol.match] = true;
2654 st.equal(true, ES.IsRegExp(obj), 'object with truthy Symbol.match is regex');
2655
2656 var regex = /a/;
2657 defineProperty(regex, Symbol.match, { value: false });
2658 st.equal(false, ES.IsRegExp(regex), 'regex with falsy Symbol.match is not regex');
2659
2660 st.end();
2661 });
2662
2663 t.end();
2664 });
2665
2666 test('IsInteger', function (t) {
2667 for (var i = -100; i < 100; i += 10) {
2668 t.equal(true, ES.IsInteger(i), i + ' is integer');
2669 t.equal(false, ES.IsInteger(i + 0.2), (i + 0.2) + ' is not integer');
2670 }
2671 t.equal(true, ES.IsInteger(-0), '-0 is integer');
2672 var notInts = v.nonNumbers.concat(v.nonIntegerNumbers, v.infinities, [NaN, [], new Date()]);
2673 forEach(notInts, function (notInt) {
2674 t.equal(false, ES.IsInteger(notInt), debug(notInt) + ' is not integer');
2675 });
2676 t.equal(false, ES.IsInteger(v.uncoercibleObject), 'uncoercibleObject is not integer');
2677 t.end();
2678 });
2679
2680 test('IteratorNext', function (t) {
2681 forEach(v.primitives, function (nonObject) {
2682 t['throws'](
2683 function () { ES.IteratorNext(nonObject); },
2684 TypeError,
2685 debug(nonObject) + ' is not an Object'
2686 );
2687
2688 t['throws'](
2689 function () { ES.IteratorNext({ next: function () { return nonObject; } }); },
2690 TypeError,
2691 '`next()` returns ' + debug(nonObject) + ', which is not an Object'
2692 );
2693 });
2694
2695 var iterator = {
2696 next: function (value) {
2697 return [arguments.length, value];
2698 }
2699 };
2700 t.deepEqual(
2701 ES.IteratorNext(iterator),
2702 [0, undefined],
2703 'returns expected value from `.next()`; `next` receives expected 0 arguments'
2704 );
2705 t.deepEqual(
2706 ES.IteratorNext(iterator, iterator),
2707 [1, iterator],
2708 'returns expected value from `.next()`; `next` receives expected 1 argument'
2709 );
2710
2711 t.end();
2712 });
2713
2714 test('IteratorComplete', function (t) {
2715 forEach(v.primitives, function (nonObject) {
2716 t['throws'](
2717 function () { ES.IteratorComplete(nonObject); },
2718 TypeError,
2719 debug(nonObject) + ' is not an Object'
2720 );
2721 });
2722
2723 forEach(v.truthies, function (truthy) {
2724 t.equal(ES.IteratorComplete({ done: truthy }), true, '{ done: ' + debug(truthy) + ' } is true');
2725 });
2726
2727 forEach(v.falsies, function (falsy) {
2728 t.equal(ES.IteratorComplete({ done: falsy }), false, '{ done: ' + debug(falsy) + ' } is false');
2729 });
2730
2731 t.end();
2732 });
2733
2734 test('IteratorValue', function (t) {
2735 forEach(v.primitives, function (nonObject) {
2736 t['throws'](
2737 function () { ES.IteratorValue(nonObject); },
2738 TypeError,
2739 debug(nonObject) + ' is not an Object'
2740 );
2741 });
2742
2743 var sentinel = {};
2744 t.equal(ES.IteratorValue({ value: sentinel }), sentinel, 'Gets `.value` off the object');
2745
2746 t.end();
2747 });
2748
2749 test('IteratorStep', function (t) {
2750 t.deepEqual(
2751 ES.IteratorStep({
2752 next: function () {
2753 return {
2754 done: false,
2755 value: [1, arguments.length]
2756 };
2757 }
2758 }),
2759 { done: false, value: [1, 0] },
2760 'not-done iterator result yields iterator result'
2761 );
2762 t.deepEqual(
2763 ES.IteratorStep({
2764 next: function () {
2765 return {
2766 done: true,
2767 value: [2, arguments.length]
2768 };
2769 }
2770 }),
2771 false,
2772 'done iterator result yields false'
2773 );
2774
2775 t.end();
2776 });
2777
2778 test('IteratorClose', function (t) {
2779 forEach(v.primitives, function (nonObject) {
2780 t['throws'](
2781 function () { ES.IteratorClose(nonObject); },
2782 TypeError,
2783 debug(nonObject) + ' is not an Object'
2784 );
2785
2786 t['throws'](
2787 function () { ES.IteratorClose({ 'return': function () { return nonObject; } }, function () {}); },
2788 TypeError,
2789 '`.return` returns ' + debug(nonObject) + ', which is not an Object'
2790 );
2791 });
2792
2793 forEach(v.nonFunctions, function (nonFunction) {
2794 t['throws'](
2795 function () { ES.IteratorClose({}, nonFunction); },
2796 TypeError,
2797 debug(nonFunction) + ' is not a thunk for a Completion Record'
2798 );
2799
2800 if (nonFunction != null) {
2801 t['throws'](
2802 function () { ES.IteratorClose({ 'return': nonFunction }, function () {}); },
2803 TypeError,
2804 '`.return` of ' + debug(nonFunction) + ' is not a Function'
2805 );
2806 }
2807 });
2808
2809 var sentinel = {};
2810 t.equal(
2811 ES.IteratorClose({ 'return': undefined }, function () { return sentinel; }),
2812 sentinel,
2813 'when `.return` is `undefined`, invokes and returns the completion thunk'
2814 );
2815
2816 /* eslint no-throw-literal: 0 */
2817 t['throws'](
2818 function () { ES.IteratorClose({ 'return': function () { throw sentinel; } }, function () {}); },
2819 sentinel,
2820 '`.return` that throws, when completionThunk does not, throws exception from `.return`'
2821 );
2822 t['throws'](
2823 function () { ES.IteratorClose({ 'return': function () { throw sentinel; } }, function () { throw -1; }); },
2824 -1,
2825 '`.return` that throws, when completionThunk does too, throws exception from completionThunk'
2826 );
2827 t['throws'](
2828 function () { ES.IteratorClose({ 'return': function () { } }, function () { throw -1; }); },
2829 -1,
2830 '`.return` that does not throw, when completionThunk does, throws exception from completionThunk'
2831 );
2832
2833 t.equal(
2834 ES.IteratorClose({ 'return': function () { return sentinel; } }, function () { return 42; }),
2835 42,
2836 'when `.return` and completionThunk do not throw, and `.return` returns an Object, returns completionThunk'
2837 );
2838
2839 t.end();
2840 });
2841
2842 test('ObjectCreate', function (t) {
2843 forEach(v.nonNullPrimitives, function (value) {
2844 t['throws'](
2845 function () { ES.ObjectCreate(value); },
2846 TypeError,
2847 debug(value) + ' is not null, or an object'
2848 );
2849 });
2850
2851 t.test('proto arg', function (st) {
2852 var Parent = function Parent() {};
2853 Parent.prototype.foo = {};
2854 var child = ES.ObjectCreate(Parent.prototype);
2855 st.equal(child instanceof Parent, true, 'child is instanceof Parent');
2856 st.equal(child.foo, Parent.prototype.foo, 'child inherits properties from Parent.prototype');
2857
2858 st.end();
2859 });
2860
2861 t.test('internal slots arg', function (st) {
2862 st.doesNotThrow(function () { ES.ObjectCreate({}, []); }, 'an empty slot list is valid');
2863
2864 st['throws'](
2865 function () { ES.ObjectCreate({}, ['a']); },
2866 SyntaxError,
2867 'internal slots are not supported'
2868 );
2869
2870 st.end();
2871 });
2872
2873 t.test('null proto', { skip: !Object.create && !$setProto }, function (st) {
2874 st.equal('toString' in {}, true, 'normal objects have toString');
2875 st.equal('toString' in ES.ObjectCreate(null), false, 'makes a null object');
2876
2877 st.end();
2878 });
2879
2880 t.test('null proto when no native Object.create', { skip: Object.create || $setProto }, function (st) {
2881 st['throws'](
2882 function () { ES.ObjectCreate(null); },
2883 SyntaxError,
2884 'without a native Object.create, can not create null objects'
2885 );
2886
2887 st.end();
2888 });
2889
2890 t.end();
2891 });
2892
2893 test('OrdinaryCreateFromConstructor', function (t) {
2894 forEach(v.nonFunctions, function (nonFunction) {
2895 t['throws'](
2896 function () { ES.OrdinaryCreateFromConstructor(nonFunction, '%Array.prototype%'); },
2897 TypeError,
2898 debug(nonFunction) + ' is not a constructor'
2899 );
2900 });
2901
2902 forEach(arrowFns, function (arrowFn) {
2903 t['throws'](
2904 function () { ES.OrdinaryCreateFromConstructor(arrowFn, '%Array.prototype%'); },
2905 TypeError,
2906 debug(arrowFn) + ' is not a constructor'
2907 );
2908 });
2909
2910 t.test('proto arg', function (st) {
2911 var Parent = function Parent() {};
2912 Parent.prototype.foo = {};
2913 var child = ES.OrdinaryCreateFromConstructor(Parent, '%Array.prototype%');
2914 st.equal(child instanceof Parent, true, 'child is instanceof Parent');
2915 st.equal(child instanceof Array, false, 'child is not instanceof Array');
2916 st.equal(child.foo, Parent.prototype.foo, 'child inherits properties from Parent.prototype');
2917
2918 st.end();
2919 });
2920
2921 t.test('internal slots arg', function (st) {
2922 st.doesNotThrow(
2923 function () { ES.OrdinaryCreateFromConstructor(function () {}, '%Array.prototype%', []); },
2924 'an empty slot list is valid'
2925 );
2926
2927 st['throws'](
2928 function () { ES.OrdinaryCreateFromConstructor(function () {}, '%Array.prototype%', ['a']); },
2929 SyntaxError,
2930 'internal slots are not supported'
2931 );
2932
2933 st.end();
2934 });
2935
2936 t.end();
2937 });
2938
2939 test('OrdinaryGetOwnProperty', function (t) {
2940 forEach(v.primitives, function (primitive) {
2941 t['throws'](
2942 function () { ES.OrdinaryGetOwnProperty(primitive, ''); },
2943 TypeError,
2944 'O: ' + debug(primitive) + ' is not an Object'
2945 );
2946 });
2947 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
2948 t['throws'](
2949 function () { ES.OrdinaryGetOwnProperty({}, nonPropertyKey); },
2950 TypeError,
2951 'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
2952 );
2953 });
2954
2955 t.equal(ES.OrdinaryGetOwnProperty({}, 'not in the object'), undefined, 'missing property yields undefined');
2956 t.equal(ES.OrdinaryGetOwnProperty({}, 'toString'), undefined, 'inherited non-own property yields undefined');
2957
2958 t.deepEqual(
2959 ES.OrdinaryGetOwnProperty({ a: 1 }, 'a'),
2960 ES.ToPropertyDescriptor({
2961 configurable: true,
2962 enumerable: true,
2963 value: 1,
2964 writable: true
2965 }),
2966 'own assigned data property yields expected descriptor'
2967 );
2968
2969 t.deepEqual(
2970 ES.OrdinaryGetOwnProperty(/a/, 'lastIndex'),
2971 ES.ToPropertyDescriptor({
2972 configurable: false,
2973 enumerable: false,
2974 value: 0,
2975 writable: true
2976 }),
2977 'regex lastIndex yields expected descriptor'
2978 );
2979
2980 t.deepEqual(
2981 ES.OrdinaryGetOwnProperty([], 'length'),
2982 ES.ToPropertyDescriptor({
2983 configurable: false,
2984 enumerable: false,
2985 value: 0,
2986 writable: true
2987 }),
2988 'array length yields expected descriptor'
2989 );
2990
2991 if (!Object.isFrozen || !Object.isFrozen(Object.prototype)) {
2992 t.deepEqual(
2993 ES.OrdinaryGetOwnProperty(Object.prototype, 'toString'),
2994 ES.ToPropertyDescriptor({
2995 configurable: true,
2996 enumerable: false,
2997 value: Object.prototype.toString,
2998 writable: true
2999 }),
3000 'own non-enumerable data property yields expected descriptor'
3001 );
3002 }
3003
3004 t.test('ES5+', { skip: !defineProperty.oDP }, function (st) {
3005 var O = {};
3006 defineProperty(O, 'foo', {
3007 configurable: false,
3008 enumerable: false,
3009 value: O,
3010 writable: true
3011 });
3012
3013 st.deepEqual(
3014 ES.OrdinaryGetOwnProperty(O, 'foo'),
3015 ES.ToPropertyDescriptor({
3016 configurable: false,
3017 enumerable: false,
3018 value: O,
3019 writable: true
3020 }),
3021 'defined own property yields expected descriptor'
3022 );
3023
3024 st.end();
3025 });
3026
3027 t.end();
3028 });
3029
3030 test('OrdinaryDefineOwnProperty', { skip: !getOwnPropertyDescriptor }, function (t) {
3031 forEach(v.primitives, function (primitive) {
3032 t['throws'](
3033 function () { ES.OrdinaryDefineOwnProperty(primitive, {}, []); },
3034 TypeError,
3035 'O: ' + debug(primitive) + ' is not an Object'
3036 );
3037 });
3038 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3039 t['throws'](
3040 function () { ES.OrdinaryDefineOwnProperty({}, nonPropertyKey, v.genericDescriptor()); },
3041 TypeError,
3042 'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
3043 );
3044 });
3045 forEach(v.primitives, function (primitive) {
3046 t['throws'](
3047 function () { ES.OrdinaryDefineOwnProperty(primitive, '', v.genericDescriptor()); },
3048 TypeError,
3049 'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
3050 );
3051 });
3052
3053 var O = {};
3054 var P = 'property key';
3055 var Desc = v.accessorDescriptor();
3056 t.equal(
3057 ES.OrdinaryDefineOwnProperty(O, P, Desc),
3058 true,
3059 'operation is successful'
3060 );
3061 t.deepEqual(
3062 getOwnPropertyDescriptor(O, P),
3063 ES.FromPropertyDescriptor(ES.CompletePropertyDescriptor(Desc)),
3064 'expected property descriptor is defined'
3065 );
3066
3067 t.end();
3068 });
3069
3070 test('OrdinaryHasInstance', function (t) {
3071 forEach(v.nonFunctions, function (nonFunction) {
3072 t.equal(ES.OrdinaryHasInstance(nonFunction, {}), false, debug(nonFunction) + ' is not callable');
3073 });
3074
3075 forEach(v.primitives, function (primitive) {
3076 t.equal(ES.OrdinaryHasInstance(function () {}, primitive), false, debug(primitive) + ' is not an object');
3077 });
3078
3079 var C = function C() {};
3080 var D = function D() {};
3081 t.equal(ES.OrdinaryHasInstance(C, new C()), true, 'constructor function has an instance of itself');
3082 t.equal(ES.OrdinaryHasInstance(C, new D()), false, 'constructor/instance mismatch is false');
3083 t.equal(ES.OrdinaryHasInstance(D, new C()), false, 'instance/constructor mismatch is false');
3084 t.equal(ES.OrdinaryHasInstance(C, {}), false, 'plain object is not an instance of a constructor');
3085 t.equal(ES.OrdinaryHasInstance(Object, {}), true, 'plain object is an instance of Object');
3086
3087 t.end();
3088 });
3089
3090 test('OrdinaryHasProperty', function (t) {
3091 forEach(v.primitives, function (primitive) {
3092 t['throws'](
3093 function () { ES.OrdinaryHasProperty(primitive, ''); },
3094 TypeError,
3095 debug(primitive) + ' is not an object'
3096 );
3097 });
3098 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3099 t['throws'](
3100 function () { ES.OrdinaryHasProperty({}, nonPropertyKey); },
3101 TypeError,
3102 'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
3103 );
3104 });
3105
3106 t.equal(ES.OrdinaryHasProperty({ a: 1 }, 'a'), true, 'own property is true');
3107 t.equal(ES.OrdinaryHasProperty({}, 'toString'), true, 'inherited property is true');
3108 t.equal(ES.OrdinaryHasProperty({}, 'nope'), false, 'absent property is false');
3109
3110 t.end();
3111 });
3112
3113 test('QuoteJSONString', function (t) {
3114 forEach(v.nonStrings, function (nonString) {
3115 t['throws'](
3116 function () { ES.QuoteJSONString(nonString); },
3117 TypeError,
3118 debug(nonString) + ' is not a String'
3119 );
3120 });
3121
3122 t.equal(ES.QuoteJSONString(''), '""', '"" gets properly JSON-quoted');
3123 t.equal(ES.QuoteJSONString('a'), '"a"', '"a" gets properly JSON-quoted');
3124 t.equal(ES.QuoteJSONString('"'), '"\\""', '"\\"" gets properly JSON-quoted');
3125 t.equal(ES.QuoteJSONString('\b'), '"\\b"', '"\\b" gets properly JSON-quoted');
3126 t.equal(ES.QuoteJSONString('\t'), '"\\t"', '"\\t" gets properly JSON-quoted');
3127 t.equal(ES.QuoteJSONString('\n'), '"\\n"', '"\\n" gets properly JSON-quoted');
3128 t.equal(ES.QuoteJSONString('\f'), '"\\f"', '"\\f" gets properly JSON-quoted');
3129 t.equal(ES.QuoteJSONString('\r'), '"\\r"', '"\\r" gets properly JSON-quoted');
3130 t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted');
3131 t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted');
3132 t.equal(ES.QuoteJSONString('\u0019'), '"\\u0019"', '"\\u0019" gets properly JSON-quoted');
3133
3134 t.end();
3135 });
3136
3137 test('RegExpCreate', function (t) {
3138 forEach(v.nonStrings, function (nonString) {
3139 if (typeof nonString !== 'symbol') {
3140 var p = typeof nonString === 'undefined' ? '' : nonString;
3141 t.equal(
3142 String(ES.RegExpCreate(p, 'g')),
3143 '/' + (String(p) || '(?:)') + '/g',
3144 debug(nonString) + ' becomes `/' + String(p) + '/g`'
3145 );
3146 }
3147 });
3148
3149 t.deepEqual(ES.RegExpCreate(), new RegExp(), 'undefined pattern and flags yields empty regex');
3150
3151 t.end();
3152 });
3153
3154 test('RegExpExec', function (t) {
3155 forEach(v.primitives, function (primitive) {
3156 t['throws'](
3157 function () { ES.RegExpExec(primitive); },
3158 TypeError,
3159 '"R" argument must be an object; ' + debug(primitive) + ' is not'
3160 );
3161 });
3162
3163 forEach(v.nonStrings, function (nonString) {
3164 t['throws'](
3165 function () { ES.RegExpExec({}, nonString); },
3166 TypeError,
3167 '"S" argument must be a String; ' + debug(nonString) + ' is not'
3168 );
3169 });
3170
3171 t.test('gets and calls a callable "exec"', function (st) {
3172 var str = '123';
3173 var o = {
3174 exec: function (S) {
3175 st.equal(this, o, '"exec" receiver is R');
3176 st.equal(S, str, '"exec" argument is S');
3177
3178 return null;
3179 }
3180 };
3181 st.plan(2);
3182 ES.RegExpExec(o, str);
3183 st.end();
3184 });
3185
3186 t.test('throws if a callable "exec" returns a non-null non-object', function (st) {
3187 var str = '123';
3188 st.plan(v.nonNullPrimitives.length);
3189 forEach(v.nonNullPrimitives, function (nonNullPrimitive) {
3190 st['throws'](
3191 function () { ES.RegExpExec({ exec: function () { return nonNullPrimitive; } }, str); },
3192 TypeError,
3193 '"exec" method must return `null` or an Object; ' + debug(nonNullPrimitive) + ' is not'
3194 );
3195 });
3196 st.end();
3197 });
3198
3199 t.test('actual regex that should match against a string', function (st) {
3200 var S = 'aabc';
3201 var R = /a/g;
3202 var match1 = ES.RegExpExec(R, S);
3203 var expected1 = assign(['a'], kludgeMatch(R, { index: 0, input: S }));
3204 var match2 = ES.RegExpExec(R, S);
3205 var expected2 = assign(['a'], kludgeMatch(R, { index: 1, input: S }));
3206 var match3 = ES.RegExpExec(R, S);
3207 st.deepEqual(match1, expected1, 'match object 1 is as expected');
3208 st.deepEqual(match2, expected2, 'match object 2 is as expected');
3209 st.equal(match3, null, 'match 3 is null as expected');
3210 st.end();
3211 });
3212
3213 t.test('actual regex that should match against a string, with shadowed "exec"', function (st) {
3214 var S = 'aabc';
3215 var R = /a/g;
3216 defineProperty(R, 'exec', { value: undefined });
3217 var match1 = ES.RegExpExec(R, S);
3218 var expected1 = assign(['a'], kludgeMatch(R, { index: 0, input: S }));
3219 var match2 = ES.RegExpExec(R, S);
3220 var expected2 = assign(['a'], kludgeMatch(R, { index: 1, input: S }));
3221 var match3 = ES.RegExpExec(R, S);
3222 st.deepEqual(match1, expected1, 'match object 1 is as expected');
3223 st.deepEqual(match2, expected2, 'match object 2 is as expected');
3224 st.equal(match3, null, 'match 3 is null as expected');
3225 st.end();
3226 });
3227 t.end();
3228 });
3229
3230 test('RequireObjectCoercible', function (t) {
3231 t.equal(false, 'CheckObjectCoercible' in ES, 'CheckObjectCoercible -> RequireObjectCoercible in ES6');
3232 t['throws'](function () { return ES.RequireObjectCoercible(undefined); }, TypeError, 'undefined throws');
3233 t['throws'](function () { return ES.RequireObjectCoercible(null); }, TypeError, 'null throws');
3234 var isCoercible = function (value) {
3235 t.doesNotThrow(function () { return ES.RequireObjectCoercible(value); }, debug(value) + ' does not throw');
3236 };
3237 forEach(v.objects.concat(v.nonNullPrimitives), isCoercible);
3238 t.end();
3239 });
3240
3241 test('SameValueZero', function (t) {
3242 t.equal(true, ES.SameValueZero(NaN, NaN), 'NaN is SameValueZero as NaN');
3243 t.equal(true, ES.SameValueZero(0, -0), '+0 is SameValueZero as -0');
3244 forEach(v.objects.concat(v.primitives), function (val) {
3245 t.equal(val === val, ES.SameValueZero(val, val), debug(val) + ' is SameValueZero to itself');
3246 });
3247 t.end();
3248 });
3249
3250 test('Set', function (t) {
3251 forEach(v.primitives, function (primitive) {
3252 t['throws'](
3253 function () { ES.Set(primitive, '', null, false); },
3254 TypeError,
3255 debug(primitive) + ' is not an Object'
3256 );
3257 });
3258
3259 forEach(v.nonPropertyKeys, function (nonKey) {
3260 t['throws'](
3261 function () { ES.Set({}, nonKey, null, false); },
3262 TypeError,
3263 debug(nonKey) + ' is not a Property Key'
3264 );
3265 });
3266
3267 forEach(v.nonBooleans, function (nonBoolean) {
3268 t['throws'](
3269 function () { ES.Set({}, '', null, nonBoolean); },
3270 TypeError,
3271 debug(nonBoolean) + ' is not a Boolean'
3272 );
3273 });
3274
3275 var o = {};
3276 var value = {};
3277 ES.Set(o, 'key', value, true);
3278 t.deepEqual(o, { key: value }, 'key is set');
3279
3280 t.test('nonwritable', { skip: !defineProperty.oDP }, function (st) {
3281 var obj = { a: value };
3282 defineProperty(obj, 'a', { writable: false });
3283
3284 st['throws'](
3285 function () { ES.Set(obj, 'a', {}, true); },
3286 TypeError,
3287 'can not Set nonwritable property'
3288 );
3289
3290 st.doesNotThrow(
3291 function () {
3292 st.equal(ES.Set(obj, 'a', {}, false), false, 'unsuccessful Set returns false');
3293 },
3294 'setting Throw to false prevents an exception'
3295 );
3296
3297 st.end();
3298 });
3299
3300 t.test('nonconfigurable', { skip: !defineProperty.oDP }, function (st) {
3301 var obj = { a: value };
3302 defineProperty(obj, 'a', { configurable: false });
3303
3304 st.equal(ES.Set(obj, 'a', value, true), true, 'successful Set returns true');
3305 st.deepEqual(obj, { a: value }, 'key is set');
3306
3307 st.end();
3308 });
3309
3310 t.test('doesn’t call [[Get]] in conforming strict mode environments', { skip: noThrowOnStrictViolation }, function (st) {
3311 var getterCalled = false;
3312 var setterCalls = 0;
3313 var obj = {};
3314 defineProperty(obj, 'a', {
3315 get: function () {
3316 getterCalled = true;
3317 },
3318 set: function () {
3319 setterCalls += 1;
3320 }
3321 });
3322
3323 st.equal(ES.Set(obj, 'a', value, false), true, 'successful Set returns true');
3324 st.equal(setterCalls, 1, 'setter was called once');
3325 st.equal(getterCalled, false, 'getter was not called');
3326
3327 st.end();
3328 });
3329
3330 t.end();
3331 });
3332
3333 test('SetFunctionName', function (t) {
3334 forEach(v.nonFunctions, function (nonFunction) {
3335 t['throws'](
3336 function () { ES.SetFunctionName(nonFunction, ''); },
3337 TypeError,
3338 debug(nonFunction) + ' is not a Function'
3339 );
3340 });
3341
3342 t.test('non-extensible function', { skip: !Object.preventExtensions }, function (st) {
3343 var f = getNamelessFunction();
3344 Object.preventExtensions(f);
3345 st['throws'](
3346 function () { ES.SetFunctionName(f, ''); },
3347 TypeError,
3348 'throws on a non-extensible function'
3349 );
3350 st.end();
3351 });
3352
3353 t.test('has an own name property', { skip: !functionsHaveNames }, function (st) {
3354 st['throws'](
3355 function () { ES.SetFunctionName(function g() {}, ''); },
3356 TypeError,
3357 'throws if function has an own `name` property'
3358 );
3359 st.end();
3360 });
3361
3362 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3363 t['throws'](
3364 function () { ES.SetFunctionName(getNamelessFunction(), nonPropertyKey); },
3365 TypeError,
3366 debug(nonPropertyKey) + ' is not a Symbol or String'
3367 );
3368 });
3369
3370 t.test('symbols', { skip: !v.hasSymbols || has(getNamelessFunction(), 'name') }, function (st) {
3371 var pairs = [
3372 [Symbol(), ''],
3373 [Symbol(undefined), ''],
3374 [Symbol(null), '[null]'],
3375 [Symbol(''), getInferredName ? '[]' : ''],
3376 [Symbol.iterator, '[Symbol.iterator]'],
3377 [Symbol('foo'), '[foo]']
3378 ];
3379 forEach(pairs, function (pair) {
3380 var sym = pair[0];
3381 var desc = pair[1];
3382 var f = getNamelessFunction();
3383 ES.SetFunctionName(f, sym);
3384 st.equal(f.name, desc, debug(sym) + ' yields a name of ' + debug(desc));
3385 });
3386
3387 st.end();
3388 });
3389
3390 var f = getNamelessFunction();
3391 t.test('when names are configurable', { skip: !functionsHaveConfigurableNames || has(f, 'name') }, function (st) {
3392 // without prefix
3393 st.notEqual(f.name, 'foo', 'precondition');
3394 ES.SetFunctionName(f, 'foo');
3395 st.equal(f.name, 'foo', 'function name is set without a prefix');
3396
3397 // with prefix
3398 var g = getNamelessFunction();
3399 st.notEqual(g.name, 'pre- foo', 'precondition');
3400 ES.SetFunctionName(g, 'foo', 'pre-');
3401 st.equal(g.name, 'pre- foo', 'function name is set with a prefix');
3402
3403 st.end();
3404 });
3405
3406 t.end();
3407 });
3408
3409 test('SetIntegrityLevel', function (t) {
3410 forEach(v.primitives, function (primitive) {
3411 t['throws'](
3412 function () { ES.SetIntegrityLevel(primitive); },
3413 TypeError,
3414 debug(primitive) + ' is not an Object'
3415 );
3416 });
3417
3418 t['throws'](
3419 function () { ES.SetIntegrityLevel({}); },
3420 /^TypeError: Assertion failed: `level` must be `"sealed"` or `"frozen"`$/,
3421 '`level` must be `"sealed"` or `"frozen"`'
3422 );
3423
3424 var O = { a: 1 };
3425 t.test('sealed', { skip: !Object.preventExtensions || noThrowOnStrictViolation }, function (st) {
3426 st.equal(ES.SetIntegrityLevel(O, 'sealed'), true);
3427 st['throws'](
3428 function () { O.b = 2; },
3429 /^TypeError: (Cannot|Can't) add property b, object is not extensible$/,
3430 'sealing prevent new properties from being added'
3431 );
3432 O.a = 2;
3433 st.equal(O.a, 2, 'pre-frozen, existing properties are mutable');
3434 st.end();
3435 });
3436
3437 t.test('frozen', { skip: !Object.freeze || noThrowOnStrictViolation }, function (st) {
3438 st.equal(ES.SetIntegrityLevel(O, 'frozen'), true);
3439 st['throws'](
3440 function () { O.a = 3; },
3441 /^TypeError: Cannot assign to read only property 'a' of /,
3442 'freezing prevents existing properties from being mutated'
3443 );
3444 st.end();
3445 });
3446
3447 t.end();
3448 });
3449
3450 test('SpeciesConstructor', function (t) {
3451 t['throws'](function () { ES.SpeciesConstructor(null); }, TypeError);
3452 t['throws'](function () { ES.SpeciesConstructor(undefined); }, TypeError);
3453
3454 var defaultConstructor = function Foo() {};
3455
3456 t.equal(
3457 ES.SpeciesConstructor({ constructor: undefined }, defaultConstructor),
3458 defaultConstructor,
3459 'undefined constructor returns defaultConstructor'
3460 );
3461
3462 t['throws'](
3463 function () { return ES.SpeciesConstructor({ constructor: null }, defaultConstructor); },
3464 TypeError,
3465 'non-undefined non-object constructor throws'
3466 );
3467
3468 t.test('with Symbol.species', { skip: !hasSpecies }, function (st) {
3469 var Bar = function Bar() {};
3470 Bar[Symbol.species] = null;
3471
3472 st.equal(
3473 ES.SpeciesConstructor(new Bar(), defaultConstructor),
3474 defaultConstructor,
3475 'undefined/null Symbol.species returns default constructor'
3476 );
3477
3478 var Baz = function Baz() {};
3479 Baz[Symbol.species] = Bar;
3480 st.equal(
3481 ES.SpeciesConstructor(new Baz(), defaultConstructor),
3482 Bar,
3483 'returns Symbol.species constructor value'
3484 );
3485
3486 Baz[Symbol.species] = {};
3487 st['throws'](
3488 function () { ES.SpeciesConstructor(new Baz(), defaultConstructor); },
3489 TypeError,
3490 'throws when non-constructor non-null non-undefined species value found'
3491 );
3492
3493 st.end();
3494 });
3495
3496 t.end();
3497 });
3498
3499 test('SplitMatch', function (t) {
3500 forEach(v.nonStrings, function (nonString) {
3501 t['throws'](
3502 function () { ES.SplitMatch(nonString, 0, ''); },
3503 TypeError,
3504 'S: ' + debug(nonString) + ' is not a String'
3505 );
3506 t['throws'](
3507 function () { ES.SplitMatch('', 0, nonString); },
3508 TypeError,
3509 'R: ' + debug(nonString) + ' is not a String'
3510 );
3511 });
3512
3513 forEach(v.nonNumbers.concat(v.nonIntegerNumbers), function (nonIntegerNumber) {
3514 t['throws'](
3515 function () { ES.SplitMatch('', nonIntegerNumber, ''); },
3516 TypeError,
3517 'q: ' + debug(nonIntegerNumber) + ' is not an integer'
3518 );
3519 });
3520
3521 t.equal(ES.SplitMatch('abc', 0, 'a'), 1, '"a" is found at index 0, before index 1, in "abc"');
3522 t.equal(ES.SplitMatch('abc', 1, 'a'), false, '"a" is not found at index 1 in "abc"');
3523 t.equal(ES.SplitMatch('abc', 2, 'a'), false, '"a" is not found at index 2 in "abc"');
3524
3525 t.equal(ES.SplitMatch('abc', 0, 'b'), false, '"a" is not found at index 0 in "abc"');
3526 t.equal(ES.SplitMatch('abc', 1, 'b'), 2, '"b" is found at index 1, before index 2, in "abc"');
3527 t.equal(ES.SplitMatch('abc', 2, 'b'), false, '"a" is not found at index 2 in "abc"');
3528
3529 t.equal(ES.SplitMatch('abc', 0, 'c'), false, '"a" is not found at index 0 in "abc"');
3530 t.equal(ES.SplitMatch('abc', 1, 'c'), false, '"a" is not found at index 1 in "abc"');
3531 t.equal(ES.SplitMatch('abc', 2, 'c'), 3, '"c" is found at index 2, before index 3, in "abc"');
3532
3533 t.equal(ES.SplitMatch('a', 0, 'ab'), false, 'R longer than S yields false');
3534
3535 var s = 'a' + wholePoo + 'c';
3536 t.equal(ES.SplitMatch(s, 1, wholePoo), 3, debug(wholePoo) + ' is found at index 1, before index 3, in ' + debug(s));
3537
3538 t.end();
3539 });
3540
3541 test('StringCreate', function (t) {
3542 forEach(v.nonStrings, function (nonString) {
3543 t['throws'](
3544 function () { ES.StringCreate(nonString); },
3545 TypeError,
3546 debug(nonString) + ' is not a String'
3547 );
3548 });
3549
3550 t.deepEqual(ES.StringCreate('foo', String.prototype), Object('foo'), '"foo" with `String.prototype` makes `Object("foo")');
3551
3552 if ($setProto) {
3553 var proto = {};
3554 t.equal($getProto(ES.StringCreate('', proto)), proto, '[[Prototype]] is set as expected');
3555 } else {
3556 t['throws'](
3557 function () { ES.StringCreate('', proto); },
3558 SyntaxError,
3559 'setting [[Prototype]] is not supported in this env'
3560 );
3561 }
3562
3563 t.equal(ES.StringCreate('a', String.prototype).length, 'a'.length, 'length is preserved');
3564
3565 t.end();
3566 });
3567
3568 test('StringGetIndexProperty', function (t) {
3569 forEach(v.nonStrings.concat(v.strings), function (nonStringObjects) {
3570 t['throws'](
3571 function () { ES.StringGetIndexProperty(nonStringObjects); },
3572 TypeError,
3573 debug(nonStringObjects) + ' is not a boxed String Object'
3574 );
3575 });
3576
3577 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3578 t['throws'](
3579 function () { ES.StringGetIndexProperty('', nonPropertyKey); },
3580 TypeError,
3581 debug(nonPropertyKey) + ' is not a Property Key'
3582 );
3583 });
3584
3585 forEach(v.symbols, function (symbol) {
3586 t.equal(
3587 ES.StringGetIndexProperty(Object('a'), symbol),
3588 undefined,
3589 debug(symbol) + ' is a Property Key, but not a String'
3590 );
3591 });
3592
3593 // a string where CanonicalNumericIndexString returns undefined, a non-integer, or -0
3594 forEach(['-1', '-0', 'undefined'].concat(v.nonIntegerNumbers), function (nonIndex) {
3595 var S = Object('abc');
3596 t.equal(
3597 ES.StringGetIndexProperty(S, String(nonIndex)),
3598 undefined,
3599 debug(nonIndex) + ' is not an index inside ' + debug(S)
3600 );
3601 });
3602
3603 forEach(v.strings, function (str) {
3604 var S = Object(str);
3605 for (var i = 0; i < str.length; i += 1) {
3606 var desc = {
3607 '[[Configurable]]': false,
3608 '[[Enumerable]]': true,
3609 '[[Value]]': str.charAt(i),
3610 '[[Writable]]': false
3611 };
3612 t.deepEqual(
3613 ES.StringGetIndexProperty(S, String(i)),
3614 desc,
3615 'boxed String ' + debug(S) + ' at index ' + debug(i) + ' is ' + debug(desc)
3616 );
3617 }
3618 t.equal(
3619 ES.StringGetIndexProperty(S, String(str.length)),
3620 undefined,
3621 'boxed String ' + debug(S) + ' at OOB index ' + debug(str.length) + ' is `undefined'
3622 );
3623 });
3624
3625 t.end();
3626 });
3627
3628 test('SymbolDescriptiveString', function (t) {
3629 forEach(v.nonSymbolPrimitives.concat(v.objects), function (nonSymbol) {
3630 t['throws'](
3631 function () { ES.SymbolDescriptiveString(nonSymbol); },
3632 TypeError,
3633 debug(nonSymbol) + ' is not a Symbol'
3634 );
3635 });
3636
3637 t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
3638 st.equal(ES.SymbolDescriptiveString(Symbol()), 'Symbol()', 'undefined description');
3639 st.equal(ES.SymbolDescriptiveString(Symbol('')), 'Symbol()', 'empty string description');
3640 st.equal(ES.SymbolDescriptiveString(Symbol.iterator), 'Symbol(Symbol.iterator)', 'well-known symbol');
3641 st.equal(ES.SymbolDescriptiveString(Symbol('foo')), 'Symbol(foo)', 'string description');
3642
3643 st.end();
3644 });
3645
3646 t.end();
3647 });
3648
3649 test('TestIntegrityLevel', function (t) {
3650 forEach(v.primitives, function (primitive) {
3651 t['throws'](
3652 function () { ES.TestIntegrityLevel(primitive); },
3653 TypeError,
3654 debug(primitive) + ' is not an Object'
3655 );
3656 });
3657
3658 t['throws'](
3659 function () { ES.TestIntegrityLevel({ a: 1 }); },
3660 /^TypeError: Assertion failed: `level` must be `"sealed"` or `"frozen"`$/,
3661 '`level` must be `"sealed"` or `"frozen"`'
3662 );
3663
3664 t.equal(ES.TestIntegrityLevel({ a: 1 }, 'sealed'), false, 'basic object is not sealed');
3665 t.equal(ES.TestIntegrityLevel({ a: 1 }, 'frozen'), false, 'basic object is not frozen');
3666
3667 t.test('preventExtensions', { skip: !Object.preventExtensions }, function (st) {
3668 var o = Object.preventExtensions({ a: 1 });
3669 st.equal(ES.TestIntegrityLevel(o, 'sealed'), false, 'nonextensible object is not sealed');
3670 st.equal(ES.TestIntegrityLevel(o, 'frozen'), false, 'nonextensible object is not frozen');
3671
3672 var empty = Object.preventExtensions({});
3673 st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty nonextensible object is sealed');
3674 st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty nonextensible object is frozen');
3675 st.end();
3676 });
3677
3678 t.test('seal', { skip: !Object.seal }, function (st) {
3679 var o = Object.seal({ a: 1 });
3680 st.equal(ES.TestIntegrityLevel(o, 'sealed'), true, 'sealed object is sealed');
3681 st.equal(ES.TestIntegrityLevel(o, 'frozen'), false, 'sealed object is not frozen');
3682
3683 var empty = Object.seal({});
3684 st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty sealed object is sealed');
3685 st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty sealed object is frozen');
3686
3687 st.end();
3688 });
3689
3690 t.test('freeze', { skip: !Object.freeze }, function (st) {
3691 var o = Object.freeze({ a: 1 });
3692 st.equal(ES.TestIntegrityLevel(o, 'sealed'), true, 'frozen object is sealed');
3693 st.equal(ES.TestIntegrityLevel(o, 'frozen'), true, 'frozen object is frozen');
3694
3695 var empty = Object.freeze({});
3696 st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty frozen object is sealed');
3697 st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty frozen object is frozen');
3698
3699 st.end();
3700 });
3701
3702 t.end();
3703 });
3704
3705 test('thisNumberValue', function (t) {
3706 forEach(v.nonNumbers, function (nonNumber) {
3707 t['throws'](
3708 function () { ES.thisNumberValue(nonNumber); },
3709 TypeError,
3710 debug(nonNumber) + ' is not a Number'
3711 );
3712 });
3713
3714 forEach(v.numbers, function (number) {
3715 t.equal(ES.thisNumberValue(number), number, debug(number) + ' is its own thisNumberValue');
3716 var obj = Object(number);
3717 t.equal(ES.thisNumberValue(obj), number, debug(obj) + ' is the boxed thisNumberValue');
3718 });
3719
3720 t.end();
3721 });
3722
3723 test('thisBooleanValue', function (t) {
3724 forEach(v.nonBooleans, function (nonBoolean) {
3725 t['throws'](
3726 function () { ES.thisBooleanValue(nonBoolean); },
3727 TypeError,
3728 debug(nonBoolean) + ' is not a Boolean'
3729 );
3730 });
3731
3732 forEach(v.booleans, function (boolean) {
3733 t.equal(ES.thisBooleanValue(boolean), boolean, debug(boolean) + ' is its own thisBooleanValue');
3734 var obj = Object(boolean);
3735 t.equal(ES.thisBooleanValue(obj), boolean, debug(obj) + ' is the boxed thisBooleanValue');
3736 });
3737
3738 t.end();
3739 });
3740
3741 test('thisStringValue', function (t) {
3742 forEach(v.nonStrings, function (nonString) {
3743 t['throws'](
3744 function () { ES.thisStringValue(nonString); },
3745 TypeError,
3746 debug(nonString) + ' is not a String'
3747 );
3748 });
3749
3750 forEach(v.strings, function (string) {
3751 t.equal(ES.thisStringValue(string), string, debug(string) + ' is its own thisStringValue');
3752 var obj = Object(string);
3753 t.equal(ES.thisStringValue(obj), string, debug(obj) + ' is the boxed thisStringValue');
3754 });
3755
3756 t.end();
3757 });
3758
3759 test('thisTimeValue', function (t) {
3760 forEach(v.primitives.concat(v.objects), function (nonDate) {
3761 t['throws'](
3762 function () { ES.thisTimeValue(nonDate); },
3763 TypeError,
3764 debug(nonDate) + ' is not a Date'
3765 );
3766 });
3767
3768 forEach(v.timestamps, function (timestamp) {
3769 var date = new Date(timestamp);
3770
3771 t.equal(ES.thisTimeValue(date), timestamp, debug(date) + ' is its own thisTimeValue');
3772 });
3773
3774 t.end();
3775 });
3776
3777 test('ToDateString', function (t) {
3778 forEach(v.nonNumbers, function (nonNumber) {
3779 t['throws'](
3780 function () { ES.ToDateString(nonNumber); },
3781 TypeError,
3782 debug(nonNumber) + ' is not a Number'
3783 );
3784 });
3785
3786 t.equal(ES.ToDateString(NaN), 'Invalid Date', 'NaN becomes "Invalid Date"');
3787 var now = +new Date();
3788 t.equal(ES.ToDateString(now), Date(now), 'any timestamp becomes `Date(timestamp)`');
3789 t.end();
3790 });
3791
3792 test('ToInt16', function (t) {
3793 t.equal(0, ES.ToInt16(NaN), 'NaN coerces to +0');
3794 forEach([0, Infinity], function (num) {
3795 t.equal(0, ES.ToInt16(num), num + ' returns +0');
3796 t.equal(0, ES.ToInt16(-num), '-' + num + ' returns +0');
3797 });
3798 t['throws'](function () { return ES.ToInt16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
3799 t.equal(ES.ToInt16(0x100000000), 0, '2^32 returns +0');
3800 t.equal(ES.ToInt16(0x100000000 - 1), -1, '2^32 - 1 returns -1');
3801 t.equal(ES.ToInt16(0x80000000), 0, '2^31 returns +0');
3802 t.equal(ES.ToInt16(0x80000000 - 1), -1, '2^31 - 1 returns -1');
3803 t.equal(ES.ToInt16(0x10000), 0, '2^16 returns +0');
3804 t.equal(ES.ToInt16(0x10000 - 1), -1, '2^16 - 1 returns -1');
3805 t.end();
3806 });
3807
3808 test('ToInt8', function (t) {
3809 t.equal(0, ES.ToInt8(NaN), 'NaN coerces to +0');
3810 forEach([0, Infinity], function (num) {
3811 t.equal(0, ES.ToInt8(num), num + ' returns +0');
3812 t.equal(0, ES.ToInt8(-num), '-' + num + ' returns +0');
3813 });
3814 t['throws'](function () { return ES.ToInt8(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
3815 t.equal(ES.ToInt8(0x100000000), 0, '2^32 returns +0');
3816 t.equal(ES.ToInt8(0x100000000 - 1), -1, '2^32 - 1 returns -1');
3817 t.equal(ES.ToInt8(0x80000000), 0, '2^31 returns +0');
3818 t.equal(ES.ToInt8(0x80000000 - 1), -1, '2^31 - 1 returns -1');
3819 t.equal(ES.ToInt8(0x10000), 0, '2^16 returns +0');
3820 t.equal(ES.ToInt8(0x10000 - 1), -1, '2^16 - 1 returns -1');
3821 t.equal(ES.ToInt8(0x100), 0, '2^8 returns +0');
3822 t.equal(ES.ToInt8(0x100 - 1), -1, '2^8 - 1 returns -1');
3823 t.equal(ES.ToInt8(0x10), 0x10, '2^4 returns 2^4');
3824 t.end();
3825 });
3826
3827 test('ToNumber', function (t) {
3828 testToNumber(t, ES, ES.ToNumber);
3829
3830 t.end();
3831 });
3832
3833 test('ToUint8', function (t) {
3834 t.equal(0, ES.ToUint8(NaN), 'NaN coerces to +0');
3835 forEach([0, Infinity], function (num) {
3836 t.equal(0, ES.ToUint8(num), num + ' returns +0');
3837 t.equal(0, ES.ToUint8(-num), '-' + num + ' returns +0');
3838 });
3839 t['throws'](function () { return ES.ToUint8(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
3840 t.equal(ES.ToUint8(0x100000000), 0, '2^32 returns +0');
3841 t.equal(ES.ToUint8(0x100000000 - 1), 0x100 - 1, '2^32 - 1 returns 2^8 - 1');
3842 t.equal(ES.ToUint8(0x80000000), 0, '2^31 returns +0');
3843 t.equal(ES.ToUint8(0x80000000 - 1), 0x100 - 1, '2^31 - 1 returns 2^8 - 1');
3844 t.equal(ES.ToUint8(0x10000), 0, '2^16 returns +0');
3845 t.equal(ES.ToUint8(0x10000 - 1), 0x100 - 1, '2^16 - 1 returns 2^8 - 1');
3846 t.equal(ES.ToUint8(0x100), 0, '2^8 returns +0');
3847 t.equal(ES.ToUint8(0x100 - 1), 0x100 - 1, '2^8 - 1 returns 2^16 - 1');
3848 t.equal(ES.ToUint8(0x10), 0x10, '2^4 returns 2^4');
3849 t.equal(ES.ToUint8(0x10 - 1), 0x10 - 1, '2^4 - 1 returns 2^4 - 1');
3850 t.end();
3851 });
3852
3853 test('ToUint8Clamp', function (t) {
3854 t.equal(0, ES.ToUint8Clamp(NaN), 'NaN coerces to +0');
3855 t.equal(0, ES.ToUint8Clamp(0), '+0 returns +0');
3856 t.equal(0, ES.ToUint8Clamp(-0), '-0 returns +0');
3857 t.equal(0, ES.ToUint8Clamp(-Infinity), '-Infinity returns +0');
3858 t['throws'](function () { return ES.ToUint8Clamp(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
3859 forEach([255, 256, 0x100000, Infinity], function (number) {
3860 t.equal(255, ES.ToUint8Clamp(number), number + ' coerces to 255');
3861 });
3862 t.equal(1, ES.ToUint8Clamp(1.49), '1.49 coerces to 1');
3863 t.equal(2, ES.ToUint8Clamp(1.5), '1.5 coerces to 2, because 2 is even');
3864 t.equal(2, ES.ToUint8Clamp(1.51), '1.51 coerces to 2');
3865
3866 t.equal(2, ES.ToUint8Clamp(2.49), '2.49 coerces to 2');
3867 t.equal(2, ES.ToUint8Clamp(2.5), '2.5 coerces to 2, because 2 is even');
3868 t.equal(3, ES.ToUint8Clamp(2.51), '2.51 coerces to 3');
3869 t.end();
3870 });
3871
3872 test('ToLength', function (t) {
3873 t['throws'](function () { return ES.ToLength(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError');
3874 t.equal(3, ES.ToLength(v.coercibleObject), 'coercibleObject coerces to 3');
3875 t.equal(42, ES.ToLength('42.5'), '"42.5" coerces to 42');
3876 t.equal(7, ES.ToLength(7.3), '7.3 coerces to 7');
3877 forEach([-0, -1, -42, -Infinity], function (negative) {
3878 t.equal(0, ES.ToLength(negative), negative + ' coerces to +0');
3879 });
3880 t.equal(MAX_SAFE_INTEGER, ES.ToLength(MAX_SAFE_INTEGER + 1), '2^53 coerces to 2^53 - 1');
3881 t.equal(MAX_SAFE_INTEGER, ES.ToLength(MAX_SAFE_INTEGER + 3), '2^53 + 2 coerces to 2^53 - 1');
3882 t.end();
3883 });
3884
3885 test('ToPropertyKey', function (t) {
3886 forEach(v.objects.concat(v.nonSymbolPrimitives), function (value) {
3887 t.equal(ES.ToPropertyKey(value), String(value), 'ToPropertyKey(value) === String(value) for non-Symbols');
3888 });
3889
3890 forEach(v.symbols, function (symbol) {
3891 t.equal(
3892 ES.ToPropertyKey(symbol),
3893 symbol,
3894 'ToPropertyKey(' + debug(symbol) + ') === ' + debug(symbol)
3895 );
3896 t.equal(
3897 ES.ToPropertyKey(Object(symbol)),
3898 symbol,
3899 'ToPropertyKey(' + debug(Object(symbol)) + ') === ' + debug(symbol)
3900 );
3901 });
3902
3903 t.end();
3904 });
3905
3906 test('ToString', function (t) {
3907 forEach(v.objects.concat(v.nonSymbolPrimitives), function (item) {
3908 t.equal(ES.ToString(item), String(item), 'ES.ToString(' + debug(item) + ') ToStrings to String(' + debug(item) + ')');
3909 });
3910
3911 t['throws'](function () { return ES.ToString(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
3912
3913 forEach(v.symbols, function (symbol) {
3914 t['throws'](function () { return ES.ToString(symbol); }, TypeError, debug(symbol) + ' throws');
3915 });
3916 t.end();
3917 });
3918
3919 test('Type', function (t) {
3920 t.equal(ES.Type(), 'Undefined', 'Type() is Undefined');
3921 t.equal(ES.Type(undefined), 'Undefined', 'Type(undefined) is Undefined');
3922 t.equal(ES.Type(null), 'Null', 'Type(null) is Null');
3923 t.equal(ES.Type(true), 'Boolean', 'Type(true) is Boolean');
3924 t.equal(ES.Type(false), 'Boolean', 'Type(false) is Boolean');
3925 t.equal(ES.Type(0), 'Number', 'Type(0) is Number');
3926 t.equal(ES.Type(NaN), 'Number', 'Type(NaN) is Number');
3927 t.equal(ES.Type('abc'), 'String', 'Type("abc") is String');
3928 t.equal(ES.Type(function () {}), 'Object', 'Type(function () {}) is Object');
3929 t.equal(ES.Type({}), 'Object', 'Type({}) is Object');
3930
3931 t.test('symbols', { skip: !v.hasSymbols }, function (st) {
3932 st.equal(ES.Type(Symbol.iterator), 'Symbol', 'Type(Symbol.iterator) is Symbol');
3933 st.end();
3934 });
3935
3936 t.end();
3937 });
3938
3939 test('ValidateAndApplyPropertyDescriptor', function (t) {
3940 forEach(v.nonUndefinedPrimitives, function (nonUndefinedPrimitive) {
3941 t['throws'](
3942 function () { ES.ValidateAndApplyPropertyDescriptor(nonUndefinedPrimitive, '', false, v.genericDescriptor(), v.genericDescriptor()); },
3943 TypeError,
3944 'O: ' + debug(nonUndefinedPrimitive) + ' is not undefined or an Object'
3945 );
3946 });
3947
3948 forEach(v.nonBooleans, function (nonBoolean) {
3949 t['throws'](
3950 function () {
3951 return ES.ValidateAndApplyPropertyDescriptor(
3952 undefined,
3953 null,
3954 nonBoolean,
3955 v.genericDescriptor(),
3956 v.genericDescriptor()
3957 );
3958 },
3959 TypeError,
3960 'extensible: ' + debug(nonBoolean) + ' is not a Boolean'
3961 );
3962 });
3963
3964 forEach(v.primitives, function (primitive) {
3965 // Desc must be a Property Descriptor
3966 t['throws'](
3967 function () {
3968 return ES.ValidateAndApplyPropertyDescriptor(
3969 undefined,
3970 null,
3971 false,
3972 primitive,
3973 v.genericDescriptor()
3974 );
3975 },
3976 TypeError,
3977 'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
3978 );
3979 });
3980
3981 forEach(v.nonUndefinedPrimitives, function (primitive) {
3982 // current must be undefined or a Property Descriptor
3983 t['throws'](
3984 function () {
3985 return ES.ValidateAndApplyPropertyDescriptor(
3986 undefined,
3987 null,
3988 false,
3989 v.genericDescriptor(),
3990 primitive
3991 );
3992 },
3993 TypeError,
3994 'current: ' + debug(primitive) + ' is not a Property Descriptor or undefined'
3995 );
3996 });
3997
3998 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3999 // if O is an object, P must be a property key
4000 t['throws'](
4001 function () {
4002 return ES.ValidateAndApplyPropertyDescriptor(
4003 {},
4004 nonPropertyKey,
4005 false,
4006 v.genericDescriptor(),
4007 v.genericDescriptor()
4008 );
4009 },
4010 TypeError,
4011 'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
4012 );
4013 });
4014
4015 t.test('current is undefined', function (st) {
4016 var propertyKey = 'howdy';
4017
4018 st.test('generic descriptor', function (s2t) {
4019 var generic = v.genericDescriptor();
4020 generic['[[Enumerable]]'] = true;
4021 var O = {};
4022 ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, generic);
4023 s2t.equal(
4024 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, generic),
4025 false,
4026 'when extensible is false, nothing happens'
4027 );
4028 s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
4029 s2t.equal(
4030 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, generic),
4031 true,
4032 'operation is successful'
4033 );
4034 var expected = {};
4035 expected[propertyKey] = undefined;
4036 s2t.deepEqual(O, expected, 'generic descriptor has been defined as an own data property');
4037 s2t.end();
4038 });
4039
4040 st.test('data descriptor', function (s2t) {
4041 var data = v.dataDescriptor();
4042 data['[[Enumerable]]'] = true;
4043
4044 var O = {};
4045 s2t.equal(
4046 ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, data),
4047 true,
4048 'noop when O is undefined'
4049 );
4050 s2t.equal(
4051 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, data),
4052 false,
4053 'when extensible is false, nothing happens'
4054 );
4055 s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
4056 s2t.equal(
4057 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, data),
4058 true,
4059 'operation is successful'
4060 );
4061 var expected = {};
4062 expected[propertyKey] = data['[[Value]]'];
4063 s2t.deepEqual(O, expected, 'data descriptor has been defined as an own data property');
4064 s2t.end();
4065 });
4066
4067 st.test('accessor descriptor', { skip: !defineProperty.oDP }, function (s2t) {
4068 var count = 0;
4069 var accessor = v.accessorDescriptor();
4070 accessor['[[Enumerable]]'] = true;
4071 accessor['[[Get]]'] = function () {
4072 count += 1;
4073 return count;
4074 };
4075
4076 var O = {};
4077 ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, accessor);
4078 s2t.equal(
4079 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, accessor),
4080 false,
4081 'when extensible is false, nothing happens'
4082 );
4083 s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
4084 s2t.equal(
4085 ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, accessor),
4086 true,
4087 'operation is successful'
4088 );
4089 var expected = {};
4090 expected[propertyKey] = accessor['[[Get]]']() + 1;
4091 s2t.deepEqual(O, expected, 'accessor descriptor has been defined as an own accessor property');
4092 s2t.end();
4093 });
4094
4095 st.end();
4096 });
4097
4098 t.test('every field in Desc is absent', { skip: 'it is unclear if having no fields qualifies Desc to be a Property Descriptor' });
4099
4100 forEach([v.dataDescriptor, v.accessorDescriptor, v.mutatorDescriptor], function (getDescriptor) {
4101 t.equal(
4102 ES.ValidateAndApplyPropertyDescriptor(undefined, 'property key', true, getDescriptor(), getDescriptor()),
4103 true,
4104 'when Desc and current are the same, early return true'
4105 );
4106 });
4107
4108 t.test('current is nonconfigurable', function (st) {
4109 // note: these must not be generic descriptors, or else the algorithm returns an early true
4110 st.equal(
4111 ES.ValidateAndApplyPropertyDescriptor(
4112 undefined,
4113 'property key',
4114 true,
4115 v.descriptors.configurable(v.dataDescriptor()),
4116 v.descriptors.nonConfigurable(v.dataDescriptor())
4117 ),
4118 false,
4119 'false if Desc is configurable'
4120 );
4121
4122 st.equal(
4123 ES.ValidateAndApplyPropertyDescriptor(
4124 undefined,
4125 'property key',
4126 true,
4127 v.descriptors.enumerable(v.dataDescriptor()),
4128 v.descriptors.nonEnumerable(v.dataDescriptor())
4129 ),
4130 false,
4131 'false if Desc is Enumerable and current is not'
4132 );
4133
4134 st.equal(
4135 ES.ValidateAndApplyPropertyDescriptor(
4136 undefined,
4137 'property key',
4138 true,
4139 v.descriptors.nonEnumerable(v.dataDescriptor()),
4140 v.descriptors.enumerable(v.dataDescriptor())
4141 ),
4142 false,
4143 'false if Desc is not Enumerable and current is'
4144 );
4145
4146 var descLackingEnumerable = v.accessorDescriptor();
4147 delete descLackingEnumerable['[[Enumerable]]'];
4148 st.equal(
4149 ES.ValidateAndApplyPropertyDescriptor(
4150 undefined,
4151 'property key',
4152 true,
4153 descLackingEnumerable,
4154 v.descriptors.enumerable(v.accessorDescriptor())
4155 ),
4156 true,
4157 'not false if Desc lacks Enumerable'
4158 );
4159
4160 st.end();
4161 });
4162
4163 t.test('Desc and current: one is a data descriptor, one is not', { skip: !defineProperty || !getOwnPropertyDescriptor }, function (st) {
4164 // note: Desc must be configurable if current is nonconfigurable, to hit this branch
4165 st.equal(
4166 ES.ValidateAndApplyPropertyDescriptor(
4167 undefined,
4168 'property key',
4169 true,
4170 v.descriptors.configurable(v.accessorDescriptor()),
4171 v.descriptors.nonConfigurable(v.dataDescriptor())
4172 ),
4173 false,
4174 'false if current (data) is nonconfigurable'
4175 );
4176
4177 st.equal(
4178 ES.ValidateAndApplyPropertyDescriptor(
4179 undefined,
4180 'property key',
4181 true,
4182 v.descriptors.configurable(v.dataDescriptor()),
4183 v.descriptors.nonConfigurable(v.accessorDescriptor())
4184 ),
4185 false,
4186 'false if current (not data) is nonconfigurable'
4187 );
4188
4189 // one is data and one is not,
4190 // // if current is data, convert to accessor
4191 // // else convert to data
4192
4193 var startsWithData = {
4194 'property key': 42
4195 };
4196 st.equal(
4197 ES.ValidateAndApplyPropertyDescriptor(
4198 startsWithData,
4199 'property key',
4200 true,
4201 v.descriptors.enumerable(v.descriptors.configurable(v.accessorDescriptor())),
4202 v.descriptors.enumerable(v.descriptors.configurable(v.dataDescriptor()))
4203 ),
4204 true,
4205 'operation is successful: current is data, Desc is accessor'
4206 );
4207 var shouldBeAccessor = getOwnPropertyDescriptor(startsWithData, 'property key');
4208 st.equal(typeof shouldBeAccessor.get, 'function', 'has a getter');
4209
4210 var key = 'property key';
4211 var startsWithAccessor = {};
4212 defineProperty(startsWithAccessor, key, {
4213 configurable: true,
4214 enumerable: true,
4215 get: function get() { return 42; }
4216 });
4217 st.equal(
4218 ES.ValidateAndApplyPropertyDescriptor(
4219 startsWithAccessor,
4220 key,
4221 true,
4222 v.descriptors.enumerable(v.descriptors.configurable(v.dataDescriptor())),
4223 v.descriptors.enumerable(v.descriptors.configurable(v.accessorDescriptor(42)))
4224 ),
4225 true,
4226 'operation is successful: current is accessor, Desc is data'
4227 );
4228 var shouldBeData = getOwnPropertyDescriptor(startsWithAccessor, 'property key');
4229 st.deepEqual(shouldBeData, { configurable: true, enumerable: true, value: 42, writable: false }, 'is a data property');
4230
4231 st.end();
4232 });
4233
4234 t.test('Desc and current are both data descriptors', function (st) {
4235 st.equal(
4236 ES.ValidateAndApplyPropertyDescriptor(
4237 undefined,
4238 'property key',
4239 true,
4240 v.descriptors.writable(v.dataDescriptor()),
4241 v.descriptors.nonWritable(v.descriptors.nonConfigurable(v.dataDescriptor()))
4242 ),
4243 false,
4244 'false if frozen current and writable Desc'
4245 );
4246
4247 st.equal(
4248 ES.ValidateAndApplyPropertyDescriptor(
4249 undefined,
4250 'property key',
4251 true,
4252 v.descriptors.configurable({ '[[Value]]': 42 }),
4253 v.descriptors.nonWritable({ '[[Value]]': 7 })
4254 ),
4255 false,
4256 'false if nonwritable current has a different value than Desc'
4257 );
4258
4259 st.end();
4260 });
4261
4262 t.test('current is nonconfigurable; Desc and current are both accessor descriptors', function (st) {
4263 st.equal(
4264 ES.ValidateAndApplyPropertyDescriptor(
4265 undefined,
4266 'property key',
4267 true,
4268 v.mutatorDescriptor(),
4269 v.descriptors.nonConfigurable(v.mutatorDescriptor())
4270 ),
4271 false,
4272 'false if both Sets are not equal'
4273 );
4274
4275 st.equal(
4276 ES.ValidateAndApplyPropertyDescriptor(
4277 undefined,
4278 'property key',
4279 true,
4280 v.accessorDescriptor(),
4281 v.descriptors.nonConfigurable(v.accessorDescriptor())
4282 ),
4283 false,
4284 'false if both Gets are not equal'
4285 );
4286
4287 st.end();
4288 });
4289
4290 t.end();
4291 });
4292};
4293
4294var es2016 = function ES2016(ES, ops, expectedMissing, skips) {
4295 es2015(ES, ops, expectedMissing, assign(assign({}, skips), {
4296 StringGetIndexProperty: true
4297 }));
4298 var test = makeTest(skips);
4299
4300 test('IterableToArrayLike', function (t) {
4301 t.test('custom iterables', { skip: !v.hasSymbols }, function (st) {
4302 var O = {};
4303 O[Symbol.iterator] = function () {
4304 var i = -1;
4305 return {
4306 next: function () {
4307 i += 1;
4308 return {
4309 done: i >= 5,
4310 value: i
4311 };
4312 }
4313 };
4314 };
4315 st.deepEqual(
4316 ES.IterableToArrayLike(O),
4317 [0, 1, 2, 3, 4],
4318 'Symbol.iterator method is called and values collected'
4319 );
4320
4321 st.end();
4322 });
4323
4324 t.deepEqual(ES.IterableToArrayLike('abc'), ['a', 'b', 'c'], 'a string of code units spreads');
4325 t.deepEqual(ES.IterableToArrayLike('💩'), ['💩'], 'a string of code points spreads');
4326 t.deepEqual(ES.IterableToArrayLike('a💩c'), ['a', '💩', 'c'], 'a string of code points and units spreads');
4327
4328 var arr = [1, 2, 3];
4329 t.deepEqual(ES.IterableToArrayLike(arr), arr, 'an array becomes a similar array');
4330 t.notEqual(ES.IterableToArrayLike(arr), arr, 'an array becomes a different, but similar, array');
4331
4332 var O = {};
4333 t.equal(ES.IterableToArrayLike(O), O, 'a non-iterable non-array non-string object is returned directly');
4334
4335 t.end();
4336 });
4337
4338 test('OrdinaryGetPrototypeOf', function (t) {
4339 t.test('values', { skip: !$getProto }, function (st) {
4340 st.equal(ES.OrdinaryGetPrototypeOf([]), Array.prototype, 'array [[Prototype]] is Array.prototype');
4341 st.equal(ES.OrdinaryGetPrototypeOf({}), Object.prototype, 'object [[Prototype]] is Object.prototype');
4342 st.equal(ES.OrdinaryGetPrototypeOf(/a/g), RegExp.prototype, 'regex [[Prototype]] is RegExp.prototype');
4343 st.equal(ES.OrdinaryGetPrototypeOf(Object('')), String.prototype, 'boxed string [[Prototype]] is String.prototype');
4344 st.equal(ES.OrdinaryGetPrototypeOf(Object(42)), Number.prototype, 'boxed number [[Prototype]] is Number.prototype');
4345 st.equal(ES.OrdinaryGetPrototypeOf(Object(true)), Boolean.prototype, 'boxed boolean [[Prototype]] is Boolean.prototype');
4346 if (v.hasSymbols) {
4347 st.equal(ES.OrdinaryGetPrototypeOf(Object(Symbol.iterator)), Symbol.prototype, 'boxed symbol [[Prototype]] is Symbol.prototype');
4348 }
4349 st.end();
4350 });
4351
4352 forEach(v.primitives, function (primitive) {
4353 t['throws'](
4354 function () { ES.OrdinaryGetPrototypeOf(primitive); },
4355 TypeError,
4356 debug(primitive) + ' is not an Object'
4357 );
4358 });
4359 t.end();
4360 });
4361
4362 test('OrdinarySetPrototypeOf', { skip: !$getProto || !$setProto }, function (t) {
4363 var a = [];
4364 var proto = {};
4365
4366 t.equal(ES.OrdinaryGetPrototypeOf(a), Array.prototype, 'precondition');
4367 t.equal(ES.OrdinarySetPrototypeOf(a, proto), true, 'setting prototype is successful');
4368 t.equal(ES.OrdinaryGetPrototypeOf(a), proto, 'postcondition');
4369
4370 t.end();
4371 });
4372
4373 test('SameValueNonNumber', function (t) {
4374 var willThrow = [
4375 [3, 4],
4376 [NaN, 4],
4377 [4, ''],
4378 ['abc', true],
4379 [{}, false]
4380 ];
4381 forEach(willThrow, function (nums) {
4382 t['throws'](function () { return ES.SameValueNonNumber.apply(ES, nums); }, TypeError, 'value must be same type and non-number');
4383 });
4384
4385 forEach(v.objects.concat(v.nonNumberPrimitives), function (val) {
4386 t.equal(val === val, ES.SameValueNonNumber(val, val), debug(val) + ' is SameValueNonNumber to itself');
4387 });
4388
4389 t.end();
4390 });
4391
4392 test('UTF16Encoding', function (t) {
4393 forEach(v.nonNumbers, function (nonNumber) {
4394 t['throws'](
4395 function () { ES.UTF16Encoding(nonNumber); },
4396 TypeError,
4397 debug(nonNumber) + ' is not a Number'
4398 );
4399 });
4400
4401 t['throws'](
4402 function () { ES.UTF16Encoding(-1); },
4403 TypeError,
4404 '-1 is < 0'
4405 );
4406
4407 t['throws'](
4408 function () { ES.UTF16Encoding(0x10FFFF + 1); },
4409 TypeError,
4410 '0x10FFFF + 1 is > 0x10FFFF'
4411 );
4412
4413 t.equal(ES.UTF16Encoding(0xD83D), leadingPoo, '0xD83D is the first half of ' + wholePoo);
4414 t.equal(ES.UTF16Encoding(0xDCA9), trailingPoo, '0xDCA9 is the last half of ' + wholePoo);
4415 t.equal(ES.UTF16Encoding(0x1F4A9), wholePoo, '0xDCA9 is the last half of ' + wholePoo);
4416
4417 t.end();
4418 });
4419
4420 test('UTF16Decode', function (t) {
4421 t['throws'](
4422 function () { ES.UTF16Decode('a'.charCodeAt(0), trailingPoo.charCodeAt(0)); },
4423 TypeError,
4424 '"a" is not a leading surrogate'
4425 );
4426 t['throws'](
4427 function () { ES.UTF16Decode(leadingPoo.charCodeAt(0), 'b'.charCodeAt(0)); },
4428 TypeError,
4429 '"b" is not a trailing surrogate'
4430 );
4431
4432 t.equal(ES.UTF16Decode(leadingPoo.charCodeAt(0), trailingPoo.charCodeAt(0)), wholePoo);
4433
4434 t.end();
4435 });
4436};
4437
4438var es2017 = function ES2017(ES, ops, expectedMissing, skips) {
4439 es2016(ES, ops, expectedMissing, assign({}, skips, {
4440 EnumerableOwnNames: true,
4441 IterableToArrayLike: true
4442 }));
4443 var test = makeTest(skips);
4444
4445 test('EnumerableOwnProperties', function (t) {
4446 var obj = testEnumerableOwnNames(t, function (O) {
4447 return ES.EnumerableOwnProperties(O, 'key');
4448 });
4449
4450 t.deepEqual(
4451 ES.EnumerableOwnProperties(obj, 'value'),
4452 [obj.own],
4453 'returns enumerable own values'
4454 );
4455
4456 t.deepEqual(
4457 ES.EnumerableOwnProperties(obj, 'key+value'),
4458 [['own', obj.own]],
4459 'returns enumerable own entries'
4460 );
4461
4462 t.end();
4463 });
4464
4465 test('IterableToList', function (t) {
4466 var customIterator = function () {
4467 var i = -1;
4468 return {
4469 next: function () {
4470 i += 1;
4471 return {
4472 done: i >= 5,
4473 value: i
4474 };
4475 }
4476 };
4477 };
4478
4479 t.deepEqual(
4480 ES.IterableToList({}, customIterator),
4481 [0, 1, 2, 3, 4],
4482 'iterator method is called and values collected'
4483 );
4484
4485 t.test('Symbol support', { skip: !v.hasSymbols }, function (st) {
4486 st.deepEqual(ES.IterableToList('abc', String.prototype[Symbol.iterator]), ['a', 'b', 'c'], 'a string of code units spreads');
4487 st.deepEqual(ES.IterableToList('☃', String.prototype[Symbol.iterator]), ['☃'], 'a string of code points spreads');
4488
4489 var arr = [1, 2, 3];
4490 st.deepEqual(ES.IterableToList(arr, arr[Symbol.iterator]), arr, 'an array becomes a similar array');
4491 st.notEqual(ES.IterableToList(arr, arr[Symbol.iterator]), arr, 'an array becomes a different, but similar, array');
4492
4493 st.end();
4494 });
4495
4496 t['throws'](
4497 function () { ES.IterableToList({}, void 0); },
4498 TypeError,
4499 'non-function iterator method'
4500 );
4501
4502 t.end();
4503 });
4504
4505 test('StringGetOwnProperty', function (t) {
4506 forEach(v.nonStrings.concat(v.strings), function (nonBoxedString) {
4507 t['throws'](
4508 function () { ES.StringGetOwnProperty(nonBoxedString, '0'); },
4509 TypeError,
4510 debug(nonBoxedString) + ' is not a boxed String'
4511 );
4512 });
4513 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
4514 t['throws'](
4515 function () { ES.StringGetOwnProperty(Object(''), nonPropertyKey); },
4516 TypeError,
4517 debug(nonPropertyKey) + ' is not a Property Key'
4518 );
4519 });
4520
4521 t.equal(ES.StringGetOwnProperty(Object(''), '0'), undefined, 'empty boxed string yields undefined');
4522
4523 forEach(v.strings, function (string) {
4524 if (string) {
4525 var S = Object(string);
4526 for (var i = 0; i < string.length; i += 1) {
4527 var descriptor = ES.StringGetOwnProperty(S, String(i));
4528 t.deepEqual(
4529 descriptor,
4530 {
4531 '[[Configurable]]': false,
4532 '[[Enumerable]]': true,
4533 '[[Value]]': string.charAt(i),
4534 '[[Writable]]': false
4535 },
4536 debug(string) + ': property ' + debug(String(i)) + ': returns expected descriptor'
4537 );
4538 }
4539 }
4540 });
4541
4542 t.end();
4543 });
4544
4545 test('ToIndex', function (t) {
4546 t.equal(ES.ToIndex(), 0, 'no value gives +0');
4547 t.equal(ES.ToIndex(undefined), 0, 'undefined value gives +0');
4548 t.equal(ES.ToIndex(-0), 0, '-0 gives +0');
4549
4550 t['throws'](function () { ES.ToIndex(-1); }, RangeError, 'negative numbers throw');
4551
4552 t['throws'](function () { ES.ToIndex(MAX_SAFE_INTEGER + 1); }, RangeError, 'too large numbers throw');
4553
4554 t.equal(ES.ToIndex(3), 3, 'numbers work');
4555 t.equal(ES.ToIndex(v.valueOfOnlyObject), 4, 'coercible objects are coerced');
4556
4557 t.end();
4558 });
4559};
4560
4561var es2018 = function ES2018(ES, ops, expectedMissing, skips) {
4562 es2017(ES, ops, expectedMissing, assign({}, skips, {
4563 EnumerableOwnProperties: true,
4564 GetSubstitution: true,
4565 IsPropertyDescriptor: true
4566 }));
4567 var test = makeTest(skips);
4568
4569 test('CopyDataProperties', function (t) {
4570 t.test('first argument: target', function (st) {
4571 forEach(v.primitives, function (primitive) {
4572 st['throws'](
4573 function () { ES.CopyDataProperties(primitive, {}, []); },
4574 TypeError,
4575 debug(primitive) + ' is not an Object'
4576 );
4577 });
4578 st.end();
4579 });
4580
4581 t.test('second argument: source', function (st) {
4582 var frozenTarget = Object.freeze ? Object.freeze({}) : {};
4583 forEach(v.nullPrimitives, function (nullish) {
4584 st.equal(
4585 ES.CopyDataProperties(frozenTarget, nullish, []),
4586 frozenTarget,
4587 debug(nullish) + ' "source" yields identical, unmodified target'
4588 );
4589 });
4590
4591 forEach(v.nonNullPrimitives, function (objectCoercible) {
4592 var target = {};
4593 var result = ES.CopyDataProperties(target, objectCoercible, []);
4594 st.equal(result, target, 'result === target');
4595 st.deepEqual(keys(result), keys(Object(objectCoercible)), 'target ends up with keys of ' + debug(objectCoercible));
4596 });
4597
4598 st.test('enumerable accessor property', { skip: !defineProperty.oDP }, function (s2t) {
4599 var target = {};
4600 var source = {};
4601 defineProperty(source, 'a', {
4602 enumerable: true,
4603 get: function () { return 42; }
4604 });
4605 var result = ES.CopyDataProperties(target, source, []);
4606 s2t.equal(result, target, 'result === target');
4607 s2t.deepEqual(result, { a: 42 }, 'target ends up with enumerable accessor of source');
4608 s2t.end();
4609 });
4610
4611 st.end();
4612 });
4613
4614 t.test('third argument: excludedItems', function (st) {
4615 forEach(v.objects.concat(v.primitives), function (nonArray) {
4616 st['throws'](
4617 function () { ES.CopyDataProperties({}, {}, nonArray); },
4618 TypeError,
4619 debug(nonArray) + ' is not an Array'
4620 );
4621 });
4622
4623 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
4624 st['throws'](
4625 function () { ES.CopyDataProperties({}, {}, [nonPropertyKey]); },
4626 TypeError,
4627 debug(nonPropertyKey) + ' is not a Property Key'
4628 );
4629 });
4630
4631 var result = ES.CopyDataProperties({}, { a: 1, b: 2, c: 3 }, ['b']);
4632 st.deepEqual(keys(result).sort(), ['a', 'c'].sort(), 'excluded string keys are excluded');
4633
4634 st.test('excluding symbols', { skip: !v.hasSymbols }, function (s2t) {
4635 var source = {};
4636 forEach(v.symbols, function (symbol) {
4637 source[symbol] = true;
4638 });
4639
4640 var includedSymbols = v.symbols.slice(1);
4641 var excludedSymbols = v.symbols.slice(0, 1);
4642 var target = ES.CopyDataProperties({}, source, excludedSymbols);
4643
4644 forEach(includedSymbols, function (symbol) {
4645 s2t.equal(has(target, symbol), true, debug(symbol) + ' is included');
4646 });
4647
4648 forEach(excludedSymbols, function (symbol) {
4649 s2t.equal(has(target, symbol), false, debug(symbol) + ' is excluded');
4650 });
4651
4652 s2t.end();
4653 });
4654
4655 st.end();
4656 });
4657
4658 // TODO: CopyDataProperties does not throw when copying fails
4659
4660 t.end();
4661 });
4662
4663 test('DateString', function (t) {
4664 forEach(v.nonNumbers.concat(NaN), function (nonNumberOrNaN) {
4665 t['throws'](
4666 function () { ES.DateString(nonNumberOrNaN); },
4667 TypeError,
4668 debug(nonNumberOrNaN) + ' is not a non-NaN Number'
4669 );
4670 });
4671
4672 t.equal(ES.DateString(Date.UTC(2019, 8, 10, 7, 8, 9)), 'Tue Sep 10 2019');
4673 t.equal(ES.DateString(Date.UTC(2016, 1, 29, 7, 8, 9)), 'Mon Feb 29 2016'); // leap day
4674 t.end();
4675 });
4676
4677 test('EnumerableOwnPropertyNames', function (t) {
4678 var obj = testEnumerableOwnNames(t, function (O) {
4679 return ES.EnumerableOwnPropertyNames(O, 'key');
4680 });
4681
4682 t.deepEqual(
4683 ES.EnumerableOwnPropertyNames(obj, 'value'),
4684 [obj.own],
4685 'returns enumerable own values'
4686 );
4687
4688 t.deepEqual(
4689 ES.EnumerableOwnPropertyNames(obj, 'key+value'),
4690 [['own', obj.own]],
4691 'returns enumerable own entries'
4692 );
4693
4694 t.end();
4695 });
4696
4697 test('GetSubstitution', function (t) {
4698 forEach(v.nonStrings, function (nonString) {
4699 t['throws'](
4700 function () { ES.GetSubstitution(nonString, '', 0, [], undefined, ''); },
4701 TypeError,
4702 '`matched`: ' + debug(nonString) + ' is not a String'
4703 );
4704
4705 t['throws'](
4706 function () { ES.GetSubstitution('', nonString, 0, [], undefined, ''); },
4707 TypeError,
4708 '`str`: ' + debug(nonString) + ' is not a String'
4709 );
4710
4711 t['throws'](
4712 function () { ES.GetSubstitution('', '', 0, [], undefined, nonString); },
4713 TypeError,
4714 '`replacement`: ' + debug(nonString) + ' is not a String'
4715 );
4716
4717 t['throws'](
4718 function () { ES.GetSubstitution('', '', 0, [nonString], undefined, ''); },
4719 TypeError,
4720 '`captures`: ' + debug([nonString]) + ' is not an Array of strings'
4721 );
4722 });
4723
4724 forEach(v.notNonNegativeIntegers, function (nonNonNegativeInteger) {
4725 t['throws'](
4726 function () { ES.GetSubstitution('', '', nonNonNegativeInteger, [], undefined, ''); },
4727 TypeError,
4728 '`position`: ' + debug(nonNonNegativeInteger) + ' is not a non-negative integer'
4729 );
4730 });
4731
4732 forEach(v.nonArrays, function (nonArray) {
4733 t['throws'](
4734 function () { ES.GetSubstitution('', '', 0, nonArray, undefined, ''); },
4735 TypeError,
4736 '`captures`: ' + debug(nonArray) + ' is not an Array'
4737 );
4738 });
4739
4740 t.equal(
4741 ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, '123'),
4742 '123',
4743 'returns the substitution'
4744 );
4745 t.equal(
4746 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '$$2$'),
4747 '$2$',
4748 'supports $$, and trailing $'
4749 );
4750
4751 t.equal(
4752 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$&<'),
4753 '>abcdef<',
4754 'supports $&'
4755 );
4756
4757 t.equal(
4758 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$`<'),
4759 '><',
4760 'supports $` at position 0'
4761 );
4762 t.equal(
4763 ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, '>$`<'),
4764 '>ab<',
4765 'supports $` at position > 0'
4766 );
4767
4768 t.equal(
4769 ES.GetSubstitution('def', 'abcdefghi', 7, [], undefined, ">$'<"),
4770 '><',
4771 "supports $' at a position where there's less than `matched.length` chars left"
4772 );
4773 t.equal(
4774 ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, ">$'<"),
4775 '>ghi<',
4776 "supports $' at a position where there's more than `matched.length` chars left"
4777 );
4778
4779 for (var i = 0; i < 100; i += 1) {
4780 var captures = [];
4781 captures[i] = 'test';
4782 if (i > 0) {
4783 t.equal(
4784 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$' + i + '<'),
4785 '>undefined<',
4786 'supports $' + i + ' with no captures'
4787 );
4788 t.equal(
4789 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$' + i),
4790 '>undefined',
4791 'supports $' + i + ' at the end of the replacement, with no captures'
4792 );
4793 t.equal(
4794 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$' + i + '<'),
4795 '><',
4796 'supports $' + i + ' with a capture at that index'
4797 );
4798 t.equal(
4799 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$' + i),
4800 '>',
4801 'supports $' + i + ' at the end of the replacement, with a capture at that index'
4802 );
4803 }
4804 if (i < 10) {
4805 t.equal(
4806 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$0' + i + '<'),
4807 i === 0 ? '><' : '>undefined<',
4808 'supports $0' + i + ' with no captures'
4809 );
4810 t.equal(
4811 ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$0' + i),
4812 i === 0 ? '>' : '>undefined',
4813 'supports $0' + i + ' at the end of the replacement, with no captures'
4814 );
4815 t.equal(
4816 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$0' + i + '<'),
4817 '><',
4818 'supports $0' + i + ' with a capture at that index'
4819 );
4820 t.equal(
4821 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$0' + i),
4822 '>',
4823 'supports $0' + i + ' at the end of the replacement, with a capture at that index'
4824 );
4825 }
4826 }
4827
4828 t.test('named captures', function (st) {
4829 var namedCaptures = {
4830 foo: 'foo!'
4831 };
4832
4833 st.equal(
4834 ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, namedCaptures, 'a>$<foo><z'),
4835 'a>foo!<z',
4836 'supports named captures'
4837 );
4838
4839 st.end();
4840 });
4841
4842 t.end();
4843 });
4844
4845 test('IsStringPrefix', function (t) {
4846 forEach(v.nonStrings, function (nonString) {
4847 t['throws'](
4848 function () { ES.IsStringPrefix(nonString, 'a'); },
4849 TypeError,
4850 'first arg: ' + debug(nonString) + ' is not a string'
4851 );
4852 t['throws'](
4853 function () { ES.IsStringPrefix('a', nonString); },
4854 TypeError,
4855 'second arg: ' + debug(nonString) + ' is not a string'
4856 );
4857 });
4858
4859 forEach(v.strings, function (string) {
4860 t.equal(ES.IsStringPrefix(string, string), true, debug(string) + ' is a prefix of itself');
4861
4862 t.equal(ES.IsStringPrefix('', string), true, 'the empty string is a prefix of everything');
4863 });
4864
4865 t.equal(ES.IsStringPrefix('abc', 'abcd'), true, '"abc" is a prefix of "abcd"');
4866 t.equal(ES.IsStringPrefix('abcd', 'abc'), false, '"abcd" is not a prefix of "abc"');
4867
4868 t.equal(ES.IsStringPrefix('a', 'bc'), false, '"a" is not a prefix of "bc"');
4869
4870 t.end();
4871 });
4872
4873 test('NumberToString', function (t) {
4874 forEach(v.nonNumbers, function (nonNumber) {
4875 t['throws'](
4876 function () { ES.NumberToString(nonNumber); },
4877 TypeError,
4878 debug(nonNumber) + ' is not a Number'
4879 );
4880 });
4881
4882 forEach(v.numbers, function (number) {
4883 t.equal(ES.NumberToString(number), String(number), debug(number) + ' stringifies to ' + number);
4884 });
4885
4886 t.end();
4887 });
4888
4889 test('PromiseResolve', function (t) {
4890 t.test('Promises unsupported', { skip: typeof Promise === 'function' }, function (st) {
4891 st['throws'](
4892 function () { ES.PromiseResolve(); },
4893 SyntaxError,
4894 'Promises are not supported'
4895 );
4896 st.end();
4897 });
4898
4899 t.test('Promises supported', { skip: typeof Promise !== 'function' }, function (st) {
4900 st.plan(2);
4901
4902 var a = {};
4903 var b = {};
4904 var fulfilled = Promise.resolve(a);
4905 var rejected = Promise.reject(b);
4906
4907 ES.PromiseResolve(Promise, fulfilled).then(function (x) {
4908 st.equal(x, a, 'fulfilled promise resolves to fulfilled');
4909 });
4910
4911 ES.PromiseResolve(Promise, rejected)['catch'](function (e) {
4912 st.equal(e, b, 'rejected promise resolves to rejected');
4913 });
4914 });
4915
4916 t.end();
4917 });
4918
4919 test('SetFunctionLength', function (t) {
4920 forEach(v.nonFunctions, function (nonFunction) {
4921 t['throws'](
4922 function () { ES.SetFunctionLength(nonFunction, 0); },
4923 TypeError,
4924 debug(nonFunction) + ' is not a Function'
4925 );
4926 });
4927
4928 t.test('non-extensible function', { skip: !Object.preventExtensions }, function (st) {
4929 var F = function F() {};
4930 Object.preventExtensions(F);
4931
4932 st['throws'](
4933 function () { ES.SetFunctionLength(F, 0); },
4934 TypeError,
4935 'non-extensible function throws'
4936 );
4937 st.end();
4938 });
4939
4940 var HasLength = function HasLength(_) { return _; };
4941 t.equal(has(HasLength, 'length'), true, 'precondition: `HasLength` has own length');
4942 t['throws'](
4943 function () { ES.SetFunctionLength(HasLength, 0); },
4944 TypeError,
4945 'function with own length throws'
4946 );
4947
4948 t.test('no length', { skip: !functionsHaveConfigurableNames }, function (st) {
4949 var HasNoLength = function HasNoLength() {};
4950 delete HasNoLength.length;
4951
4952 st.equal(has(HasNoLength, 'length'), false, 'precondition: `HasNoLength` has no own length');
4953
4954 forEach(v.nonNumbers, function (nonNumber) {
4955 st['throws'](
4956 function () { ES.SetFunctionLength(HasNoLength, nonNumber); },
4957 TypeError,
4958 debug(nonNumber) + ' is not a Number'
4959 );
4960 });
4961
4962 forEach([-1, -42, -Infinity, Infinity].concat(v.nonIntegerNumbers), function (nonPositiveInteger) {
4963 st['throws'](
4964 function () { ES.SetFunctionLength(HasNoLength, nonPositiveInteger); },
4965 TypeError,
4966 debug(nonPositiveInteger) + ' is not a positive integer Number'
4967 );
4968 });
4969
4970 st.end();
4971 });
4972
4973 // defines an own configurable non-enum non-write length property
4974
4975 t.end();
4976 });
4977
4978 test('thisSymbolValue', function (t) {
4979 forEach(v.nonSymbolPrimitives.concat(v.objects), function (nonSymbol) {
4980 t['throws'](
4981 function () { ES.thisSymbolValue(nonSymbol); },
4982 v.hasSymbols ? TypeError : SyntaxError,
4983 debug(nonSymbol) + ' is not a Symbol'
4984 );
4985 });
4986
4987 t.test('no native Symbols', { skip: v.hasSymbols }, function (st) {
4988 forEach(v.objects.concat(v.primitives), function (value) {
4989 st['throws'](
4990 function () { ES.thisSymbolValue(value); },
4991 SyntaxError,
4992 'Symbols are not supported'
4993 );
4994 });
4995 st.end();
4996 });
4997
4998 t.test('symbol values', { skip: !v.hasSymbols }, function (st) {
4999 forEach(v.symbols, function (symbol) {
5000 st.equal(ES.thisSymbolValue(symbol), symbol, 'Symbol value of ' + debug(symbol) + ' is same symbol');
5001
5002 st.equal(
5003 ES.thisSymbolValue(Object(symbol)),
5004 symbol,
5005 'Symbol value of ' + debug(Object(symbol)) + ' is ' + debug(symbol)
5006 );
5007 });
5008
5009 st.end();
5010 });
5011
5012 t.end();
5013 });
5014
5015 test('TimeString', function (t) {
5016 forEach(v.nonNumbers.concat(NaN), function (nonNumberOrNaN) {
5017 t['throws'](
5018 function () { ES.TimeString(nonNumberOrNaN); },
5019 TypeError,
5020 debug(nonNumberOrNaN) + ' is not a non-NaN Number'
5021 );
5022 });
5023
5024 var tv = Date.UTC(2019, 8, 10, 7, 8, 9);
5025 t.equal(ES.TimeString(tv), '07:08:09 GMT');
5026 t.end();
5027 });
5028
5029 test('UnicodeEscape', function (t) {
5030 forEach(v.nonStrings, function (nonString) {
5031 t['throws'](
5032 function () { ES.UnicodeEscape(nonString); },
5033 TypeError,
5034 debug(nonString) + ' is not a String'
5035 );
5036 });
5037 t['throws'](
5038 function () { ES.UnicodeEscape(''); },
5039 TypeError,
5040 'empty string does not have length 1'
5041 );
5042 t['throws'](
5043 function () { ES.UnicodeEscape('ab'); },
5044 TypeError,
5045 '2-char string does not have length 1'
5046 );
5047
5048 t.equal(ES.UnicodeEscape(' '), '\\u0020');
5049 t.equal(ES.UnicodeEscape('a'), '\\u0061');
5050 t.equal(ES.UnicodeEscape(leadingPoo), '\\ud83d');
5051 t.equal(ES.UnicodeEscape(trailingPoo), '\\udca9');
5052
5053 t.end();
5054 });
5055};
5056
5057var es2019 = function ES2019(ES, ops, expectedMissing, skips) {
5058 es2018(ES, ops, expectedMissing, assign({}, skips, {
5059 }));
5060 var test = makeTest(skips);
5061
5062 test('AddEntriesFromIterable', function (t) {
5063 t['throws'](
5064 function () { ES.AddEntriesFromIterable({}, undefined, function () {}); },
5065 TypeError,
5066 'iterable must not be undefined'
5067 );
5068 t['throws'](
5069 function () { ES.AddEntriesFromIterable({}, null, function () {}); },
5070 TypeError,
5071 'iterable must not be null'
5072 );
5073 forEach(v.nonFunctions, function (nonFunction) {
5074 t['throws'](
5075 function () { ES.AddEntriesFromIterable({}, {}, nonFunction); },
5076 TypeError,
5077 debug(nonFunction) + ' is not a function'
5078 );
5079 });
5080
5081 t.test('Symbol support', { skip: !v.hasSymbols }, function (st) {
5082 st.plan(4);
5083
5084 var O = {};
5085 st.equal(ES.AddEntriesFromIterable(O, [], function () {}), O, 'returns the target');
5086
5087 var adder = function (key, value) {
5088 st.equal(this, O, 'adder gets proper receiver');
5089 st.equal(key, 0, 'k is key');
5090 st.equal(value, 'a', 'v is value');
5091 };
5092 ES.AddEntriesFromIterable(O, ['a'].entries(), adder);
5093
5094 st.end();
5095 });
5096
5097 t.end();
5098 });
5099
5100 test('FlattenIntoArray', function (t) {
5101 t.test('no mapper function', function (st) {
5102 var testDepth = function testDepth(tt, depth, expected) {
5103 var a = [];
5104 var o = [[1], 2, , [[3]], [], 4, [[[[5]]]]]; // eslint-disable-line no-sparse-arrays
5105 ES.FlattenIntoArray(a, o, o.length, 0, depth);
5106 tt.deepEqual(a, expected, 'depth: ' + depth);
5107 };
5108
5109 testDepth(st, 1, [1, 2, [3], 4, [[[5]]]]);
5110 testDepth(st, 2, [1, 2, 3, 4, [[5]]]);
5111 testDepth(st, 3, [1, 2, 3, 4, [5]]);
5112 testDepth(st, 4, [1, 2, 3, 4, 5]);
5113 testDepth(st, Infinity, [1, 2, 3, 4, 5]);
5114 st.end();
5115 });
5116
5117 t.test('mapper function', function (st) {
5118 var testMapper = function testMapper(tt, mapper, expected, thisArg) {
5119 var a = [];
5120 var o = [[1], 2, , [[3]], [], 4, [[[[5]]]]]; // eslint-disable-line no-sparse-arrays
5121 ES.FlattenIntoArray(a, o, o.length, 0, 1, mapper, thisArg);
5122 tt.deepEqual(a, expected);
5123 };
5124
5125 var double = function double(x) {
5126 return typeof x === 'number' ? 2 * x : x;
5127 };
5128 testMapper(
5129 st,
5130 double,
5131 [1, 4, [3], 8, [[[5]]]]
5132 );
5133 var receiver = hasStrictMode ? 42 : Object(42);
5134 testMapper(
5135 st,
5136 function (x) { return [this, double(x)]; },
5137 [receiver, [1], receiver, 4, receiver, [[3]], receiver, [], receiver, 8, receiver, [[[[5]]]]],
5138 42
5139 );
5140 st.end();
5141 });
5142
5143 t.end();
5144 });
5145
5146 test('TrimString', function (t) {
5147 t.test('non-object string', function (st) {
5148 forEach(v.nullPrimitives, function (nullish) {
5149 st['throws'](
5150 function () { ES.TrimString(nullish); },
5151 debug(nullish) + ' is not an Object'
5152 );
5153 });
5154 st.end();
5155 });
5156
5157 var string = ' \n abc \n ';
5158 t.equal(ES.TrimString(string, 'start'), string.slice(string.indexOf('a')));
5159 t.equal(ES.TrimString(string, 'end'), string.slice(0, string.lastIndexOf('c') + 1));
5160 t.equal(ES.TrimString(string, 'start+end'), string.slice(string.indexOf('a'), string.lastIndexOf('c') + 1));
5161
5162 t.end();
5163 });
5164};
5165
5166var es2020 = function ES2020(ES, ops, expectedMissing, skips) {
5167 es2019(ES, ops, expectedMissing, assign({}, skips, {
5168 CopyDataProperties: true,
5169 GetIterator: true,
5170 NumberToString: true,
5171 ObjectCreate: true,
5172 SameValueNonNumber: true,
5173 ToInteger: true,
5174 UTF16Decode: true
5175 }));
5176 var test = makeTest(skips);
5177
5178 test('BigInt::add', { skip: !hasBigInts }, function (t) {
5179 forEach(v.nonBigInts, function (nonBigInt) {
5180 t['throws'](
5181 function () { ES.BigInt.add(nonBigInt, 0); },
5182 TypeError,
5183 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5184 );
5185 t['throws'](
5186 function () { ES.BigInt.add(0, nonBigInt); },
5187 TypeError,
5188 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5189 );
5190 });
5191
5192 t.equal(ES.BigInt.add($BigInt(0), $BigInt(0)), $BigInt(0), '0n + 0n is 0n');
5193
5194 forEach(v.bigints, function (bigint) {
5195 if (bigint !== $BigInt(0)) {
5196 t.equal(ES.BigInt.add(bigint, $BigInt(0)), bigint, debug(bigint) + ' + 0n adds to ' + bigint);
5197 }
5198 t.equal(ES.BigInt.add(bigint, $BigInt(1)), bigint + $BigInt(1), debug(bigint) + ' + 1n adds to ' + (bigint + $BigInt(1)));
5199 t.equal(ES.BigInt.add(bigint, -$BigInt(42)), bigint - $BigInt(42), debug(bigint) + ' + -42n adds to ' + (bigint - $BigInt(42)));
5200 });
5201
5202 t.end();
5203 });
5204
5205 test('BigInt::bitwiseAND', { skip: !hasBigInts }, function (t) {
5206 forEach(v.nonBigInts, function (nonBigInt) {
5207 t['throws'](
5208 function () { ES.BigInt.bitwiseAND(nonBigInt, $BigInt(0)); },
5209 TypeError,
5210 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5211 );
5212 t['throws'](
5213 function () { ES.BigInt.bitwiseAND($BigInt(0), nonBigInt); },
5214 TypeError,
5215 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5216 );
5217 });
5218
5219 t.equal(ES.BigInt.bitwiseAND($BigInt(1), $BigInt(2)), $BigInt(1) & $BigInt(2));
5220
5221 t.end();
5222 });
5223
5224 test('BigInt::bitwiseNOT', function (t) {
5225 forEach(v.nonBigInts, function (nonBigInt) {
5226 t['throws'](
5227 function () { ES.BigInt.bitwiseNOT(nonBigInt); },
5228 TypeError,
5229 debug(nonBigInt) + ' is not a BigInt'
5230 );
5231 });
5232
5233 t.test('actual BigInts', { skip: !hasBigInts }, function (st) {
5234 forEach(v.int32s, function (int32) {
5235 var bigInt32 = $BigInt(int32);
5236 st.equal(ES.BigInt.bitwiseNOT(bigInt32), ~bigInt32, debug(bigInt32) + ' becomes ~' + debug(bigInt32));
5237 });
5238 st.end();
5239 });
5240
5241 t.end();
5242 });
5243
5244 test('BigInt::bitwiseOR', { skip: !hasBigInts }, function (t) {
5245 forEach(v.nonBigInts, function (nonBigInt) {
5246 t['throws'](
5247 function () { ES.BigInt.bitwiseOR(nonBigInt, $BigInt(0)); },
5248 TypeError,
5249 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5250 );
5251 t['throws'](
5252 function () { ES.BigInt.bitwiseOR($BigInt(0), nonBigInt); },
5253 TypeError,
5254 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5255 );
5256 });
5257
5258 t.equal(ES.BigInt.bitwiseOR($BigInt(1), $BigInt(2)), $BigInt(1) | $BigInt(2));
5259
5260 t.end();
5261 });
5262
5263 test('BigInt::bitwiseXOR', { skip: !hasBigInts }, function (t) {
5264 forEach(v.nonBigInts, function (nonBigInt) {
5265 t['throws'](
5266 function () { ES.BigInt.bitwiseXOR(nonBigInt, $BigInt(0)); },
5267 TypeError,
5268 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5269 );
5270 t['throws'](
5271 function () { ES.BigInt.bitwiseXOR($BigInt(0), nonBigInt); },
5272 TypeError,
5273 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5274 );
5275 });
5276
5277 t.equal(ES.BigInt.bitwiseXOR($BigInt(1), $BigInt(2)), $BigInt(1) ^ $BigInt(2));
5278
5279 t.end();
5280 });
5281
5282 test('BigInt::divide', { skip: !hasBigInts }, function (t) {
5283 forEach(v.nonBigInts, function (nonBigInt) {
5284 t['throws'](
5285 function () { ES.BigInt.divide(nonBigInt, $BigInt(0)); },
5286 TypeError,
5287 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5288 );
5289 t['throws'](
5290 function () { ES.BigInt.divide($BigInt(0), nonBigInt); },
5291 TypeError,
5292 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5293 );
5294 });
5295
5296 t['throws'](
5297 function () { ES.BigInt.divide($BigInt(1), $BigInt(0)); },
5298 RangeError,
5299 'dividing by zero throws'
5300 );
5301
5302 forEach(v.bigints, function (bigint) {
5303 if (bigint !== $BigInt(0)) {
5304 t.equal(ES.BigInt.divide(bigint, bigint), $BigInt(1), debug(bigint) + ' divided by itself is 1n');
5305 t.equal(ES.BigInt.divide(bigint, $BigInt(2)), bigint / $BigInt(2), debug(bigint) + ' divided by 2n is half itself');
5306 }
5307 });
5308
5309 t.end();
5310 });
5311
5312 test('BigInt::equal', { skip: !hasBigInts }, function (t) {
5313 forEach(v.nonBigInts, function (nonBigInt) {
5314 t['throws'](
5315 function () { ES.BigInt.equal(nonBigInt, $BigInt(0)); },
5316 TypeError,
5317 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5318 );
5319 t['throws'](
5320 function () { ES.Number.equal($BigInt(0), nonBigInt); },
5321 TypeError,
5322 'y: ' + debug(nonBigInt) + ' is not a Number'
5323 );
5324 });
5325
5326 forEach(v.bigints, function (bigint) {
5327 if (BigInt !== $BigInt(0)) {
5328 t.equal(ES.BigInt.equal(bigint, bigint), true, debug(bigint) + ' is equal to itself');
5329 t.equal(ES.BigInt.equal(bigint, bigint + $BigInt(1)), false, debug(bigint) + ' is not equal to itself plus 1n');
5330 }
5331 });
5332
5333 t.end();
5334 });
5335
5336 test('BigInt::exponentiate', { skip: !hasBigInts }, function (t) {
5337 forEach(v.nonBigInts, function (nonBigInt) {
5338 t['throws'](
5339 function () { ES.BigInt.exponentiate(nonBigInt, $BigInt(0)); },
5340 TypeError,
5341 'base: ' + debug(nonBigInt) + ' is not a BigInt'
5342 );
5343 t['throws'](
5344 function () { ES.BigInt.exponentiate($BigInt(0), nonBigInt); },
5345 TypeError,
5346 'exponent: ' + debug(nonBigInt) + ' is not a BigInt'
5347 );
5348 });
5349
5350 t['throws'](
5351 function () { ES.BigInt.exponentiate($BigInt(1), -$BigInt(1)); },
5352 RangeError,
5353 'negative exponent throws'
5354 );
5355
5356 forEach(v.bigints, function (bigint) {
5357 if (bigint !== $BigInt(0)) {
5358 t.equal(ES.BigInt.exponentiate(bigint, $BigInt(0)), $BigInt(1), debug(bigint) + ' ** 0n is 1n');
5359
5360 var square = bigint;
5361 for (var i = 0; i < Number(bigint); i += 1) {
5362 square += bigint;
5363 }
5364 t.equal(ES.BigInt.exponentiate(bigint, bigint), square, debug(bigint) + ' ** ' + debug(bigint) + ' is equal to ' + debug(square));
5365 }
5366 });
5367
5368 t.end();
5369 });
5370
5371 test('BigInt::leftShift', { skip: !hasBigInts }, function (t) {
5372 forEach(v.nonBigInts, function (nonBigInt) {
5373 t['throws'](
5374 function () { ES.BigInt.leftShift(nonBigInt, $BigInt(0)); },
5375 TypeError,
5376 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5377 );
5378 t['throws'](
5379 function () { ES.BigInt.leftShift($BigInt(0), nonBigInt); },
5380 TypeError,
5381 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5382 );
5383 });
5384
5385 forEach([0].concat(v.int32s), function (int32) {
5386 var bigInt32 = $BigInt(int32);
5387 forEach([1, 3, 5, 31, 32, 33], function (bits) {
5388 var bitsN = $BigInt(bits);
5389 t.equal(
5390 ES.BigInt.leftShift(bigInt32, bitsN),
5391 bigInt32 << bitsN,
5392 debug(bigInt32) + ' << ' + debug(bitsN) + ' is ' + debug(bigInt32 << bitsN)
5393 );
5394 });
5395 });
5396
5397 t.end();
5398 });
5399
5400 test('BigInt::lessThan', { skip: !hasBigInts }, function (t) {
5401 forEach(v.nonBigInts, function (nonBigInt) {
5402 t['throws'](
5403 function () { ES.BigInt.lessThan(nonBigInt, $BigInt(0)); },
5404 TypeError,
5405 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5406 );
5407 t['throws'](
5408 function () { ES.BigInt.lessThan($BigInt(0), nonBigInt); },
5409 TypeError,
5410 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5411 );
5412 });
5413
5414 t.equal(ES.BigInt.lessThan($BigInt(0), $BigInt(0)), false, '0n < 0n is false');
5415
5416 forEach(v.bigints, function (bigint) {
5417 t.equal(ES.BigInt.lessThan(bigint, bigint), false, debug(bigint) + ' is not less than itself');
5418
5419 t.equal(ES.BigInt.lessThan(bigint, bigint + $BigInt(1)), true, debug(bigint) + ' < ' + debug(bigint + $BigInt(1)) + ' is true');
5420 t.equal(ES.BigInt.lessThan(bigint + $BigInt(1), bigint), false, debug(bigint + $BigInt(1)) + ' < ' + debug(bigint) + ' is false');
5421 });
5422
5423 t.end();
5424 });
5425
5426 test('BigInt::multiply', { skip: !hasBigInts }, function (t) {
5427 forEach(v.nonBigInts, function (nonBigInt) {
5428 t['throws'](
5429 function () { ES.BigInt.multiply(nonBigInt, $BigInt(0)); },
5430 TypeError,
5431 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5432 );
5433 t['throws'](
5434 function () { ES.BigInt.multiply($BigInt(0), nonBigInt); },
5435 TypeError,
5436 'y: ' + debug(nonBigInt) + ' is not a Number'
5437 );
5438 });
5439
5440 t.equal(ES.BigInt.multiply($BigInt(0), $BigInt(0)), $BigInt(0), '0n * 0n is 0n');
5441
5442 forEach(v.bigints, function (bigint) {
5443 if (bigint !== $BigInt(0)) {
5444 t.equal(ES.BigInt.multiply(bigint, $BigInt(0)), $BigInt(0), debug(bigint) + ' * 0n produces 0n');
5445 t.equal(ES.BigInt.multiply(bigint, $BigInt(1)), bigint, debug(bigint) + ' * 1n produces itself');
5446 t.equal(ES.BigInt.multiply(bigint, -$BigInt(42)), bigint * -$BigInt(42), debug(bigint) + ' * -42n produces ' + (bigint - $BigInt(42)));
5447 }
5448 });
5449
5450 t.end();
5451 });
5452
5453 test('BigInt::remainder', { skip: !hasBigInts }, function (t) {
5454 forEach(v.nonBigInts, function (nonBigInt) {
5455 t['throws'](
5456 function () { ES.BigInt.remainder(nonBigInt, $BigInt(0)); },
5457 TypeError,
5458 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5459 );
5460 t['throws'](
5461 function () { ES.BigInt.remainder($BigInt(0), nonBigInt); },
5462 TypeError,
5463 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5464 );
5465 });
5466
5467 t['throws'](
5468 function () { ES.BigInt.remainder($BigInt(1), $BigInt(0)); },
5469 RangeError,
5470 'dividing by zero throws'
5471 );
5472
5473 forEach(v.bigints, function (bigint) {
5474 if (bigint !== $BigInt(0)) {
5475 t.equal(
5476 ES.BigInt.remainder($BigInt(0), bigint),
5477 $BigInt(0),
5478 '0n % ' + debug(bigint) + ' is 0n'
5479 );
5480 t.equal(
5481 ES.BigInt.remainder(bigint + $BigInt(1), bigint),
5482 $BigInt(1),
5483 debug(bigint) + ' % ' + debug(bigint + $BigInt(1)) + ' is 1n'
5484 );
5485 }
5486 });
5487
5488 t.end();
5489 });
5490
5491 test('BigInt::sameValue', { skip: !hasBigInts }, function (t) {
5492 forEach(v.nonBigInts, function (nonBigInt) {
5493 t['throws'](
5494 function () { ES.BigInt.sameValue(nonBigInt, $BigInt(0)); },
5495 TypeError,
5496 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5497 );
5498 t['throws'](
5499 function () { ES.BigInt.sameValue($BigInt(0), nonBigInt); },
5500 TypeError,
5501 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5502 );
5503 });
5504
5505 t.equal(ES.BigInt.sameValue($BigInt(0), $BigInt(0)), true, '0n is sameValue as 0n');
5506
5507 forEach(v.bigints, function (bigint) {
5508 t.ok(ES.BigInt.sameValue(bigint, bigint), debug(bigint) + ' is the sameValue as itself');
5509 });
5510
5511 t.end();
5512 });
5513
5514 test('BigInt::sameValueZero', { skip: !hasBigInts }, function (t) {
5515 forEach(v.nonBigInts, function (nonBigInt) {
5516 t['throws'](
5517 function () { ES.BigInt.sameValueZero(nonBigInt, $BigInt(0)); },
5518 TypeError,
5519 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5520 );
5521 t['throws'](
5522 function () { ES.BigInt.sameValueZero($BigInt(0), nonBigInt); },
5523 TypeError,
5524 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5525 );
5526 });
5527
5528 forEach(v.bigints, function (bigint) {
5529 t.ok(ES.BigInt.sameValueZero(bigint, bigint), debug(bigint) + ' is the sameValueZero as itself');
5530 });
5531
5532 t.end();
5533 });
5534
5535 test('BigInt::signedRightShift', { skip: !hasBigInts }, function (t) {
5536 forEach(v.nonBigInts, function (nonBigInt) {
5537 t['throws'](
5538 function () { ES.BigInt.signedRightShift(nonBigInt, $BigInt(0)); },
5539 TypeError,
5540 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5541 );
5542 t['throws'](
5543 function () { ES.BigInt.signedRightShift($BigInt(0), nonBigInt); },
5544 TypeError,
5545 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5546 );
5547 });
5548
5549 forEach([0].concat(v.int32s), function (int32) {
5550 var bigInt32 = $BigInt(int32);
5551 forEach([1, 3, 5, 31, 32, 33], function (bits) {
5552 var bitsN = $BigInt(bits);
5553 t.equal(
5554 ES.BigInt.signedRightShift(bigInt32, bitsN),
5555 bigInt32 >> bitsN,
5556 debug(bigInt32) + ' >> ' + debug(bitsN) + ' is ' + debug(bigInt32 >> bitsN)
5557 );
5558 });
5559 });
5560
5561 t.end();
5562 });
5563
5564 test('BigInt::subtract', { skip: !hasBigInts }, function (t) {
5565 forEach(v.nonBigInts, function (nonBigInt) {
5566 t['throws'](
5567 function () { ES.BigInt.subtract(nonBigInt, $BigInt(0)); },
5568 TypeError,
5569 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5570 );
5571 t['throws'](
5572 function () { ES.BigInt.subtract($BigInt(0), nonBigInt); },
5573 TypeError,
5574 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5575 );
5576 });
5577
5578 t.equal(ES.BigInt.subtract($BigInt(0), $BigInt(0)), $BigInt(0), '0n - 0n is 0n');
5579
5580 forEach(v.bigints, function (bigint) {
5581 t.equal(ES.BigInt.subtract(bigint, $BigInt(0)), bigint, debug(bigint) + ' - 0n produces ' + bigint);
5582 t.equal(ES.BigInt.subtract(bigint, $BigInt(1)), bigint - $BigInt(1), debug(bigint) + ' - 1n produces ' + (bigint + $BigInt(1)));
5583 t.equal(ES.BigInt.subtract(bigint, $BigInt(42)), bigint - $BigInt(42), debug(bigint) + ' - 42n produces ' + (bigint - $BigInt(42)));
5584 });
5585
5586 t.end();
5587 });
5588
5589 test('BigInt::toString', function (t) {
5590 forEach(v.nonBigInts, function (nonBigInt) {
5591 t['throws'](
5592 function () { ES.BigInt.toString(nonBigInt); },
5593 TypeError,
5594 debug(nonBigInt) + ' is not a BigInt'
5595 );
5596 });
5597
5598 forEach(v.bigints, function (bigint) {
5599 t.equal(ES.BigInt.toString(bigint), String(bigint), debug(bigint) + ' stringifies to ' + bigint);
5600 });
5601
5602 t.end();
5603 });
5604
5605 test('BigInt::unaryMinus', function (t) {
5606 forEach(v.nonBigInts, function (nonBigInt) {
5607 t['throws'](
5608 function () { ES.BigInt.unaryMinus(nonBigInt); },
5609 TypeError,
5610 debug(nonBigInt) + ' is not a BigInt'
5611 );
5612 });
5613
5614 t.test('actual BigInts', { skip: !hasBigInts }, function (st) {
5615 forEach(v.bigints, function (bigint) {
5616 st.equal(ES.BigInt.unaryMinus(bigint), -bigint, debug(bigint) + ' produces -' + debug(bigint));
5617 });
5618 st.end();
5619 });
5620
5621 t.end();
5622 });
5623
5624 test('BigInt::unsignedRightShift', { skip: !hasBigInts }, function (t) {
5625 forEach(v.nonBigInts, function (nonBigInt) {
5626 t['throws'](
5627 function () { ES.BigInt.unsignedRightShift(nonBigInt, $BigInt(0)); },
5628 TypeError,
5629 'x: ' + debug(nonBigInt) + ' is not a BigInt'
5630 );
5631 t['throws'](
5632 function () { ES.BigInt.unsignedRightShift($BigInt(0), nonBigInt); },
5633 TypeError,
5634 'y: ' + debug(nonBigInt) + ' is not a BigInt'
5635 );
5636 });
5637
5638 forEach([0].concat(v.int32s), function (int32) {
5639 var bigInt32 = $BigInt(int32);
5640 forEach([1, 3, 5, 31, 32, 33], function (bits) {
5641 var bitsN = $BigInt(bits);
5642 t['throws'](
5643 function () { ES.BigInt.unsignedRightShift(bigInt32, bitsN); },
5644 TypeError,
5645 debug(bigInt32) + ' >>> ' + debug(bitsN) + ' throws'
5646 );
5647 });
5648 });
5649
5650 t.end();
5651 });
5652
5653 test('BigIntBitwiseOp', { skip: !hasBigInts }, function (t) {
5654 t['throws'](
5655 function () { ES.BigIntBitwiseOp('invalid', BigInt(0), BigInt(0)); },
5656 TypeError,
5657 'throws with an invalid op'
5658 );
5659
5660 t.equal(ES.BigIntBitwiseOp('&', BigInt(1), BigInt(2)), BigInt(1) & BigInt(2));
5661 t.equal(ES.BigIntBitwiseOp('|', BigInt(1), BigInt(2)), BigInt(1) | BigInt(2));
5662 t.equal(ES.BigIntBitwiseOp('^', BigInt(1), BigInt(2)), BigInt(1) ^ BigInt(2));
5663
5664 t.end();
5665 });
5666
5667 test('BinaryAnd', function (t) {
5668 t.equal(ES.BinaryAnd(0, 0), 0);
5669 t.equal(ES.BinaryAnd(0, 1), 0);
5670 t.equal(ES.BinaryAnd(1, 0), 0);
5671 t.equal(ES.BinaryAnd(1, 1), 1);
5672
5673 forEach(v.nonIntegerNumbers.concat(v.nonNumberPrimitives, v.objects), function (nonBit) {
5674 t['throws'](
5675 function () { ES.BinaryAnd(0, nonBit); },
5676 TypeError
5677 );
5678 t['throws'](
5679 function () { ES.BinaryAnd(nonBit, 1); },
5680 TypeError
5681 );
5682 });
5683 t.end();
5684 });
5685
5686 test('BinaryOr', function (t) {
5687 t.equal(ES.BinaryOr(0, 0), 0);
5688 t.equal(ES.BinaryOr(0, 1), 1);
5689 t.equal(ES.BinaryOr(1, 0), 1);
5690 t.equal(ES.BinaryOr(1, 1), 1);
5691
5692 forEach(v.nonIntegerNumbers.concat(v.nonNumberPrimitives, v.objects), function (nonBit) {
5693 t['throws'](
5694 function () { ES.BinaryOr(0, nonBit); },
5695 TypeError
5696 );
5697 t['throws'](
5698 function () { ES.BinaryOr(nonBit, 1); },
5699 TypeError
5700 );
5701 });
5702 t.end();
5703 });
5704
5705 test('BinaryXor', function (t) {
5706 t.equal(ES.BinaryXor(0, 0), 0);
5707 t.equal(ES.BinaryXor(0, 1), 1);
5708 t.equal(ES.BinaryXor(1, 0), 1);
5709 t.equal(ES.BinaryXor(1, 1), 0);
5710
5711 forEach(v.nonIntegerNumbers.concat(v.nonNumberPrimitives, v.objects), function (nonBit) {
5712 t['throws'](
5713 function () { ES.BinaryXor(0, nonBit); },
5714 TypeError
5715 );
5716 t['throws'](
5717 function () { ES.BinaryXor(nonBit, 1); },
5718 TypeError
5719 );
5720 });
5721 t.end();
5722 });
5723
5724 test('CodePointAt', function (t) {
5725 t['throws'](
5726 function () { ES.CodePointAt('abc', -1); },
5727 TypeError,
5728 'requires an index >= 0'
5729 );
5730 t['throws'](
5731 function () { ES.CodePointAt('abc', 3); },
5732 TypeError,
5733 'requires an index < string length'
5734 );
5735
5736 t.deepEqual(ES.CodePointAt('abc', 0), {
5737 '[[CodePoint]]': 'a',
5738 '[[CodeUnitCount]]': 1,
5739 '[[IsUnpairedSurrogate]]': false
5740 });
5741 t.deepEqual(ES.CodePointAt('abc', 1), {
5742 '[[CodePoint]]': 'b',
5743 '[[CodeUnitCount]]': 1,
5744 '[[IsUnpairedSurrogate]]': false
5745 });
5746 t.deepEqual(ES.CodePointAt('abc', 2), {
5747 '[[CodePoint]]': 'c',
5748 '[[CodeUnitCount]]': 1,
5749 '[[IsUnpairedSurrogate]]': false
5750 });
5751
5752 var strWithHalfPoo = 'a' + leadingPoo + 'c';
5753 var strWithWholePoo = 'a' + wholePoo + 'd';
5754
5755 t.deepEqual(ES.CodePointAt(strWithHalfPoo, 0), {
5756 '[[CodePoint]]': 'a',
5757 '[[CodeUnitCount]]': 1,
5758 '[[IsUnpairedSurrogate]]': false
5759 });
5760 t.deepEqual(ES.CodePointAt(strWithHalfPoo, 1), {
5761 '[[CodePoint]]': leadingPoo,
5762 '[[CodeUnitCount]]': 1,
5763 '[[IsUnpairedSurrogate]]': true
5764 });
5765 t.deepEqual(ES.CodePointAt(strWithHalfPoo, 2), {
5766 '[[CodePoint]]': 'c',
5767 '[[CodeUnitCount]]': 1,
5768 '[[IsUnpairedSurrogate]]': false
5769 });
5770
5771 t.deepEqual(ES.CodePointAt(strWithWholePoo, 0), {
5772 '[[CodePoint]]': 'a',
5773 '[[CodeUnitCount]]': 1,
5774 '[[IsUnpairedSurrogate]]': false
5775 });
5776 t.deepEqual(ES.CodePointAt(strWithWholePoo, 1), {
5777 '[[CodePoint]]': wholePoo,
5778 '[[CodeUnitCount]]': 2,
5779 '[[IsUnpairedSurrogate]]': false
5780 });
5781 t.deepEqual(ES.CodePointAt(strWithWholePoo, 2), {
5782 '[[CodePoint]]': trailingPoo,
5783 '[[CodeUnitCount]]': 1,
5784 '[[IsUnpairedSurrogate]]': true
5785 });
5786 t.deepEqual(ES.CodePointAt(strWithWholePoo, 3), {
5787 '[[CodePoint]]': 'd',
5788 '[[CodeUnitCount]]': 1,
5789 '[[IsUnpairedSurrogate]]': false
5790 });
5791
5792 t.end();
5793 });
5794
5795 test('CopyDataProperties', function (t) {
5796 t.test('first argument: target', function (st) {
5797 forEach(v.primitives, function (primitive) {
5798 st['throws'](
5799 function () { ES.CopyDataProperties(primitive, {}, []); },
5800 TypeError,
5801 debug(primitive) + ' is not an Object'
5802 );
5803 });
5804 st.end();
5805 });
5806
5807 t.test('second argument: source', function (st) {
5808 var frozenTarget = Object.freeze ? Object.freeze({}) : {};
5809 forEach(v.nullPrimitives, function (nullish) {
5810 st.equal(
5811 ES.CopyDataProperties(frozenTarget, nullish, []),
5812 frozenTarget,
5813 debug(nullish) + ' "source" yields identical, unmodified target'
5814 );
5815 });
5816
5817 forEach(v.nonNullPrimitives, function (objectCoercible) {
5818 var target = {};
5819 var result = ES.CopyDataProperties(target, objectCoercible, []);
5820 st.equal(result, target, 'result === target');
5821 st.deepEqual(keys(result), keys(Object(objectCoercible)), 'target ends up with keys of ' + debug(objectCoercible));
5822 });
5823
5824 st.test('enumerable accessor property', { skip: !defineProperty.oDP }, function (s2t) {
5825 var target = {};
5826 var source = {};
5827 defineProperty(source, 'a', {
5828 enumerable: true,
5829 get: function () { return 42; }
5830 });
5831 var result = ES.CopyDataProperties(target, source, []);
5832 s2t.equal(result, target, 'result === target');
5833 s2t.deepEqual(result, { a: 42 }, 'target ends up with enumerable accessor of source');
5834 s2t.end();
5835 });
5836
5837 st.end();
5838 });
5839
5840 t.test('third argument: excludedItems', function (st) {
5841 forEach(v.objects.concat(v.primitives), function (nonArray) {
5842 st['throws'](
5843 function () { ES.CopyDataProperties({}, {}, nonArray); },
5844 TypeError,
5845 debug(nonArray) + ' is not an Array'
5846 );
5847 });
5848
5849 forEach(v.nonPropertyKeys, function (nonPropertyKey) {
5850 st['throws'](
5851 function () { ES.CopyDataProperties({}, {}, [nonPropertyKey]); },
5852 TypeError,
5853 debug(nonPropertyKey) + ' is not a Property Key'
5854 );
5855 });
5856
5857 var result = ES.CopyDataProperties({}, { a: 1, b: 2, c: 3 }, ['b']);
5858 st.deepEqual(keys(result).sort(), ['a', 'c'].sort(), 'excluded string keys are excluded');
5859
5860 st.test('excluding symbols', { skip: !v.hasSymbols }, function (s2t) {
5861 var source = {};
5862 forEach(v.symbols, function (symbol) {
5863 source[symbol] = true;
5864 });
5865
5866 var includedSymbols = v.symbols.slice(1);
5867 var excludedSymbols = v.symbols.slice(0, 1);
5868 var target = ES.CopyDataProperties({}, source, excludedSymbols);
5869
5870 forEach(includedSymbols, function (symbol) {
5871 s2t.equal(has(target, symbol), true, debug(symbol) + ' is included');
5872 });
5873
5874 forEach(excludedSymbols, function (symbol) {
5875 s2t.equal(has(target, symbol), false, debug(symbol) + ' is excluded');
5876 });
5877
5878 s2t.end();
5879 });
5880
5881 st.end();
5882 });
5883
5884 // TODO: CopyDataProperties throws when copying fails
5885
5886 t.end();
5887 });
5888
5889 test('GetIterator', function (t) {
5890 try {
5891 ES.GetIterator({}, null);
5892 } catch (e) {
5893 t.ok(e.message.indexOf('Assertion failed: `hint` must be one of \'sync\' or \'async\'' >= 0));
5894 }
5895
5896 var arr = [1, 2];
5897 testIterator(t, ES.GetIterator(arr), arr);
5898
5899 testIterator(t, ES.GetIterator('abc'), 'abc'.split(''));
5900
5901 t.test('Symbol.iterator', { skip: !v.hasSymbols }, function (st) {
5902 var m = new Map();
5903 m.set(1, 'a');
5904 m.set(2, 'b');
5905
5906 testIterator(st, ES.GetIterator(m), [[1, 'a'], [2, 'b']]);
5907
5908 st.end();
5909 });
5910
5911 t.test('Symbol.asyncIterator', { skip: !v.hasSymbols || !Symbol.asyncIterator }, function (st) {
5912 try {
5913 ES.GetIterator(arr, 'async');
5914 } catch (e) {
5915 st.ok(e.message.indexOf("async from sync iterators aren't currently supported") >= 0);
5916 }
5917
5918 var it = {
5919 next: function () {
5920 return Promise.resolve({
5921 done: true
5922 });
5923 }
5924 };
5925 var obj = {};
5926 obj[Symbol.asyncIterator] = function () {
5927 return it;
5928 };
5929
5930 st.equal(ES.GetIterator(obj, 'async'), it);
5931
5932 st.end();
5933 });
5934
5935 t.end();
5936 });
5937
5938 var unclampedUnsignedIntegerTypes = [
5939 'Int8',
5940 'Int16',
5941 'Int32'
5942 ];
5943 var clampedTypes = [
5944 'Uint8C'
5945 ];
5946 var unclampedSignedIntegerTypes = [
5947 'Uint8',
5948 'Uint16',
5949 'Uint32'
5950 ];
5951 var unclampedIntegerTypes = unclampedUnsignedIntegerTypes.concat(unclampedSignedIntegerTypes);
5952 var floatTypes = [
5953 'Float32',
5954 'Float64'
5955 ];
5956 var integerTypes = unclampedIntegerTypes.concat(clampedTypes, floatTypes);
5957 var bigIntTypes = [
5958 'BigInt64',
5959 'BigUint64'
5960 ];
5961 var numberTypes = floatTypes.concat(integerTypes);
5962 var nonIntegerTypes = floatTypes.concat(bigIntTypes);
5963 var unsignedElementTypes = unclampedSignedIntegerTypes.concat([
5964 'BigUint64'
5965 ]);
5966 var signedElementTypes = unclampedUnsignedIntegerTypes;
5967
5968 test('IsBigIntElementType', function (t) {
5969 forEach(bigIntTypes, function (type) {
5970 t.equal(
5971 ES.IsBigIntElementType(type),
5972 true,
5973 debug(type) + ' is a BigInt element type'
5974 );
5975 });
5976
5977 forEach(numberTypes, function (type) {
5978 t.equal(
5979 ES.IsBigIntElementType(type),
5980 false,
5981 debug(type) + ' is not a BigInt element type'
5982 );
5983 });
5984
5985 t.end();
5986 });
5987
5988 test('IsUnsignedElementType', function (t) {
5989 forEach(unsignedElementTypes, function (type) {
5990 t.equal(
5991 ES.IsUnsignedElementType(type),
5992 true,
5993 debug(type) + ' is an unsigned element type'
5994 );
5995 });
5996
5997 forEach(signedElementTypes, function (type) {
5998 t.equal(
5999 ES.IsUnsignedElementType(type),
6000 false,
6001 debug(type) + ' is not an unsigned element type'
6002 );
6003 });
6004
6005 t.end();
6006 });
6007
6008 test('IsUnclampedIntegerElementType', function (t) {
6009 forEach(unclampedIntegerTypes, function (type) {
6010 t.equal(
6011 ES.IsUnclampedIntegerElementType(type),
6012 true,
6013 debug(type) + ' is an unclamped integer element type'
6014 );
6015 });
6016
6017 forEach(clampedTypes.concat(nonIntegerTypes), function (type) {
6018 t.equal(
6019 ES.IsUnclampedIntegerElementType(type),
6020 false,
6021 debug(type) + ' is not an unclamped integer element type'
6022 );
6023 });
6024
6025 t.end();
6026 });
6027
6028 test('IsNonNegativeInteger', function (t) {
6029 forEach(v.notNonNegativeIntegers, function (nonIntegerNumber) {
6030 t.equal(
6031 ES.IsNonNegativeInteger(nonIntegerNumber),
6032 false,
6033 debug(nonIntegerNumber) + ' is not a non-negative integer'
6034 );
6035 });
6036
6037 forEach(v.zeroes.concat(v.integerNumbers), function (nonNegativeInteger) {
6038 t.equal(
6039 ES.IsNonNegativeInteger(nonNegativeInteger),
6040 true,
6041 debug(nonNegativeInteger) + ' is a non-negative integer'
6042 );
6043 });
6044
6045 t.end();
6046 });
6047
6048 test('IsNoTearConfiguration', function (t) {
6049 forEach(unclampedIntegerTypes, function (type) {
6050 t.equal(
6051 ES.IsNoTearConfiguration(type),
6052 true,
6053 debug(type) + ' with any order is a no-tear configuration'
6054 );
6055 });
6056
6057 forEach(bigIntTypes, function (type) {
6058 t.equal(
6059 ES.IsNoTearConfiguration(type, 'Init'),
6060 false,
6061 debug(type) + ' with ' + debug('Init') + ' is not a no-tear configuration'
6062 );
6063
6064 t.equal(
6065 ES.IsNoTearConfiguration(type, 'Unordered'),
6066 false,
6067 debug(type) + ' with ' + debug('Unordered') + ' is not a no-tear configuration'
6068 );
6069
6070 t.equal(
6071 ES.IsNoTearConfiguration(type),
6072 true,
6073 debug(type) + ' with any other order is a no-tear configuration'
6074 );
6075 });
6076
6077 forEach(clampedTypes, function (type) {
6078 t.equal(
6079 ES.IsNoTearConfiguration(type),
6080 false,
6081 debug(type) + ' with any order is not a no-tear configuration'
6082 );
6083 });
6084
6085 t.end();
6086 });
6087
6088 test('LengthOfArrayLike', function (t) {
6089 forEach(v.primitives, function (primitive) {
6090 t['throws'](
6091 function () { ES.LengthOfArrayLike(primitive); },
6092 TypeError,
6093 debug(primitive) + ' is not an Object'
6094 );
6095 });
6096
6097 t.equal(ES.LengthOfArrayLike([]), 0);
6098 t.equal(ES.LengthOfArrayLike([1]), 1);
6099 t.equal(ES.LengthOfArrayLike({ length: 42 }), 42);
6100
6101 t.end();
6102 });
6103
6104 test('Number::add', function (t) {
6105 forEach(v.nonNumbers, function (nonNumber) {
6106 t['throws'](
6107 function () { ES.Number.add(nonNumber, 0); },
6108 TypeError,
6109 'x: ' + debug(nonNumber) + ' is not a Number'
6110 );
6111 t['throws'](
6112 function () { ES.Number.add(0, nonNumber); },
6113 TypeError,
6114 'y: ' + debug(nonNumber) + ' is not a Number'
6115 );
6116 });
6117
6118 t.equal(ES.Number.add(+Infinity, +Infinity), +Infinity, '+∞ + +∞ is +∞');
6119 t.equal(ES.Number.add(-Infinity, -Infinity), -Infinity, '-∞ + -∞ is -∞');
6120 t.equal(ES.Number.add(+Infinity, -Infinity), NaN, '+∞ + -∞ is NaN');
6121 t.equal(ES.Number.add(-Infinity, +Infinity), NaN, '-∞ + +∞ is NaN');
6122
6123 t.equal(ES.Number.add(+0, +0), +0, '0 + 0 is +0');
6124 t.equal(ES.Number.add(+0, -0), +0, '0 + -0 is +0');
6125 t.equal(ES.Number.add(-0, +0), +0, '-0 + 0 is +0');
6126 t.equal(ES.Number.add(-0, -0), -0, '-0 + -0 is -0');
6127
6128 forEach(v.numbers, function (number) {
6129 if (number !== 0) {
6130 t.equal(ES.Number.add(number, 0), number, debug(number) + ' + 0 adds to ' + number);
6131 }
6132 t.equal(ES.Number.add(number, 1), number + 1, debug(number) + ' + 1 adds to ' + (number + 1));
6133 t.equal(ES.Number.add(1, number), number + 1, '1 + ' + debug(number) + ' adds to ' + (number + 1));
6134 t.equal(ES.Number.add(number, -42), number - 42, debug(number) + ' + -42 adds to ' + (number - 42));
6135 t.equal(ES.Number.add(-42, number), number - 42, '-42 + ' + debug(number) + ' adds to ' + (number - 42));
6136 });
6137
6138 t.end();
6139 });
6140
6141 test('Number::bitwiseAND', function (t) {
6142 forEach(v.nonNumbers, function (nonNumber) {
6143 t['throws'](
6144 function () { ES.Number.bitwiseAND(nonNumber, 0); },
6145 TypeError,
6146 'x: ' + debug(nonNumber) + ' is not a Number'
6147 );
6148 t['throws'](
6149 function () { ES.Number.bitwiseAND(0, nonNumber); },
6150 TypeError,
6151 'y: ' + debug(nonNumber) + ' is not a Number'
6152 );
6153 });
6154
6155 t.equal(ES.Number.bitwiseAND(1, 2), 1 & 2);
6156
6157 t.end();
6158 });
6159
6160 test('Number::bitwiseNOT', function (t) {
6161 forEach(v.nonNumbers, function (nonNumber) {
6162 t['throws'](
6163 function () { ES.Number.bitwiseNOT(nonNumber); },
6164 TypeError,
6165 debug(nonNumber) + ' is not a Number'
6166 );
6167 });
6168
6169 forEach(v.int32s, function (int32) {
6170 t.equal(ES.Number.bitwiseNOT(int32), ~int32, debug(int32) + ' becomes ~' + debug(int32));
6171 });
6172
6173 t.end();
6174 });
6175
6176 test('Number::bitwiseOR', function (t) {
6177 forEach(v.nonNumbers, function (nonNumber) {
6178 t['throws'](
6179 function () { ES.Number.bitwiseOR(nonNumber, 0); },
6180 TypeError,
6181 'x: ' + debug(nonNumber) + ' is not a Number'
6182 );
6183 t['throws'](
6184 function () { ES.Number.bitwiseOR(0, nonNumber); },
6185 TypeError,
6186 'y: ' + debug(nonNumber) + ' is not a Number'
6187 );
6188 });
6189
6190 t.equal(ES.Number.bitwiseOR(1, 2), 1 | 2);
6191
6192 t.end();
6193 });
6194
6195 test('Number::bitwiseXOR', function (t) {
6196 forEach(v.nonNumbers, function (nonNumber) {
6197 t['throws'](
6198 function () { ES.Number.bitwiseXOR(nonNumber, 0); },
6199 TypeError,
6200 'x: ' + debug(nonNumber) + ' is not a Number'
6201 );
6202 t['throws'](
6203 function () { ES.Number.bitwiseXOR(0, nonNumber); },
6204 TypeError,
6205 'y: ' + debug(nonNumber) + ' is not a Number'
6206 );
6207 });
6208
6209 t.equal(ES.Number.bitwiseXOR(1, 2), 1 ^ 2);
6210
6211 t.end();
6212 });
6213
6214 test('Number::divide', function (t) {
6215 forEach(v.nonNumbers, function (nonNumber) {
6216 t['throws'](
6217 function () { ES.Number.divide(nonNumber, 0); },
6218 TypeError,
6219 'x: ' + debug(nonNumber) + ' is not a Number'
6220 );
6221 t['throws'](
6222 function () { ES.Number.divide(0, nonNumber); },
6223 TypeError,
6224 'y: ' + debug(nonNumber) + ' is not a Number'
6225 );
6226 });
6227
6228 t.equal(ES.Number.divide(Infinity, Infinity), NaN, '∞ / ∞ is NaN');
6229 t.equal(ES.Number.divide(-Infinity, Infinity), NaN, '-∞ / ∞ is NaN');
6230 t.equal(ES.Number.divide(Infinity, -Infinity), NaN, '∞ / -∞ is NaN');
6231 t.equal(ES.Number.divide(-Infinity, -Infinity), NaN, '-∞ / -∞ is NaN');
6232
6233 t.equal(ES.Number.divide(NaN, NaN), NaN, 'NaN / NaN is NaN');
6234
6235 t.equal(ES.Number.divide(+Infinity, +0), +Infinity, '+∞ / +0 is +∞');
6236 t.equal(ES.Number.divide(-Infinity, -0), +Infinity, '-∞ / -0 is +∞');
6237 t.equal(ES.Number.divide(+Infinity, -0), -Infinity, '+∞ / -0 is -∞');
6238 t.equal(ES.Number.divide(-Infinity, +0), -Infinity, '-∞ / +0 is -∞');
6239
6240 t.equal(ES.Number.divide(+0, +Infinity), +0, '+0 / +∞ is +0');
6241 t.equal(ES.Number.divide(-0, -Infinity), +0, '-0 / -∞ is +0');
6242 t.equal(ES.Number.divide(-0, +Infinity), -0, '-0 / +∞ is -0');
6243 t.equal(ES.Number.divide(+0, -Infinity), -0, '+0 / -∞ is -0');
6244
6245 forEach(v.numbers, function (number) {
6246 if (number !== 0 && isFinite(number)) {
6247 t.equal(ES.Number.divide(number, number), 1, debug(number) + ' divided by itself is 1');
6248 t.equal(ES.Number.divide(number, 2), number / 2, debug(number) + ' divided by 2 is half itself');
6249 }
6250 });
6251
6252 t.end();
6253 });
6254
6255 test('Number::equal', function (t) {
6256 forEach(v.nonNumbers, function (nonNumber) {
6257 t['throws'](
6258 function () { ES.Number.equal(nonNumber, 0); },
6259 TypeError,
6260 'x: ' + debug(nonNumber) + ' is not a Number'
6261 );
6262 t['throws'](
6263 function () { ES.Number.equal(0, nonNumber); },
6264 TypeError,
6265 'y: ' + debug(nonNumber) + ' is not a Number'
6266 );
6267 });
6268
6269 t.equal(ES.Number.equal(Infinity, Infinity), true, '∞ === ∞');
6270 t.equal(ES.Number.equal(-Infinity, Infinity), false, '-∞ !== ∞');
6271 t.equal(ES.Number.equal(Infinity, -Infinity), false, '∞ !== -∞');
6272 t.equal(ES.Number.equal(-Infinity, -Infinity), true, '-∞ === -∞');
6273
6274 t.equal(ES.Number.equal(NaN, NaN), false, 'NaN !== NaN');
6275
6276 t.equal(ES.Number.equal(Infinity, 0), false, '∞ !== 0');
6277 t.equal(ES.Number.equal(-Infinity, -0), false, '-∞ !== -0');
6278 t.equal(ES.Number.equal(Infinity, -0), false, '∞ !== -0');
6279 t.equal(ES.Number.equal(-Infinity, 0), false, '-∞ !== 0');
6280
6281 t.equal(ES.Number.equal(+0, +0), true, '+0 === +0');
6282 t.equal(ES.Number.equal(+0, -0), true, '+0 === -0');
6283 t.equal(ES.Number.equal(-0, +0), true, '-0 === +0');
6284 t.equal(ES.Number.equal(-0, -0), true, '-0 === -0');
6285
6286 forEach(v.numbers, function (number) {
6287 if (isFinite(number)) {
6288 t.equal(ES.Number.equal(number, number), true, debug(number) + ' is equal to itself');
6289 t.equal(ES.Number.equal(number, number + 1), false, debug(number) + ' is not equal to itself plus 1');
6290 }
6291 });
6292
6293 t.end();
6294 });
6295
6296 test('Number::exponentiate', function (t) {
6297 forEach(v.nonNumbers, function (nonNumber) {
6298 t['throws'](
6299 function () { ES.Number.exponentiate(nonNumber, 0); },
6300 TypeError,
6301 'base: ' + debug(nonNumber) + ' is not a Number'
6302 );
6303 t['throws'](
6304 function () { ES.Number.exponentiate(0, nonNumber); },
6305 TypeError,
6306 'exponent: ' + debug(nonNumber) + ' is not a Number'
6307 );
6308 });
6309
6310 t.equal(ES.Number.exponentiate(0, 42), 0, '+0 ** 42 is +0');
6311 t.equal(ES.Number.exponentiate(0, -42), Infinity, '+0 ** 42 is +∞');
6312 t.equal(ES.Number.exponentiate(-0, 42), 0, '-0 ** 42 is +0');
6313 t.equal(ES.Number.exponentiate(-0, 41), -0, '-0 ** 41 is -0');
6314 t.equal(ES.Number.exponentiate(-0, -42), Infinity, '-0 ** 42 is +∞');
6315 t.equal(ES.Number.exponentiate(-0, -41), -Infinity, '-0 ** 41 is -∞');
6316
6317 t.equal(ES.Number.exponentiate(Infinity, 0), 1, '+∞ ** 0 is 1');
6318 t.equal(ES.Number.exponentiate(Infinity, -0), 1, '+∞ ** -0 is 1');
6319 t.equal(ES.Number.exponentiate(-Infinity, 0), 1, '-∞ ** 0 is 1');
6320 t.equal(ES.Number.exponentiate(-Infinity, -0), 1, '-∞ ** -0 is 1');
6321
6322 t.equal(ES.Number.exponentiate(Infinity, 1), Infinity, '+∞ ** 1 is +∞');
6323 t.equal(ES.Number.exponentiate(Infinity, 2), Infinity, '+∞ ** 2 is +∞');
6324 t.equal(ES.Number.exponentiate(Infinity, -1), +0, '+∞ ** -1 is +0');
6325 t.equal(ES.Number.exponentiate(Infinity, -2), +0, '+∞ ** -2 is +0');
6326
6327 t.equal(ES.Number.exponentiate(-Infinity, 1), -Infinity, '-∞ ** 1 is -∞');
6328 t.equal(ES.Number.exponentiate(-Infinity, 2), Infinity, '-∞ ** 2 is +∞');
6329 t.equal(ES.Number.exponentiate(-Infinity, -1), -0, '-∞ ** --1 is -0');
6330 t.equal(ES.Number.exponentiate(-Infinity, -2), +0, '-∞ ** --2 is +0');
6331
6332 t.equal(ES.Number.exponentiate(1.1, Infinity), Infinity, '1.1 ** +∞ is +∞');
6333 t.equal(ES.Number.exponentiate(1.1, -Infinity), 0, '1.1 ** -∞ is +0');
6334 t.equal(ES.Number.exponentiate(-1.1, Infinity), Infinity, '-1.1 ** +∞ is +∞');
6335 t.equal(ES.Number.exponentiate(-1.1, -Infinity), 0, '-1.1 ** -∞ is +0');
6336
6337 t.equal(ES.Number.exponentiate(1, Infinity), NaN, '1 ** +∞ is NaN');
6338 t.equal(ES.Number.exponentiate(1, -Infinity), NaN, '1 ** -∞ is NaN');
6339 t.equal(ES.Number.exponentiate(-1, Infinity), NaN, '-1 ** +∞ is NaN');
6340 t.equal(ES.Number.exponentiate(-1, -Infinity), NaN, '-1 ** -∞ is NaN');
6341
6342 t.equal(ES.Number.exponentiate(0.9, Infinity), 0, '0.9 ** +∞ is +0');
6343 t.equal(ES.Number.exponentiate(0.9, -Infinity), Infinity, '0.9 ** -∞ is ∞');
6344 t.equal(ES.Number.exponentiate(-0.9, Infinity), 0, '-0.9 ** +∞ is +0');
6345 t.equal(ES.Number.exponentiate(-0.9, -Infinity), Infinity, '-0.9 ** -∞ is +∞');
6346
6347 forEach(v.numbers.concat(NaN), function (number) {
6348 t.equal(ES.Number.exponentiate(number, NaN), NaN, debug(number) + ' ** NaN is NaN');
6349
6350 if (number !== 0) {
6351 t.equal(ES.Number.exponentiate(number, 0), 1, debug(number) + ' ** +0 is 1');
6352 t.equal(ES.Number.exponentiate(number, -0), 1, debug(number) + ' ** -0 is 1');
6353 t.equal(ES.Number.exponentiate(NaN, number), NaN, 'NaN ** ' + debug(number) + ' is NaN');
6354 }
6355
6356 if (number !== 0 && isFinite(number)) {
6357 t.equal(ES.Number.equal(number, number), true, debug(number) + ' is equal to itself');
6358 t.equal(ES.Number.equal(number, number + 1), false, debug(number) + ' is not equal to itself plus 1');
6359 }
6360 });
6361
6362 t.end();
6363 });
6364
6365 test('Number::leftShift', function (t) {
6366 forEach(v.nonNumbers, function (nonNumber) {
6367 t['throws'](
6368 function () { ES.Number.leftShift(nonNumber, 0); },
6369 TypeError,
6370 'x: ' + debug(nonNumber) + ' is not a Number'
6371 );
6372 t['throws'](
6373 function () { ES.Number.leftShift(0, nonNumber); },
6374 TypeError,
6375 'y: ' + debug(nonNumber) + ' is not a Number'
6376 );
6377 });
6378
6379 forEach([0].concat(v.int32s), function (int32) {
6380 forEach([1, 3, 5, 31, 32, 33], function (bits) {
6381 t.equal(ES.Number.leftShift(int32, bits), int32 << bits, debug(int32) + ' << ' + bits + ' is ' + debug(int32 << bits));
6382 });
6383 });
6384
6385 t.end();
6386 });
6387
6388 test('Number::lessThan', function (t) {
6389 forEach(v.nonNumbers, function (nonNumber) {
6390 t['throws'](
6391 function () { ES.Number.lessThan(nonNumber, 0); },
6392 TypeError,
6393 'x: ' + debug(nonNumber) + ' is not a Number'
6394 );
6395 t['throws'](
6396 function () { ES.Number.lessThan(0, nonNumber); },
6397 TypeError,
6398 'y: ' + debug(nonNumber) + ' is not a Number'
6399 );
6400 });
6401
6402 t.equal(ES.Number.lessThan(+0, -0), false, '+0 < -0 is false');
6403 t.equal(ES.Number.lessThan(+0, +0), false, '+0 < +0 is false');
6404 t.equal(ES.Number.lessThan(-0, +0), false, '-0 < +0 is false');
6405 t.equal(ES.Number.lessThan(-0, -0), false, '-0 < -0 is false');
6406
6407 t.equal(ES.Number.lessThan(NaN, NaN), undefined, 'NaN < NaN is undefined');
6408
6409 t.equal(ES.Number.lessThan(+Infinity, +Infinity), false, '+∞ < +∞ is false');
6410 t.equal(ES.Number.lessThan(+Infinity, -Infinity), false, '+∞ < -∞ is false');
6411 t.equal(ES.Number.lessThan(-Infinity, +Infinity), true, '-∞ < +∞ is true');
6412 t.equal(ES.Number.lessThan(-Infinity, -Infinity), false, '-∞ < -∞ is false');
6413
6414 forEach(v.numbers.concat(v.infinities), function (number) {
6415 t.equal(ES.Number.lessThan(NaN, number), undefined, 'NaN < ' + debug(number) + ' is undefined');
6416 t.equal(ES.Number.lessThan(number, NaN), undefined, debug(number) + ' < NaN is undefined');
6417
6418 t.equal(ES.Number.lessThan(number, number), false, debug(number) + ' is not less than itself');
6419
6420 if (isFinite(number)) {
6421 t.equal(ES.Number.lessThan(number, number + 1), true, debug(number) + ' < ' + debug(number + 1) + ' is true');
6422 t.equal(ES.Number.lessThan(number + 1, number), false, debug(number + 1) + ' < ' + debug(number) + ' is false');
6423
6424 t.equal(ES.Number.lessThan(Infinity, number), false, '+∞ < ' + debug(number) + ' is false');
6425 t.equal(ES.Number.lessThan(number, Infinity), true, debug(number) + ' < +∞ is true');
6426 t.equal(ES.Number.lessThan(-Infinity, number), true, '-∞ < ' + debug(number) + ' is true');
6427 t.equal(ES.Number.lessThan(number, -Infinity), false, debug(number) + ' < -∞ is false');
6428 }
6429 });
6430
6431 t.end();
6432 });
6433
6434 test('Number::multiply', function (t) {
6435 forEach(v.nonNumbers, function (nonNumber) {
6436 t['throws'](
6437 function () { ES.Number.multiply(nonNumber, 0); },
6438 TypeError,
6439 'x: ' + debug(nonNumber) + ' is not a Number'
6440 );
6441 t['throws'](
6442 function () { ES.Number.multiply(0, nonNumber); },
6443 TypeError,
6444 'y: ' + debug(nonNumber) + ' is not a Number'
6445 );
6446 });
6447
6448 forEach([+0, -0, 1, -1], function (x) {
6449 var expected = x === 0 ? NaN : Infinity;
6450 t.equal(ES.Number.multiply(Infinity, x), expected, '+∞ * ' + debug(x) + ' is ' + debug(expected));
6451 t.equal(ES.Number.multiply(x, Infinity), expected, debug(x) + ' * +∞ is ' + debug(expected));
6452 t.equal(ES.Number.multiply(-Infinity, x), -expected, '-∞ * ' + debug(x) + ' is ' + debug(expected));
6453 t.equal(ES.Number.multiply(x, -Infinity), -expected, debug(x) + ' * -∞ is ' + debug(expected));
6454 });
6455
6456 t.equal(ES.Number.multiply(Infinity, Infinity), Infinity, '+∞ * +∞ is +∞');
6457 t.equal(ES.Number.multiply(Infinity, -Infinity), -Infinity, '+∞ * -∞ is -∞');
6458 t.equal(ES.Number.multiply(-Infinity, Infinity), -Infinity, '-∞ * +∞ is -∞');
6459 t.equal(ES.Number.multiply(-Infinity, -Infinity), Infinity, '-∞ * -∞ is +∞');
6460
6461 t.equal(ES.Number.multiply(+0, +0), +0, '0 * 0 is +0');
6462 t.equal(ES.Number.multiply(+0, -0), -0, '0 * -0 is -0');
6463 t.equal(ES.Number.multiply(-0, +0), -0, '-0 * 0 is -0');
6464 t.equal(ES.Number.multiply(-0, -0), +0, '-0 * -0 is +0');
6465
6466 forEach(v.numbers.concat(NaN), function (number) {
6467 t.equal(ES.Number.multiply(NaN, number), NaN, 'NaN * ' + debug(number) + ' is NaN');
6468 t.equal(ES.Number.multiply(number, NaN), NaN, debug(number) + ' * NaN is NaN');
6469
6470 if (number !== 0 && isFinite(number)) {
6471 t.equal(ES.Number.multiply(number, 0), number > 0 ? 0 : -0, debug(number) + ' * +0 produces ' + (number > 0 ? '+0' : '-0'));
6472 t.equal(ES.Number.multiply(0, number), number > 0 ? 0 : -0, '+0 * ' + debug(number) + ' produces ' + (number > 0 ? '+0' : '-0'));
6473 t.equal(ES.Number.multiply(number, -0), number > 0 ? -0 : 0, debug(number) + ' * -0 produces ' + (number > 0 ? '-0' : '+0'));
6474 t.equal(ES.Number.multiply(-0, number), number > 0 ? -0 : 0, '-0 * ' + debug(number) + ' produces ' + (number > 0 ? '-0' : '+0'));
6475 t.equal(ES.Number.multiply(number, 1), number, debug(number) + ' * 1 produces itself');
6476 t.equal(ES.Number.multiply(number, -42), number * -42, debug(number) + ' * -42 produces ' + (number - 42));
6477 }
6478 });
6479
6480 t.end();
6481 });
6482
6483 test('Number::remainder', function (t) {
6484 forEach(v.nonNumbers, function (nonNumber) {
6485 t['throws'](
6486 function () { ES.Number.remainder(nonNumber, 0); },
6487 TypeError,
6488 'x: ' + debug(nonNumber) + ' is not a Number'
6489 );
6490 t['throws'](
6491 function () { ES.Number.remainder(0, nonNumber); },
6492 TypeError,
6493 'y: ' + debug(nonNumber) + ' is not a Number'
6494 );
6495 });
6496
6497 t.equal(ES.Number.remainder(NaN, NaN), NaN, 'NaN % NaN is NaN');
6498
6499 t.equal(ES.Number.remainder(+0, +0), NaN, '+0 % +0 is NaN');
6500 t.equal(ES.Number.remainder(+0, -0), NaN, '+0 % -0 is NaN');
6501 t.equal(ES.Number.remainder(-0, +0), NaN, '-0 % +0 is NaN');
6502 t.equal(ES.Number.remainder(-0, -0), NaN, '-0 % -0 is NaN');
6503
6504 forEach(v.numbers, function (number) {
6505 t.equal(ES.Number.remainder(number, NaN), NaN, debug(number) + ' % NaN is NaN');
6506 t.equal(ES.Number.remainder(NaN, number), NaN, 'NaN % ' + debug(number) + ' is NaN');
6507
6508 t.equal(ES.Number.remainder(Infinity, number), NaN, '+∞ % ' + debug(number) + ' is NaN');
6509 t.equal(ES.Number.remainder(-Infinity, number), NaN, '-∞ % ' + debug(number) + ' is NaN');
6510 t.equal(ES.Number.remainder(number, 0), NaN, debug(number) + ' % +0 is NaN');
6511 t.equal(ES.Number.remainder(number, -0), NaN, debug(number) + ' % -0 is NaN');
6512
6513 if (isFinite(number)) {
6514 t.equal(ES.Number.remainder(number, Infinity), number, debug(number) + ' % +∞ is ' + debug(number));
6515 t.equal(ES.Number.remainder(number, -Infinity), number, debug(number) + ' % -∞ is ' + debug(number));
6516 if (number !== 0) {
6517 t.equal(ES.Number.remainder(0, number), 0, '+0 % ' + debug(number) + ' is ' + debug(number));
6518 t.equal(ES.Number.remainder(-0, number), -0, '-0 % ' + debug(number) + ' is ' + debug(number));
6519 t.looseEqual(ES.Number.remainder(number * 2, number), 0, debug(number) + ' % ' + debug(number * 2) + ' is 0');
6520 }
6521 }
6522 });
6523
6524 t.end();
6525 });
6526
6527 test('Number::sameValue', function (t) {
6528 forEach(v.nonNumbers, function (nonNumber) {
6529 t['throws'](
6530 function () { ES.Number.sameValue(nonNumber, 0); },
6531 TypeError,
6532 'x: ' + debug(nonNumber) + ' is not a Number'
6533 );
6534 t['throws'](
6535 function () { ES.Number.sameValue(0, nonNumber); },
6536 TypeError,
6537 'y: ' + debug(nonNumber) + ' is not a Number'
6538 );
6539 });
6540
6541 t.ok(ES.Number.sameValue(NaN, NaN), true, 'NaN is the sameValue as NaN');
6542
6543 t.equal(ES.Number.sameValue(+0, +0), true, '+0 is sameValue as +0');
6544 t.equal(ES.Number.sameValue(+0, -0), false, '+0 is not sameValue as -0');
6545 t.equal(ES.Number.sameValue(-0, +0), false, '-0 is not sameValue as +0');
6546 t.equal(ES.Number.sameValue(-0, -0), true, '-0 is sameValue as -0');
6547
6548 forEach(v.numbers, function (number) {
6549 t.ok(ES.Number.sameValue(number, number), debug(number) + ' is the sameValue as itself');
6550 });
6551
6552 t.end();
6553 });
6554
6555 test('Number::sameValueZero', function (t) {
6556 forEach(v.nonNumbers, function (nonNumber) {
6557 t['throws'](
6558 function () { ES.Number.sameValueZero(nonNumber, 0); },
6559 TypeError,
6560 'x: ' + debug(nonNumber) + ' is not a Number'
6561 );
6562 t['throws'](
6563 function () { ES.Number.sameValueZero(0, nonNumber); },
6564 TypeError,
6565 'y: ' + debug(nonNumber) + ' is not a Number'
6566 );
6567 });
6568
6569 t.ok(ES.Number.sameValueZero(NaN, NaN), true, 'NaN is the sameValueZero as NaN');
6570
6571 t.equal(ES.Number.sameValueZero(+0, +0), true, '+0 is sameValueZero as +0');
6572 t.equal(ES.Number.sameValueZero(+0, -0), true, '+0 is sameValueZero as -0');
6573 t.equal(ES.Number.sameValueZero(-0, +0), true, '-0 is sameValueZero as +0');
6574 t.equal(ES.Number.sameValueZero(-0, -0), true, '-0 is sameValueZero as -0');
6575
6576 forEach(v.numbers, function (number) {
6577 t.ok(ES.Number.sameValueZero(number, number), debug(number) + ' is the sameValueZero as itself');
6578 });
6579
6580 t.end();
6581 });
6582
6583 test('Number::signedRightShift', function (t) {
6584 forEach(v.nonNumbers, function (nonNumber) {
6585 t['throws'](
6586 function () { ES.Number.signedRightShift(nonNumber, 0); },
6587 TypeError,
6588 'x: ' + debug(nonNumber) + ' is not a Number'
6589 );
6590 t['throws'](
6591 function () { ES.Number.signedRightShift(0, nonNumber); },
6592 TypeError,
6593 'y: ' + debug(nonNumber) + ' is not a Number'
6594 );
6595 });
6596
6597 forEach([0].concat(v.int32s), function (int32) {
6598 forEach([1, 3, 5, 31, 32, 33], function (bits) {
6599 t.equal(ES.Number.signedRightShift(int32, bits), int32 >> bits, debug(int32) + ' >> ' + bits + ' is ' + debug(int32 >> bits));
6600 });
6601 });
6602
6603 t.end();
6604 });
6605
6606 test('Number::subtract', function (t) {
6607 forEach(v.nonNumbers, function (nonNumber) {
6608 t['throws'](
6609 function () { ES.Number.subtract(nonNumber, 0); },
6610 TypeError,
6611 'x: ' + debug(nonNumber) + ' is not a Number'
6612 );
6613 t['throws'](
6614 function () { ES.Number.subtract(0, nonNumber); },
6615 TypeError,
6616 'y: ' + debug(nonNumber) + ' is not a Number'
6617 );
6618 });
6619
6620 t.equal(ES.Number.subtract(+0, +0), +0, '0 - 0 is +0');
6621 t.equal(ES.Number.subtract(+0, -0), +0, '0 - -0 is +0');
6622 t.equal(ES.Number.subtract(-0, +0), -0, '-0 - 0 is -0');
6623 t.equal(ES.Number.subtract(-0, -0), +0, '-0 - -0 is +0');
6624
6625 forEach(v.numbers, function (number) {
6626 if (number !== 0) {
6627 t.equal(ES.Number.subtract(number, 0), number, debug(number) + ' - 0 produces ' + number);
6628 }
6629 t.equal(ES.Number.subtract(number, 1), number - 1, debug(number) + ' - 1 produces ' + (number + 1));
6630 t.equal(ES.Number.subtract(number, 42), number - 42, debug(number) + ' - 42 produces ' + (number - 42));
6631 });
6632
6633 t.end();
6634 });
6635
6636 test('Number::toString', function (t) {
6637 forEach(v.nonNumbers, function (nonNumber) {
6638 t['throws'](
6639 function () { ES.Number.toString(nonNumber); },
6640 TypeError,
6641 debug(nonNumber) + ' is not a Number'
6642 );
6643 });
6644
6645 forEach(v.numbers, function (number) {
6646 t.equal(ES.Number.toString(number), String(number), debug(number) + ' stringifies to ' + number);
6647 });
6648
6649 t.end();
6650 });
6651
6652 test('Number::unaryMinus', function (t) {
6653 forEach(v.nonNumbers, function (nonNumber) {
6654 t['throws'](
6655 function () { ES.Number.unaryMinus(nonNumber); },
6656 TypeError,
6657 debug(nonNumber) + ' is not a Number'
6658 );
6659 });
6660
6661 t.equal(ES.Number.unaryMinus(NaN), NaN, 'NaN produces NaN');
6662
6663 forEach(v.numbers, function (number) {
6664 t.equal(ES.Number.unaryMinus(number), -number, debug(number) + ' produces -' + debug(number));
6665 });
6666
6667 t.end();
6668 });
6669
6670 test('Number::unsignedRightShift', function (t) {
6671 forEach(v.nonNumbers, function (nonNumber) {
6672 t['throws'](
6673 function () { ES.Number.unsignedRightShift(nonNumber, 0); },
6674 TypeError,
6675 'x: ' + debug(nonNumber) + ' is not a Number'
6676 );
6677 t['throws'](
6678 function () { ES.Number.unsignedRightShift(0, nonNumber); },
6679 TypeError,
6680 'y: ' + debug(nonNumber) + ' is not a Number'
6681 );
6682 });
6683
6684 forEach([0].concat(v.int32s), function (int32) {
6685 forEach([1, 3, 5, 31, 32, 33], function (bits) {
6686 t.equal(ES.Number.unsignedRightShift(int32, bits), int32 >>> bits, debug(int32) + ' >>> ' + bits + ' is ' + debug(int32 >>> bits));
6687 });
6688 });
6689
6690 t.end();
6691 });
6692
6693 test('NumberToBigInt', function (t) {
6694 forEach(v.nonNumbers, function (nonNumber) {
6695 t['throws'](
6696 function () { ES.NumberToBigInt(nonNumber); },
6697 TypeError,
6698 debug(nonNumber) + ' is not a Number'
6699 );
6700 });
6701
6702 forEach(v.nonIntegerNumbers, function (nonIntegerNumber) {
6703 t['throws'](
6704 function () { ES.NumberToBigInt(nonIntegerNumber); },
6705 RangeError,
6706 debug(nonIntegerNumber) + ' is not an integer'
6707 );
6708 });
6709
6710 t.test('actual BigInts', { skip: !hasBigInts }, function (st) {
6711 forEach(v.integerNumbers, function (int) {
6712 if (int >= 1e17) {
6713 // BigInt(1e17) throws on node v10.4 - v10.8
6714 try {
6715 st.equal(ES.NumberToBigInt(int), $BigInt(int), debug(int) + ' becomes ' + debug($BigInt(int)));
6716 } catch (e) {
6717 st['throws'](
6718 function () { $BigInt(int); },
6719 RangeError,
6720 debug(int) + ' is too large on this engine to convert into a BigInt'
6721 );
6722 }
6723 } else {
6724 st.equal(ES.NumberToBigInt(int), $BigInt(int), debug(int) + ' becomes ' + debug($BigInt(int)));
6725 }
6726 });
6727 st.end();
6728 });
6729
6730 t.end();
6731 });
6732
6733 test('OrdinaryObjectCreate', function (t) {
6734 forEach(v.nonNullPrimitives, function (value) {
6735 t['throws'](
6736 function () { ES.OrdinaryObjectCreate(value); },
6737 TypeError,
6738 debug(value) + ' is not null, or an object'
6739 );
6740 });
6741
6742 t.test('proto arg', function (st) {
6743 var Parent = function Parent() {};
6744 Parent.prototype.foo = {};
6745 var child = ES.OrdinaryObjectCreate(Parent.prototype);
6746 st.equal(child instanceof Parent, true, 'child is instanceof Parent');
6747 st.equal(child.foo, Parent.prototype.foo, 'child inherits properties from Parent.prototype');
6748
6749 st.end();
6750 });
6751
6752 t.test('internal slots arg', function (st) {
6753 st.doesNotThrow(function () { ES.OrdinaryObjectCreate({}, []); }, 'an empty slot list is valid');
6754
6755 st['throws'](
6756 function () { ES.OrdinaryObjectCreate({}, ['a']); },
6757 SyntaxError,
6758 'internal slots are not supported'
6759 );
6760
6761 st.end();
6762 });
6763
6764 t.test('null proto', { skip: !$setProto }, function (st) {
6765 st.equal('toString' in {}, true, 'normal objects have toString');
6766 st.equal('toString' in ES.OrdinaryObjectCreate(null), false, 'makes a null object');
6767
6768 st.end();
6769 });
6770
6771 t.test('null proto when no native Object.create', { skip: $setProto }, function (st) {
6772 st['throws'](
6773 function () { ES.OrdinaryObjectCreate(null); },
6774 SyntaxError,
6775 'without a native Object.create, can not create null objects'
6776 );
6777
6778 st.end();
6779 });
6780
6781 t.end();
6782 });
6783
6784 test('SameValueNonNumeric', function (t) {
6785 var willThrow = [
6786 [3, 4],
6787 [NaN, 4],
6788 [4, ''],
6789 ['abc', true],
6790 [{}, false]
6791 ];
6792 forEach(willThrow, function (nums) {
6793 t['throws'](function () { return ES.SameValueNonNumeric.apply(ES, nums); }, TypeError, 'value must be same type and non-number');
6794 });
6795
6796 forEach(v.objects.concat(v.nonNumberPrimitives), function (val) {
6797 t.equal(val === val, ES.SameValueNonNumeric(val, val), debug(val) + ' is SameValueNonNumeric to itself');
6798 });
6799
6800 t.end();
6801 });
6802
6803 test('StringPad', function (t) {
6804 t.equal(ES.StringPad('a', 3, undefined, 'start'), ' a');
6805 t.equal(ES.StringPad('a', 3, undefined, 'end'), 'a ');
6806 t.equal(ES.StringPad('a', 3, '0', 'start'), '00a');
6807 t.equal(ES.StringPad('a', 3, '0', 'end'), 'a00');
6808 t.equal(ES.StringPad('a', 3, '012', 'start'), '01a');
6809 t.equal(ES.StringPad('a', 3, '012', 'end'), 'a01');
6810 t.equal(ES.StringPad('a', 7, '012', 'start'), '012012a');
6811 t.equal(ES.StringPad('a', 7, '012', 'end'), 'a012012');
6812
6813 t.end();
6814 });
6815
6816 test('thisBigIntValue', { skip: !hasBigInts }, function (t) {
6817 t.equal(ES.thisBigIntValue(BigInt(42)), BigInt(42));
6818 t.equal(ES.thisBigIntValue(Object(BigInt(42))), BigInt(42));
6819
6820 forEach(v.nonBigInts, function (nonBigInt) {
6821 t['throws'](
6822 function () { ES.thisBigIntValue(nonBigInt); },
6823 TypeError,
6824 debug(nonBigInt) + ' is not a BigInt'
6825 );
6826 });
6827
6828 t.end();
6829 });
6830
6831 test('ToInteger', function (t) {
6832 forEach([0, -0, NaN], function (num) {
6833 t.equal(0, ES.ToInteger(num), debug(num) + ' returns +0');
6834 });
6835 forEach([Infinity, 42], function (num) {
6836 t.equal(num, ES.ToInteger(num), debug(num) + ' returns itself');
6837 t.equal(-num, ES.ToInteger(-num), '-' + debug(num) + ' returns itself');
6838 });
6839 t.equal(3, ES.ToInteger(Math.PI), 'pi returns 3');
6840 t['throws'](function () { return ES.ToInteger(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
6841 t.end();
6842 });
6843
6844 test('UTF16DecodeSurrogatePair', function (t) {
6845 t['throws'](
6846 function () { ES.UTF16DecodeSurrogatePair('a'.charCodeAt(0), trailingPoo.charCodeAt(0)); },
6847 TypeError,
6848 '"a" is not a leading surrogate'
6849 );
6850 t['throws'](
6851 function () { ES.UTF16DecodeSurrogatePair(leadingPoo.charCodeAt(0), 'b'.charCodeAt(0)); },
6852 TypeError,
6853 '"b" is not a trailing surrogate'
6854 );
6855
6856 t.equal(ES.UTF16DecodeSurrogatePair(leadingPoo.charCodeAt(0), trailingPoo.charCodeAt(0)), wholePoo);
6857
6858 t.end();
6859 });
6860
6861 test('NumberBitwiseOp', function (t) {
6862 t['throws'](
6863 function () { ES.NumberBitwiseOp('invalid', 0, 0); },
6864 TypeError,
6865 'throws with an invalid op'
6866 );
6867
6868 forEach(v.nonNumbers, function (nonNumber) {
6869 t['throws'](
6870 function () { ES.NumberBitwiseOp('&', nonNumber, 0); },
6871 TypeError,
6872 'x: ' + debug(nonNumber) + ' is not a Number'
6873 );
6874 t['throws'](
6875 function () { ES.NumberBitwiseOp('&', 0, nonNumber); },
6876 TypeError,
6877 'y: ' + debug(nonNumber) + ' is not a Number'
6878 );
6879 });
6880
6881 t.equal(ES.NumberBitwiseOp('&', 1, 2), 1 & 2);
6882 t.equal(ES.NumberBitwiseOp('|', 1, 2), 1 | 2);
6883 t.equal(ES.NumberBitwiseOp('^', 1, 2), 1 ^ 2);
6884
6885 t.end();
6886 });
6887
6888 test('ToNumeric', function (t) {
6889 testToNumber(t, ES, ES.ToNumeric);
6890
6891 t.test('BigInts', { skip: !hasBigInts }, function (st) {
6892 st.equal(ES.ToNumeric(BigInt(42)), BigInt(42), debug(BigInt(42)) + ' is ' + debug(BigInt(42)));
6893 st.equal(ES.ToNumeric(Object(BigInt(42))), BigInt(42), debug(Object(BigInt(42))) + ' is ' + debug(BigInt(42)));
6894
6895 var valueOf = { valueOf: function () { return BigInt(7); } };
6896 st.equal(ES.ToNumeric(valueOf), valueOf.valueOf(), debug(valueOf) + ' is ' + debug(valueOf.valueOf()));
6897
6898 var toPrimitive = {};
6899 var value = BigInt(-2);
6900 toPrimitive[Symbol.toPrimitive] = function () { return value; };
6901 st.equal(ES.ToNumeric(toPrimitive), value, debug(toPrimitive) + ' is ' + debug(value));
6902
6903 st.end();
6904 });
6905
6906 t.end();
6907 });
6908
6909 test('UTF16DecodeString', function (t) {
6910 forEach(v.nonStrings, function (nonString) {
6911 t['throws'](
6912 function () { ES.UTF16DecodeString(nonString); },
6913 TypeError,
6914 debug(nonString) + ' is not a String'
6915 );
6916 });
6917
6918 t.deepEqual(ES.UTF16DecodeString('abc'), ['a', 'b', 'c'], 'code units get split');
6919 t.deepEqual(ES.UTF16DecodeString('a' + wholePoo + 'c'), ['a', wholePoo, 'c'], 'code points get split too');
6920
6921 t.end();
6922 });
6923};
6924
6925module.exports = {
6926 es5: es5,
6927 es2015: es2015,
6928 es2016: es2016,
6929 es2017: es2017,
6930 es2018: es2018,
6931 es2019: es2019,
6932 es2020: es2020
6933};