Passed
Push — master ( 445067...6ce435 )
by Johan
02:18
created

node_modules/es-abstract/test/tests.js   F

Complexity

Total Complexity 558
Complexity/F 1.04

Size

Lines of Code 3584
Function Count 536

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 558
eloc 2386
mnd 22
bc 22
fnc 536
dl 0
loc 3584
rs 0.8
bpm 0.041
cpm 1.041
noi 1
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like node_modules/es-abstract/test/tests.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
'use strict';
2
3
var test = require('tape');
4
5
var forEach = require('foreach');
6
var is = require('object-is');
7
var debug = require('object-inspect');
8
var assign = require('object.assign');
9
var keys = require('object-keys');
10
var has = require('has');
11
12
var assertRecordTests = require('./helpers/assertRecord');
13
var v = require('./helpers/values');
14
var diffOps = require('./diffOps');
15
16
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;
17
18
var getArraySubclassWithSpeciesConstructor = function getArraySubclass(speciesConstructor) {
19
	var Bar = function Bar() {
20
		var inst = [];
21
		Object.setPrototypeOf(inst, Bar.prototype);
22
		Object.defineProperty(inst, 'constructor', { value: Bar });
23
		return inst;
24
	};
25
	Bar.prototype = Object.create(Array.prototype);
26
	Object.setPrototypeOf(Bar, Array);
27
	Object.defineProperty(Bar, Symbol.species, { value: speciesConstructor });
28
29
	return Bar;
30
};
31
32
var hasSpecies = v.hasSymbols && Symbol.species;
33
34
var hasGroups = 'groups' in (/a/).exec('a');
35
var groups = function groups(matchObject) {
36
	return hasGroups ? assign(matchObject, { groups: matchObject.groups }) : matchObject;
37
};
38
39
var testEnumerableOwnNames = function (t, enumerableOwnNames) {
40
	forEach(v.primitives, function (nonObject) {
41
		t['throws'](
42
			function () { enumerableOwnNames(nonObject); },
43
			debug(nonObject) + ' is not an Object'
44
		);
45
	});
46
47
	var Child = function Child() {
48
		this.own = {};
49
	};
50
	Child.prototype = {
51
		inherited: {}
52
	};
53
54
	var obj = new Child();
55
56
	t.equal('own' in obj, true, 'has "own"');
57
	t.equal(has(obj, 'own'), true, 'has own "own"');
58
	t.equal(Object.prototype.propertyIsEnumerable.call(obj, 'own'), true, 'has enumerable "own"');
59
60
	t.equal('inherited' in obj, true, 'has "inherited"');
61
	t.equal(has(obj, 'inherited'), false, 'has non-own "inherited"');
62
	t.equal(has(Child.prototype, 'inherited'), true, 'Child.prototype has own "inherited"');
63
	t.equal(Child.prototype.inherited, obj.inherited, 'Child.prototype.inherited === obj.inherited');
64
	t.equal(Object.prototype.propertyIsEnumerable.call(Child.prototype, 'inherited'), true, 'has enumerable "inherited"');
65
66
	t.equal('toString' in obj, true, 'has "toString"');
67
	t.equal(has(obj, 'toString'), false, 'has non-own "toString"');
68
	t.equal(has(Object.prototype, 'toString'), true, 'Object.prototype has own "toString"');
69
	t.equal(Object.prototype.toString, obj.toString, 'Object.prototype.toString === obj.toString');
70
	// eslint-disable-next-line no-useless-call
71
	t.equal(Object.prototype.propertyIsEnumerable.call(Object.prototype, 'toString'), false, 'has non-enumerable "toString"');
72
73
	return obj;
74
};
75
76
var es2015 = function ES2015(ES, ops, expectedMissing, skips) {
77
	test('has expected operations', function (t) {
78
		var diff = diffOps(ES, ops, expectedMissing);
79
80
		t.deepEqual(diff.extra, [], 'no extra ops');
81
82
		t.deepEqual(diff.missing, [], 'no unexpected missing ops');
83
84
		t.end();
85
	});
86
87
	test('ToPrimitive', function (t) {
88
		t.test('primitives', function (st) {
89
			var testPrimitive = function (primitive) {
90
				st.ok(is(ES.ToPrimitive(primitive), primitive), debug(primitive) + ' is returned correctly');
91
			};
92
			forEach(v.primitives, testPrimitive);
93
			st.end();
94
		});
95
96
		t.test('objects', function (st) {
97
			st.equal(ES.ToPrimitive(v.coercibleObject), 3, 'coercibleObject with no hint coerces to valueOf');
98
			st.ok(is(ES.ToPrimitive({}), '[object Object]'), '{} with no hint coerces to Object#toString');
99
			st.equal(ES.ToPrimitive(v.coercibleObject, Number), 3, 'coercibleObject with hint Number coerces to valueOf');
100
			st.ok(is(ES.ToPrimitive({}, Number), '[object Object]'), '{} with hint Number coerces to NaN');
101
			st.equal(ES.ToPrimitive(v.coercibleObject, String), 42, 'coercibleObject with hint String coerces to nonstringified toString');
102
			st.equal(ES.ToPrimitive({}, String), '[object Object]', '{} with hint String coerces to Object#toString');
103
			st.equal(ES.ToPrimitive(v.toStringOnlyObject), 7, 'toStringOnlyObject returns non-stringified toString');
104
			st.equal(ES.ToPrimitive(v.valueOfOnlyObject), 4, 'valueOfOnlyObject returns valueOf');
105
			st['throws'](function () { return ES.ToPrimitive(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError');
106
			st.end();
107
		});
108
109
		t.test('dates', function (st) {
110
			var invalid = new Date(NaN);
111
			st.equal(ES.ToPrimitive(invalid), Date.prototype.toString.call(invalid), 'invalid Date coerces to Date#toString');
112
			var now = new Date();
113
			st.equal(ES.ToPrimitive(now), Date.prototype.toString.call(now), 'Date coerces to Date#toString');
114
			st.end();
115
		});
116
117
		t.end();
118
	});
119
120
	test('ToBoolean', function (t) {
121
		t.equal(false, ES.ToBoolean(undefined), 'undefined coerces to false');
122
		t.equal(false, ES.ToBoolean(null), 'null coerces to false');
123
		t.equal(false, ES.ToBoolean(false), 'false returns false');
124
		t.equal(true, ES.ToBoolean(true), 'true returns true');
125
126
		t.test('numbers', function (st) {
127
			forEach([0, -0, NaN], function (falsyNumber) {
128
				st.equal(false, ES.ToBoolean(falsyNumber), 'falsy number ' + falsyNumber + ' coerces to false');
129
			});
130
			forEach([Infinity, 42, 1, -Infinity], function (truthyNumber) {
131
				st.equal(true, ES.ToBoolean(truthyNumber), 'truthy number ' + truthyNumber + ' coerces to true');
132
			});
133
134
			st.end();
135
		});
136
137
		t.equal(false, ES.ToBoolean(''), 'empty string coerces to false');
138
		t.equal(true, ES.ToBoolean('foo'), 'nonempty string coerces to true');
139
140
		t.test('objects', function (st) {
141
			forEach(v.objects, function (obj) {
142
				st.equal(true, ES.ToBoolean(obj), 'object coerces to true');
143
			});
144
			st.equal(true, ES.ToBoolean(v.uncoercibleObject), 'uncoercibleObject coerces to true');
145
146
			st.end();
147
		});
148
149
		t.end();
150
	});
151
152
	test('ToNumber', function (t) {
153
		t.ok(is(NaN, ES.ToNumber(undefined)), 'undefined coerces to NaN');
154
		t.ok(is(ES.ToNumber(null), 0), 'null coerces to +0');
155
		t.ok(is(ES.ToNumber(false), 0), 'false coerces to +0');
156
		t.equal(1, ES.ToNumber(true), 'true coerces to 1');
157
158
		t.test('numbers', function (st) {
159
			st.ok(is(NaN, ES.ToNumber(NaN)), 'NaN returns itself');
160
			forEach([0, -0, 42, Infinity, -Infinity], function (num) {
161
				st.equal(num, ES.ToNumber(num), num + ' returns itself');
162
			});
163
			forEach(['foo', '0', '4a', '2.0', 'Infinity', '-Infinity'], function (numString) {
164
				st.ok(is(+numString, ES.ToNumber(numString)), '"' + numString + '" coerces to ' + Number(numString));
165
			});
166
			st.end();
167
		});
168
169
		t.test('objects', function (st) {
170
			forEach(v.objects, function (object) {
171
				st.ok(is(ES.ToNumber(object), ES.ToNumber(ES.ToPrimitive(object))), 'object ' + object + ' coerces to same as ToPrimitive of object does');
172
			});
173
			st['throws'](function () { return ES.ToNumber(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
174
			st.end();
175
		});
176
177
		t.test('binary literals', function (st) {
178
			st.equal(ES.ToNumber('0b10'), 2, '0b10 is 2');
179
			st.equal(ES.ToNumber({ toString: function () { return '0b11'; } }), 3, 'Object that toStrings to 0b11 is 3');
180
181
			st.equal(true, is(ES.ToNumber('0b12'), NaN), '0b12 is NaN');
182
			st.equal(true, is(ES.ToNumber({ toString: function () { return '0b112'; } }), NaN), 'Object that toStrings to 0b112 is NaN');
183
			st.end();
184
		});
185
186
		t.test('octal literals', function (st) {
187
			st.equal(ES.ToNumber('0o10'), 8, '0o10 is 8');
188
			st.equal(ES.ToNumber({ toString: function () { return '0o11'; } }), 9, 'Object that toStrings to 0o11 is 9');
189
190
			st.equal(true, is(ES.ToNumber('0o18'), NaN), '0o18 is NaN');
191
			st.equal(true, is(ES.ToNumber({ toString: function () { return '0o118'; } }), NaN), 'Object that toStrings to 0o118 is NaN');
192
			st.end();
193
		});
194
195
		t.test('signed hex numbers', function (st) {
196
			st.equal(true, is(ES.ToNumber('-0xF'), NaN), '-0xF is NaN');
197
			st.equal(true, is(ES.ToNumber(' -0xF '), NaN), 'space-padded -0xF is NaN');
198
			st.equal(true, is(ES.ToNumber('+0xF'), NaN), '+0xF is NaN');
199
			st.equal(true, is(ES.ToNumber(' +0xF '), NaN), 'space-padded +0xF is NaN');
200
201
			st.end();
202
		});
203
204
		t.test('trimming of whitespace and non-whitespace characters', function (st) {
205
			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';
206
			st.equal(0, ES.ToNumber(whitespace + 0 + whitespace), 'whitespace is trimmed');
207
208
			// Zero-width space (zws), next line character (nel), and non-character (bom) are not whitespace.
209
			var nonWhitespaces = {
210
				'\\u0085': '\u0085',
211
				'\\u200b': '\u200b',
212
				'\\ufffe': '\ufffe'
213
			};
214
215
			forEach(nonWhitespaces, function (desc, nonWS) {
216
				st.equal(true, is(ES.ToNumber(nonWS + 0 + nonWS), NaN), 'non-whitespace ' + desc + ' not trimmed');
217
			});
218
219
			st.end();
220
		});
221
222
		forEach(v.symbols, function (symbol) {
223
			t['throws'](
224
				function () { ES.ToNumber(symbol); },
225
				TypeError,
226
				'Symbols can’t be converted to a Number: ' + debug(symbol)
227
			);
228
		});
229
230
		t.test('dates', function (st) {
231
			var invalid = new Date(NaN);
232
			st.ok(is(ES.ToNumber(invalid), NaN), 'invalid Date coerces to NaN');
233
			var now = Date.now();
234
			st.equal(ES.ToNumber(new Date(now)), now, 'Date coerces to timestamp');
235
			st.end();
236
		});
237
238
		t.end();
239
	});
240
241
	test('ToInteger', function (t) {
242
		t.ok(is(0, ES.ToInteger(NaN)), 'NaN coerces to +0');
243
		forEach([0, Infinity, 42], function (num) {
244
			t.ok(is(num, ES.ToInteger(num)), num + ' returns itself');
245
			t.ok(is(-num, ES.ToInteger(-num)), '-' + num + ' returns itself');
246
		});
247
		t.equal(3, ES.ToInteger(Math.PI), 'pi returns 3');
248
		t['throws'](function () { return ES.ToInteger(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
249
		t.end();
250
	});
251
252
	test('ToInt32', function (t) {
253
		t.ok(is(0, ES.ToInt32(NaN)), 'NaN coerces to +0');
254
		forEach([0, Infinity], function (num) {
255
			t.ok(is(0, ES.ToInt32(num)), num + ' returns +0');
256
			t.ok(is(0, ES.ToInt32(-num)), '-' + num + ' returns +0');
257
		});
258
		t['throws'](function () { return ES.ToInt32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
259
		t.ok(is(ES.ToInt32(0x100000000), 0), '2^32 returns +0');
260
		t.ok(is(ES.ToInt32(0x100000000 - 1), -1), '2^32 - 1 returns -1');
261
		t.ok(is(ES.ToInt32(0x80000000), -0x80000000), '2^31 returns -2^31');
262
		t.ok(is(ES.ToInt32(0x80000000 - 1), 0x80000000 - 1), '2^31 - 1 returns 2^31 - 1');
263
		forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
264
			t.ok(is(ES.ToInt32(num), ES.ToInt32(ES.ToUint32(num))), 'ToInt32(x) === ToInt32(ToUint32(x)) for 0x' + num.toString(16));
265
			t.ok(is(ES.ToInt32(-num), ES.ToInt32(ES.ToUint32(-num))), 'ToInt32(x) === ToInt32(ToUint32(x)) for -0x' + num.toString(16));
266
		});
267
		t.end();
268
	});
269
270
	test('ToUint32', function (t) {
271
		t.ok(is(0, ES.ToUint32(NaN)), 'NaN coerces to +0');
272
		forEach([0, Infinity], function (num) {
273
			t.ok(is(0, ES.ToUint32(num)), num + ' returns +0');
274
			t.ok(is(0, ES.ToUint32(-num)), '-' + num + ' returns +0');
275
		});
276
		t['throws'](function () { return ES.ToUint32(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
277
		t.ok(is(ES.ToUint32(0x100000000), 0), '2^32 returns +0');
278
		t.ok(is(ES.ToUint32(0x100000000 - 1), 0x100000000 - 1), '2^32 - 1 returns 2^32 - 1');
279
		t.ok(is(ES.ToUint32(0x80000000), 0x80000000), '2^31 returns 2^31');
280
		t.ok(is(ES.ToUint32(0x80000000 - 1), 0x80000000 - 1), '2^31 - 1 returns 2^31 - 1');
281
		forEach([0, Infinity, NaN, 0x100000000, 0x80000000, 0x10000, 0x42], function (num) {
282
			t.ok(is(ES.ToUint32(num), ES.ToUint32(ES.ToInt32(num))), 'ToUint32(x) === ToUint32(ToInt32(x)) for 0x' + num.toString(16));
283
			t.ok(is(ES.ToUint32(-num), ES.ToUint32(ES.ToInt32(-num))), 'ToUint32(x) === ToUint32(ToInt32(x)) for -0x' + num.toString(16));
284
		});
285
		t.end();
286
	});
287
288
	test('ToInt16', function (t) {
289
		t.ok(is(0, ES.ToInt16(NaN)), 'NaN coerces to +0');
290
		forEach([0, Infinity], function (num) {
291
			t.ok(is(0, ES.ToInt16(num)), num + ' returns +0');
292
			t.ok(is(0, ES.ToInt16(-num)), '-' + num + ' returns +0');
293
		});
294
		t['throws'](function () { return ES.ToInt16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
295
		t.ok(is(ES.ToInt16(0x100000000), 0), '2^32 returns +0');
296
		t.ok(is(ES.ToInt16(0x100000000 - 1), -1), '2^32 - 1 returns -1');
297
		t.ok(is(ES.ToInt16(0x80000000), 0), '2^31 returns +0');
298
		t.ok(is(ES.ToInt16(0x80000000 - 1), -1), '2^31 - 1 returns -1');
299
		t.ok(is(ES.ToInt16(0x10000), 0), '2^16 returns +0');
300
		t.ok(is(ES.ToInt16(0x10000 - 1), -1), '2^16 - 1 returns -1');
301
		t.end();
302
	});
303
304
	test('ToUint16', function (t) {
305
		t.ok(is(0, ES.ToUint16(NaN)), 'NaN coerces to +0');
306
		forEach([0, Infinity], function (num) {
307
			t.ok(is(0, ES.ToUint16(num)), num + ' returns +0');
308
			t.ok(is(0, ES.ToUint16(-num)), '-' + num + ' returns +0');
309
		});
310
		t['throws'](function () { return ES.ToUint16(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
311
		t.ok(is(ES.ToUint16(0x100000000), 0), '2^32 returns +0');
312
		t.ok(is(ES.ToUint16(0x100000000 - 1), 0x10000 - 1), '2^32 - 1 returns 2^16 - 1');
313
		t.ok(is(ES.ToUint16(0x80000000), 0), '2^31 returns +0');
314
		t.ok(is(ES.ToUint16(0x80000000 - 1), 0x10000 - 1), '2^31 - 1 returns 2^16 - 1');
315
		t.ok(is(ES.ToUint16(0x10000), 0), '2^16 returns +0');
316
		t.ok(is(ES.ToUint16(0x10000 - 1), 0x10000 - 1), '2^16 - 1 returns 2^16 - 1');
317
		t.end();
318
	});
319
320
	test('ToInt8', function (t) {
321
		t.ok(is(0, ES.ToInt8(NaN)), 'NaN coerces to +0');
322
		forEach([0, Infinity], function (num) {
323
			t.ok(is(0, ES.ToInt8(num)), num + ' returns +0');
324
			t.ok(is(0, ES.ToInt8(-num)), '-' + num + ' returns +0');
325
		});
326
		t['throws'](function () { return ES.ToInt8(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
327
		t.ok(is(ES.ToInt8(0x100000000), 0), '2^32 returns +0');
328
		t.ok(is(ES.ToInt8(0x100000000 - 1), -1), '2^32 - 1 returns -1');
329
		t.ok(is(ES.ToInt8(0x80000000), 0), '2^31 returns +0');
330
		t.ok(is(ES.ToInt8(0x80000000 - 1), -1), '2^31 - 1 returns -1');
331
		t.ok(is(ES.ToInt8(0x10000), 0), '2^16 returns +0');
332
		t.ok(is(ES.ToInt8(0x10000 - 1), -1), '2^16 - 1 returns -1');
333
		t.ok(is(ES.ToInt8(0x100), 0), '2^8 returns +0');
334
		t.ok(is(ES.ToInt8(0x100 - 1), -1), '2^8 - 1 returns -1');
335
		t.ok(is(ES.ToInt8(0x10), 0x10), '2^4 returns 2^4');
336
		t.end();
337
	});
338
339
	test('ToUint8', function (t) {
340
		t.ok(is(0, ES.ToUint8(NaN)), 'NaN coerces to +0');
341
		forEach([0, Infinity], function (num) {
342
			t.ok(is(0, ES.ToUint8(num)), num + ' returns +0');
343
			t.ok(is(0, ES.ToUint8(-num)), '-' + num + ' returns +0');
344
		});
345
		t['throws'](function () { return ES.ToUint8(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
346
		t.ok(is(ES.ToUint8(0x100000000), 0), '2^32 returns +0');
347
		t.ok(is(ES.ToUint8(0x100000000 - 1), 0x100 - 1), '2^32 - 1 returns 2^8 - 1');
348
		t.ok(is(ES.ToUint8(0x80000000), 0), '2^31 returns +0');
349
		t.ok(is(ES.ToUint8(0x80000000 - 1), 0x100 - 1), '2^31 - 1 returns 2^8 - 1');
350
		t.ok(is(ES.ToUint8(0x10000), 0), '2^16 returns +0');
351
		t.ok(is(ES.ToUint8(0x10000 - 1), 0x100 - 1), '2^16 - 1 returns 2^8 - 1');
352
		t.ok(is(ES.ToUint8(0x100), 0), '2^8 returns +0');
353
		t.ok(is(ES.ToUint8(0x100 - 1), 0x100 - 1), '2^8 - 1 returns 2^16 - 1');
354
		t.ok(is(ES.ToUint8(0x10), 0x10), '2^4 returns 2^4');
355
		t.ok(is(ES.ToUint8(0x10 - 1), 0x10 - 1), '2^4 - 1 returns 2^4 - 1');
356
		t.end();
357
	});
358
359
	test('ToUint8Clamp', function (t) {
360
		t.ok(is(0, ES.ToUint8Clamp(NaN)), 'NaN coerces to +0');
361
		t.ok(is(0, ES.ToUint8Clamp(0)), '+0 returns +0');
362
		t.ok(is(0, ES.ToUint8Clamp(-0)), '-0 returns +0');
363
		t.ok(is(0, ES.ToUint8Clamp(-Infinity)), '-Infinity returns +0');
364
		t['throws'](function () { return ES.ToUint8Clamp(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
365
		forEach([255, 256, 0x100000, Infinity], function (number) {
366
			t.ok(is(255, ES.ToUint8Clamp(number)), number + ' coerces to 255');
367
		});
368
		t.equal(1, ES.ToUint8Clamp(1.49), '1.49 coerces to 1');
369
		t.equal(2, ES.ToUint8Clamp(1.5), '1.5 coerces to 2, because 2 is even');
370
		t.equal(2, ES.ToUint8Clamp(1.51), '1.51 coerces to 2');
371
372
		t.equal(2, ES.ToUint8Clamp(2.49), '2.49 coerces to 2');
373
		t.equal(2, ES.ToUint8Clamp(2.5), '2.5 coerces to 2, because 2 is even');
374
		t.equal(3, ES.ToUint8Clamp(2.51), '2.51 coerces to 3');
375
		t.end();
376
	});
377
378
	test('ToString', function (t) {
379
		forEach(v.objects.concat(v.nonSymbolPrimitives), function (item) {
380
			t.equal(ES.ToString(item), String(item), 'ES.ToString(' + debug(item) + ') ToStrings to String(' + debug(item) + ')');
381
		});
382
383
		t['throws'](function () { return ES.ToString(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws');
384
385
		forEach(v.symbols, function (symbol) {
386
			t['throws'](function () { return ES.ToString(symbol); }, TypeError, debug(symbol) + ' throws');
387
		});
388
		t.end();
389
	});
390
391
	test('ToObject', function (t) {
392
		t['throws'](function () { return ES.ToObject(undefined); }, TypeError, 'undefined throws');
393
		t['throws'](function () { return ES.ToObject(null); }, TypeError, 'null throws');
394
		forEach(v.numbers, function (number) {
395
			var obj = ES.ToObject(number);
396
			t.equal(typeof obj, 'object', 'number ' + number + ' coerces to object');
397
			t.equal(true, obj instanceof Number, 'object of ' + number + ' is Number object');
398
			t.ok(is(obj.valueOf(), number), 'object of ' + number + ' coerces to ' + number);
399
		});
400
		t.end();
401
	});
402
403
	test('RequireObjectCoercible', function (t) {
404
		t.equal(false, 'CheckObjectCoercible' in ES, 'CheckObjectCoercible -> RequireObjectCoercible in ES6');
405
		t['throws'](function () { return ES.RequireObjectCoercible(undefined); }, TypeError, 'undefined throws');
406
		t['throws'](function () { return ES.RequireObjectCoercible(null); }, TypeError, 'null throws');
407
		var isCoercible = function (value) {
408
			t.doesNotThrow(function () { return ES.RequireObjectCoercible(value); }, debug(value) + ' does not throw');
409
		};
410
		forEach(v.objects.concat(v.nonNullPrimitives), isCoercible);
411
		t.end();
412
	});
413
414
	test('IsCallable', function (t) {
415
		t.equal(true, ES.IsCallable(function () {}), 'function is callable');
416
		var nonCallables = [/a/g, {}, Object.prototype, NaN].concat(v.nonFunctions);
417
		forEach(nonCallables, function (nonCallable) {
418
			t.equal(false, ES.IsCallable(nonCallable), debug(nonCallable) + ' is not callable');
419
		});
420
		t.end();
421
	});
422
423
	test('SameValue', function (t) {
424
		t.equal(true, ES.SameValue(NaN, NaN), 'NaN is SameValue as NaN');
425
		t.equal(false, ES.SameValue(0, -0), '+0 is not SameValue as -0');
426
		forEach(v.objects.concat(v.primitives), function (val) {
427
			t.equal(val === val, ES.SameValue(val, val), debug(val) + ' is SameValue to itself');
428
		});
429
		t.end();
430
	});
431
432
	test('SameValueZero', function (t) {
433
		t.equal(true, ES.SameValueZero(NaN, NaN), 'NaN is SameValueZero as NaN');
434
		t.equal(true, ES.SameValueZero(0, -0), '+0 is SameValueZero as -0');
435
		forEach(v.objects.concat(v.primitives), function (val) {
436
			t.equal(val === val, ES.SameValueZero(val, val), debug(val) + ' is SameValueZero to itself');
437
		});
438
		t.end();
439
	});
440
441
	test('ToPropertyKey', function (t) {
442
		forEach(v.objects.concat(v.nonSymbolPrimitives), function (value) {
443
			t.equal(ES.ToPropertyKey(value), String(value), 'ToPropertyKey(value) === String(value) for non-Symbols');
444
		});
445
446
		forEach(v.symbols, function (symbol) {
447
			t.equal(
448
				ES.ToPropertyKey(symbol),
449
				symbol,
450
				'ToPropertyKey(' + debug(symbol) + ') === ' + debug(symbol)
451
			);
452
			t.equal(
453
				ES.ToPropertyKey(Object(symbol)),
454
				symbol,
455
				'ToPropertyKey(' + debug(Object(symbol)) + ') === ' + debug(symbol)
456
			);
457
		});
458
459
		t.end();
460
	});
461
462
	test('ToLength', function (t) {
463
		t['throws'](function () { return ES.ToLength(v.uncoercibleObject); }, TypeError, 'uncoercibleObject throws a TypeError');
464
		t.equal(3, ES.ToLength(v.coercibleObject), 'coercibleObject coerces to 3');
465
		t.equal(42, ES.ToLength('42.5'), '"42.5" coerces to 42');
466
		t.equal(7, ES.ToLength(7.3), '7.3 coerces to 7');
467
		forEach([-0, -1, -42, -Infinity], function (negative) {
468
			t.ok(is(0, ES.ToLength(negative)), negative + ' coerces to +0');
469
		});
470
		t.equal(MAX_SAFE_INTEGER, ES.ToLength(MAX_SAFE_INTEGER + 1), '2^53 coerces to 2^53 - 1');
471
		t.equal(MAX_SAFE_INTEGER, ES.ToLength(MAX_SAFE_INTEGER + 3), '2^53 + 2 coerces to 2^53 - 1');
472
		t.end();
473
	});
474
475
	test('IsArray', function (t) {
476
		t.equal(true, ES.IsArray([]), '[] is array');
477
		t.equal(false, ES.IsArray({}), '{} is not array');
478
		t.equal(false, ES.IsArray({ length: 1, 0: true }), 'arraylike object is not array');
479
		forEach(v.objects.concat(v.primitives), function (value) {
480
			t.equal(false, ES.IsArray(value), debug(value) + ' is not array');
481
		});
482
		t.end();
483
	});
484
485
	test('IsRegExp', function (t) {
486
		forEach([/a/g, new RegExp('a', 'g')], function (regex) {
487
			t.equal(true, ES.IsRegExp(regex), regex + ' is regex');
488
		});
489
490
		forEach(v.objects.concat(v.primitives), function (nonRegex) {
491
			t.equal(false, ES.IsRegExp(nonRegex), debug(nonRegex) + ' is not regex');
492
		});
493
494
		t.test('Symbol.match', { skip: !v.hasSymbols || !Symbol.match }, function (st) {
495
			var obj = {};
496
			obj[Symbol.match] = true;
497
			st.equal(true, ES.IsRegExp(obj), 'object with truthy Symbol.match is regex');
498
499
			var regex = /a/;
500
			regex[Symbol.match] = false;
501
			st.equal(false, ES.IsRegExp(regex), 'regex with falsy Symbol.match is not regex');
502
503
			st.end();
504
		});
505
506
		t.end();
507
	});
508
509
	test('IsPropertyKey', function (t) {
510
		forEach(v.numbers.concat(v.objects), function (notKey) {
511
			t.equal(false, ES.IsPropertyKey(notKey), debug(notKey) + ' is not property key');
512
		});
513
514
		t.equal(true, ES.IsPropertyKey('foo'), 'string is property key');
515
516
		forEach(v.symbols, function (symbol) {
517
			t.equal(true, ES.IsPropertyKey(symbol), debug(symbol) + ' is property key');
518
		});
519
		t.end();
520
	});
521
522
	test('IsInteger', function (t) {
523
		for (var i = -100; i < 100; i += 10) {
524
			t.equal(true, ES.IsInteger(i), i + ' is integer');
525
			t.equal(false, ES.IsInteger(i + 0.2), (i + 0.2) + ' is not integer');
526
		}
527
		t.equal(true, ES.IsInteger(-0), '-0 is integer');
528
		var notInts = v.nonNumbers.concat(v.nonIntegerNumbers, [Infinity, -Infinity, NaN, [], new Date()]);
529
		forEach(notInts, function (notInt) {
530
			t.equal(false, ES.IsInteger(notInt), debug(notInt) + ' is not integer');
531
		});
532
		t.equal(false, ES.IsInteger(v.uncoercibleObject), 'uncoercibleObject is not integer');
533
		t.end();
534
	});
535
536
	test('IsExtensible', function (t) {
537
		forEach(v.objects, function (object) {
538
			t.equal(true, ES.IsExtensible(object), debug(object) + ' object is extensible');
539
		});
540
		forEach(v.primitives, function (primitive) {
541
			t.equal(false, ES.IsExtensible(primitive), debug(primitive) + ' is not extensible');
542
		});
543
		if (Object.preventExtensions) {
544
			t.equal(false, ES.IsExtensible(Object.preventExtensions({})), 'object with extensions prevented is not extensible');
545
		}
546
		t.end();
547
	});
548
549
	test('CanonicalNumericIndexString', function (t) {
550
		var throwsOnNonString = function (notString) {
551
			t['throws'](
552
				function () { return ES.CanonicalNumericIndexString(notString); },
553
				TypeError,
554
				debug(notString) + ' is not a string'
555
			);
556
		};
557
		forEach(v.objects.concat(v.numbers), throwsOnNonString);
558
		t.ok(is(-0, ES.CanonicalNumericIndexString('-0')), '"-0" returns -0');
559
		for (var i = -50; i < 50; i += 10) {
560
			t.equal(i, ES.CanonicalNumericIndexString(String(i)), '"' + i + '" returns ' + i);
561
			t.equal(undefined, ES.CanonicalNumericIndexString(String(i) + 'a'), '"' + i + 'a" returns undefined');
562
		}
563
		t.end();
564
	});
565
566
	test('IsConstructor', function (t) {
567
		t.equal(true, ES.IsConstructor(function () {}), 'function is constructor');
568
		t.equal(false, ES.IsConstructor(/a/g), 'regex is not constructor');
569
		forEach(v.objects, function (object) {
570
			t.equal(false, ES.IsConstructor(object), object + ' object is not constructor');
571
		});
572
573
		try {
574
			var foo = Function('return class Foo {}')(); // eslint-disable-line no-new-func
575
			t.equal(ES.IsConstructor(foo), true, 'class is constructor');
576
		} catch (e) {
577
			t.comment('SKIP: class syntax not supported.');
578
		}
579
		t.end();
580
	});
581
582
	test('Call', function (t) {
583
		var receiver = {};
584
		var notFuncs = v.nonFunctions.concat([/a/g, new RegExp('a', 'g')]);
585
		t.plan(notFuncs.length + 4);
586
		var throwsIfNotCallable = function (notFunc) {
587
			t['throws'](
588
				function () { return ES.Call(notFunc, receiver); },
589
				TypeError,
590
				debug(notFunc) + ' (' + typeof notFunc + ') is not callable'
591
			);
592
		};
593
		forEach(notFuncs, throwsIfNotCallable);
594
		ES.Call(
595
			function (a, b) {
596
				t.equal(this, receiver, 'context matches expected');
597
				t.deepEqual([a, b], [1, 2], 'named args are correct');
598
				t.equal(arguments.length, 3, 'extra argument was passed');
599
				t.equal(arguments[2], 3, 'extra argument was correct');
600
			},
601
			receiver,
602
			[1, 2, 3]
603
		);
604
		t.end();
605
	});
606
607
	test('GetV', function (t) {
608
		t['throws'](function () { return ES.GetV({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
609
		var obj = { a: function () {} };
610
		t.equal(ES.GetV(obj, 'a'), obj.a, 'returns property if it exists');
611
		t.equal(ES.GetV(obj, 'b'), undefined, 'returns undefiend if property does not exist');
612
		t.end();
613
	});
614
615
	test('GetMethod', function (t) {
616
		t['throws'](function () { return ES.GetMethod({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
617
		t.equal(ES.GetMethod({}, 'a'), undefined, 'returns undefined in property is undefined');
618
		t.equal(ES.GetMethod({ a: null }, 'a'), undefined, 'returns undefined if property is null');
619
		t.equal(ES.GetMethod({ a: undefined }, 'a'), undefined, 'returns undefined if property is undefined');
620
		var obj = { a: function () {} };
621
		t['throws'](function () { ES.GetMethod({ a: 'b' }, 'a'); }, TypeError, 'throws TypeError if property exists and is not callable');
622
		t.equal(ES.GetMethod(obj, 'a'), obj.a, 'returns property if it is callable');
623
		t.end();
624
	});
625
626
	test('Get', function (t) {
627
		t['throws'](function () { return ES.Get('a', 'a'); }, TypeError, 'Throws a TypeError if `O` is not an Object');
628
		t['throws'](function () { return ES.Get({ 7: 7 }, 7); }, TypeError, 'Throws a TypeError if `P` is not a property key');
629
630
		var value = {};
631
		t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
632
			var sym = Symbol('sym');
633
			var obj = {};
634
			obj[sym] = value;
635
			st.equal(ES.Get(obj, sym), value, 'returns property `P` if it exists on object `O`');
636
			st.end();
637
		});
638
		t.equal(ES.Get({ a: value }, 'a'), value, 'returns property `P` if it exists on object `O`');
639
		t.end();
640
	});
641
642
	test('Type', { skip: !v.hasSymbols }, function (t) {
643
		t.equal(ES.Type(Symbol.iterator), 'Symbol', 'Type(Symbol.iterator) is Symbol');
644
		t.end();
645
	});
646
647
	test('SpeciesConstructor', function (t) {
648
		t['throws'](function () { ES.SpeciesConstructor(null); }, TypeError);
649
		t['throws'](function () { ES.SpeciesConstructor(undefined); }, TypeError);
650
651
		var defaultConstructor = function Foo() {};
652
653
		t.equal(
654
			ES.SpeciesConstructor({ constructor: undefined }, defaultConstructor),
655
			defaultConstructor,
656
			'undefined constructor returns defaultConstructor'
657
		);
658
659
		t['throws'](
660
			function () { return ES.SpeciesConstructor({ constructor: null }, defaultConstructor); },
661
			TypeError,
662
			'non-undefined non-object constructor throws'
663
		);
664
665
		t.test('with Symbol.species', { skip: !hasSpecies }, function (st) {
666
			var Bar = function Bar() {};
667
			Bar[Symbol.species] = null;
668
669
			st.equal(
670
				ES.SpeciesConstructor(new Bar(), defaultConstructor),
671
				defaultConstructor,
672
				'undefined/null Symbol.species returns default constructor'
673
			);
674
675
			var Baz = function Baz() {};
676
			Baz[Symbol.species] = Bar;
677
			st.equal(
678
				ES.SpeciesConstructor(new Baz(), defaultConstructor),
679
				Bar,
680
				'returns Symbol.species constructor value'
681
			);
682
683
			Baz[Symbol.species] = {};
684
			st['throws'](
685
				function () { ES.SpeciesConstructor(new Baz(), defaultConstructor); },
686
				TypeError,
687
				'throws when non-constructor non-null non-undefined species value found'
688
			);
689
690
			st.end();
691
		});
692
693
		t.end();
694
	});
695
696
	test('IsPropertyDescriptor', { skip: skips && skips.IsPropertyDescriptor }, function (t) {
697
		forEach(v.nonUndefinedPrimitives, function (primitive) {
698
			t.equal(
699
				ES.IsPropertyDescriptor(primitive),
700
				false,
701
				debug(primitive) + ' is not a Property Descriptor'
702
			);
703
		});
704
705
		t.equal(ES.IsPropertyDescriptor({ invalid: true }), false, 'invalid keys not allowed on a Property Descriptor');
706
707
		t.equal(ES.IsPropertyDescriptor({}), true, 'empty object is an incomplete Property Descriptor');
708
709
		t.equal(ES.IsPropertyDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is a Property Descriptor');
710
		t.equal(ES.IsPropertyDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is a Property Descriptor');
711
		t.equal(ES.IsPropertyDescriptor(v.dataDescriptor()), true, 'data descriptor is a Property Descriptor');
712
		t.equal(ES.IsPropertyDescriptor(v.genericDescriptor()), true, 'generic descriptor is a Property Descriptor');
713
714
		t['throws'](
715
			function () {
716
				ES.IsPropertyDescriptor(v.bothDescriptor());
717
			}, TypeError,
718
			'a Property Descriptor can not be both a Data and an Accessor Descriptor'
719
		);
720
721
		t.end();
722
	});
723
724
	assertRecordTests(ES, test);
725
726
	test('IsAccessorDescriptor', function (t) {
727
		forEach(v.nonUndefinedPrimitives, function (primitive) {
728
			t['throws'](
729
				function () { ES.IsAccessorDescriptor(primitive); },
730
				TypeError,
731
				debug(primitive) + ' is not a Property Descriptor'
732
			);
733
		});
734
735
		t.equal(ES.IsAccessorDescriptor(), false, 'no value is not an Accessor Descriptor');
736
		t.equal(ES.IsAccessorDescriptor(undefined), false, 'undefined value is not an Accessor Descriptor');
737
738
		t.equal(ES.IsAccessorDescriptor(v.accessorDescriptor()), true, 'accessor descriptor is an Accessor Descriptor');
739
		t.equal(ES.IsAccessorDescriptor(v.mutatorDescriptor()), true, 'mutator descriptor is an Accessor Descriptor');
740
		t.equal(ES.IsAccessorDescriptor(v.dataDescriptor()), false, 'data descriptor is not an Accessor Descriptor');
741
		t.equal(ES.IsAccessorDescriptor(v.genericDescriptor()), false, 'generic descriptor is not an Accessor Descriptor');
742
743
		t.end();
744
	});
745
746
	test('IsDataDescriptor', function (t) {
747
		forEach(v.nonUndefinedPrimitives, function (primitive) {
748
			t['throws'](
749
				function () { ES.IsDataDescriptor(primitive); },
750
				TypeError,
751
				debug(primitive) + ' is not a Property Descriptor'
752
			);
753
		});
754
755
		t.equal(ES.IsDataDescriptor(), false, 'no value is not a Data Descriptor');
756
		t.equal(ES.IsDataDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
757
758
		t.equal(ES.IsDataDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a Data Descriptor');
759
		t.equal(ES.IsDataDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a Data Descriptor');
760
		t.equal(ES.IsDataDescriptor(v.dataDescriptor()), true, 'data descriptor is a Data Descriptor');
761
		t.equal(ES.IsDataDescriptor(v.genericDescriptor()), false, 'generic descriptor is not a Data Descriptor');
762
763
		t.end();
764
	});
765
766
	test('IsGenericDescriptor', function (t) {
767
		forEach(v.nonUndefinedPrimitives, function (primitive) {
768
			t['throws'](
769
				function () { ES.IsGenericDescriptor(primitive); },
770
				TypeError,
771
				debug(primitive) + ' is not a Property Descriptor'
772
			);
773
		});
774
775
		t.equal(ES.IsGenericDescriptor(), false, 'no value is not a Data Descriptor');
776
		t.equal(ES.IsGenericDescriptor(undefined), false, 'undefined value is not a Data Descriptor');
777
778
		t.equal(ES.IsGenericDescriptor(v.accessorDescriptor()), false, 'accessor descriptor is not a generic Descriptor');
779
		t.equal(ES.IsGenericDescriptor(v.mutatorDescriptor()), false, 'mutator descriptor is not a generic Descriptor');
780
		t.equal(ES.IsGenericDescriptor(v.dataDescriptor()), false, 'data descriptor is not a generic Descriptor');
781
782
		t.equal(ES.IsGenericDescriptor(v.genericDescriptor()), true, 'generic descriptor is a generic Descriptor');
783
784
		t.end();
785
	});
786
787
	test('FromPropertyDescriptor', function (t) {
788
		t.equal(ES.FromPropertyDescriptor(), undefined, 'no value begets undefined');
789
		t.equal(ES.FromPropertyDescriptor(undefined), undefined, 'undefined value begets undefined');
790
791
		forEach(v.nonUndefinedPrimitives, function (primitive) {
792
			t['throws'](
793
				function () { ES.FromPropertyDescriptor(primitive); },
794
				TypeError,
795
				debug(primitive) + ' is not a Property Descriptor'
796
			);
797
		});
798
799
		var accessor = v.accessorDescriptor();
800
		t.deepEqual(ES.FromPropertyDescriptor(accessor), {
801
			get: accessor['[[Get]]'],
802
			enumerable: !!accessor['[[Enumerable]]'],
803
			configurable: !!accessor['[[Configurable]]']
804
		});
805
806
		var mutator = v.mutatorDescriptor();
807
		t.deepEqual(ES.FromPropertyDescriptor(mutator), {
808
			set: mutator['[[Set]]'],
809
			enumerable: !!mutator['[[Enumerable]]'],
810
			configurable: !!mutator['[[Configurable]]']
811
		});
812
		var data = v.dataDescriptor();
813
		t.deepEqual(ES.FromPropertyDescriptor(data), {
814
			value: data['[[Value]]'],
815
			writable: data['[[Writable]]']
816
		});
817
818
		t.deepEqual(ES.FromPropertyDescriptor(v.genericDescriptor()), {
819
			enumerable: false,
820
			configurable: true
821
		});
822
823
		t.end();
824
	});
825
826
	test('ToPropertyDescriptor', function (t) {
827
		forEach(v.nonUndefinedPrimitives, function (primitive) {
828
			t['throws'](
829
				function () { ES.ToPropertyDescriptor(primitive); },
830
				TypeError,
831
				debug(primitive) + ' is not an Object'
832
			);
833
		});
834
835
		var accessor = v.accessorDescriptor();
836
		t.deepEqual(ES.ToPropertyDescriptor({
837
			get: accessor['[[Get]]'],
838
			enumerable: !!accessor['[[Enumerable]]'],
839
			configurable: !!accessor['[[Configurable]]']
840
		}), accessor);
841
842
		var mutator = v.mutatorDescriptor();
843
		t.deepEqual(ES.ToPropertyDescriptor({
844
			set: mutator['[[Set]]'],
845
			enumerable: !!mutator['[[Enumerable]]'],
846
			configurable: !!mutator['[[Configurable]]']
847
		}), mutator);
848
849
		var data = v.dataDescriptor();
850
		t.deepEqual(ES.ToPropertyDescriptor({
851
			value: data['[[Value]]'],
852
			writable: data['[[Writable]]'],
853
			configurable: !!data['[[Configurable]]']
854
		}), assign(data, { '[[Configurable]]': false }));
855
856
		var both = v.bothDescriptor();
857
		t['throws'](
858
			function () {
859
				ES.FromPropertyDescriptor({ get: both['[[Get]]'], value: both['[[Value]]'] });
860
			},
861
			TypeError,
862
			'data and accessor descriptors are mutually exclusive'
863
		);
864
865
		t.end();
866
	});
867
868
	test('CompletePropertyDescriptor', function (t) {
869
		forEach(v.nonUndefinedPrimitives, function (primitive) {
870
			t['throws'](
871
				function () { ES.CompletePropertyDescriptor(primitive); },
872
				TypeError,
873
				debug(primitive) + ' is not a Property Descriptor'
874
			);
875
		});
876
877
		var generic = v.genericDescriptor();
878
		t.deepEqual(
879
			ES.CompletePropertyDescriptor(generic),
880
			{
881
				'[[Configurable]]': !!generic['[[Configurable]]'],
882
				'[[Enumerable]]': !!generic['[[Enumerable]]'],
883
				'[[Value]]': undefined,
884
				'[[Writable]]': false
885
			},
886
			'completes a Generic Descriptor'
887
		);
888
889
		var data = v.dataDescriptor();
890
		t.deepEqual(
891
			ES.CompletePropertyDescriptor(data),
892
			{
893
				'[[Configurable]]': !!data['[[Configurable]]'],
894
				'[[Enumerable]]': false,
895
				'[[Value]]': data['[[Value]]'],
896
				'[[Writable]]': !!data['[[Writable]]']
897
			},
898
			'completes a Data Descriptor'
899
		);
900
901
		var accessor = v.accessorDescriptor();
902
		t.deepEqual(
903
			ES.CompletePropertyDescriptor(accessor),
904
			{
905
				'[[Get]]': accessor['[[Get]]'],
906
				'[[Enumerable]]': !!accessor['[[Enumerable]]'],
907
				'[[Configurable]]': !!accessor['[[Configurable]]'],
908
				'[[Set]]': undefined
909
			},
910
			'completes an Accessor Descriptor'
911
		);
912
913
		var mutator = v.mutatorDescriptor();
914
		t.deepEqual(
915
			ES.CompletePropertyDescriptor(mutator),
916
			{
917
				'[[Set]]': mutator['[[Set]]'],
918
				'[[Enumerable]]': !!mutator['[[Enumerable]]'],
919
				'[[Configurable]]': !!mutator['[[Configurable]]'],
920
				'[[Get]]': undefined
921
			},
922
			'completes a mutator Descriptor'
923
		);
924
925
		t['throws'](
926
			function () { ES.CompletePropertyDescriptor(v.bothDescriptor()); },
927
			TypeError,
928
			'data and accessor descriptors are mutually exclusive'
929
		);
930
931
		t.end();
932
	});
933
934
	test('Set', function (t) {
935
		forEach(v.primitives, function (primitive) {
936
			t['throws'](
937
				function () { ES.Set(primitive, '', null, false); },
938
				TypeError,
939
				debug(primitive) + ' is not an Object'
940
			);
941
		});
942
943
		forEach(v.nonPropertyKeys, function (nonKey) {
944
			t['throws'](
945
				function () { ES.Set({}, nonKey, null, false); },
946
				TypeError,
947
				debug(nonKey) + ' is not a Property Key'
948
			);
949
		});
950
951
		forEach(v.nonBooleans, function (nonBoolean) {
952
			t['throws'](
953
				function () { ES.Set({}, '', null, nonBoolean); },
954
				TypeError,
955
				debug(nonBoolean) + ' is not a Boolean'
956
			);
957
		});
958
959
		var o = {};
960
		var value = {};
961
		ES.Set(o, 'key', value, true);
962
		t.deepEqual(o, { key: value }, 'key is set');
963
964
		t.test('nonwritable', { skip: !Object.defineProperty }, function (st) {
965
			var obj = { a: value };
966
			Object.defineProperty(obj, 'a', { writable: false });
967
968
			st['throws'](
969
				function () { ES.Set(obj, 'a', value, true); },
970
				TypeError,
971
				'can not Set nonwritable property'
972
			);
973
974
			st.doesNotThrow(
975
				function () { ES.Set(obj, 'a', value, false); },
976
				'setting Throw to false prevents an exception'
977
			);
978
979
			st.end();
980
		});
981
982
		t.test('nonconfigurable', { skip: !Object.defineProperty }, function (st) {
983
			var obj = { a: value };
984
			Object.defineProperty(obj, 'a', { configurable: false });
985
986
			ES.Set(obj, 'a', value, true);
987
			st.deepEqual(obj, { a: value }, 'key is set');
988
989
			st.end();
990
		});
991
992
		t.end();
993
	});
994
995
	test('HasOwnProperty', function (t) {
996
		forEach(v.primitives, function (primitive) {
997
			t['throws'](
998
				function () { ES.HasOwnProperty(primitive, 'key'); },
999
				TypeError,
1000
				debug(primitive) + ' is not an Object'
1001
			);
1002
		});
1003
1004
		forEach(v.nonPropertyKeys, function (nonKey) {
1005
			t['throws'](
1006
				function () { ES.HasOwnProperty({}, nonKey); },
1007
				TypeError,
1008
				debug(nonKey) + ' is not a Property Key'
1009
			);
1010
		});
1011
1012
		t.equal(ES.HasOwnProperty({}, 'toString'), false, 'inherited properties are not own');
1013
		t.equal(
1014
			ES.HasOwnProperty({ toString: 1 }, 'toString'),
1015
			true,
1016
			'shadowed inherited own properties are own'
1017
		);
1018
		t.equal(ES.HasOwnProperty({ a: 1 }, 'a'), true, 'own properties are own');
1019
1020
		t.end();
1021
	});
1022
1023
	test('HasProperty', function (t) {
1024
		forEach(v.primitives, function (primitive) {
1025
			t['throws'](
1026
				function () { ES.HasProperty(primitive, 'key'); },
1027
				TypeError,
1028
				debug(primitive) + ' is not an Object'
1029
			);
1030
		});
1031
1032
		forEach(v.nonPropertyKeys, function (nonKey) {
1033
			t['throws'](
1034
				function () { ES.HasProperty({}, nonKey); },
1035
				TypeError,
1036
				debug(nonKey) + ' is not a Property Key'
1037
			);
1038
		});
1039
1040
		t.equal(ES.HasProperty({}, 'nope'), false, 'object does not have nonexistent properties');
1041
		t.equal(ES.HasProperty({}, 'toString'), true, 'object has inherited properties');
1042
		t.equal(
1043
			ES.HasProperty({ toString: 1 }, 'toString'),
1044
			true,
1045
			'object has shadowed inherited own properties'
1046
		);
1047
		t.equal(ES.HasProperty({ a: 1 }, 'a'), true, 'object has own properties');
1048
1049
		t.end();
1050
	});
1051
1052
	test('IsConcatSpreadable', function (t) {
1053
		forEach(v.primitives, function (primitive) {
1054
			t.equal(ES.IsConcatSpreadable(primitive), false, debug(primitive) + ' is not an Object');
1055
		});
1056
1057
		var hasSymbolConcatSpreadable = v.hasSymbols && Symbol.isConcatSpreadable;
1058
		t.test('Symbol.isConcatSpreadable', { skip: !hasSymbolConcatSpreadable }, function (st) {
1059
			forEach(v.falsies, function (falsy) {
1060
				var obj = {};
1061
				obj[Symbol.isConcatSpreadable] = falsy;
1062
				st.equal(
1063
					ES.IsConcatSpreadable(obj),
1064
					false,
1065
					'an object with ' + debug(falsy) + ' as Symbol.isConcatSpreadable is not concat spreadable'
1066
				);
1067
			});
1068
1069
			forEach(v.truthies, function (truthy) {
1070
				var obj = {};
1071
				obj[Symbol.isConcatSpreadable] = truthy;
1072
				st.equal(
1073
					ES.IsConcatSpreadable(obj),
1074
					true,
1075
					'an object with ' + debug(truthy) + ' as Symbol.isConcatSpreadable is concat spreadable'
1076
				);
1077
			});
1078
1079
			st.end();
1080
		});
1081
1082
		forEach(v.objects, function (object) {
1083
			t.equal(
1084
				ES.IsConcatSpreadable(object),
1085
				false,
1086
				'non-array without Symbol.isConcatSpreadable is not concat spreadable'
1087
			);
1088
		});
1089
1090
		t.equal(ES.IsConcatSpreadable([]), true, 'arrays are concat spreadable');
1091
1092
		t.end();
1093
	});
1094
1095
	test('Invoke', function (t) {
1096
		forEach(v.nonPropertyKeys, function (nonKey) {
1097
			t['throws'](
1098
				function () { ES.Invoke({}, nonKey); },
1099
				TypeError,
1100
				debug(nonKey) + ' is not a Property Key'
1101
			);
1102
		});
1103
1104
		t['throws'](function () { ES.Invoke({ o: false }, 'o'); }, TypeError, 'fails on a non-function');
1105
1106
		t.test('invoked callback', function (st) {
1107
			var aValue = {};
1108
			var bValue = {};
1109
			var obj = {
1110
				f: function (a) {
1111
					st.equal(arguments.length, 2, '2 args passed');
1112
					st.equal(a, aValue, 'first arg is correct');
1113
					st.equal(arguments[1], bValue, 'second arg is correct');
1114
				}
1115
			};
1116
			st.plan(3);
1117
			ES.Invoke(obj, 'f', aValue, bValue);
1118
		});
1119
1120
		t.end();
1121
	});
1122
1123
	test('GetIterator', { skip: true });
1124
1125
	test('IteratorNext', { skip: true });
1126
1127
	test('IteratorComplete', { skip: true });
1128
1129
	test('IteratorValue', { skip: true });
1130
1131
	test('IteratorStep', { skip: true });
1132
1133
	test('IteratorClose', { skip: true });
1134
1135
	test('CreateIterResultObject', function (t) {
1136
		forEach(v.nonBooleans, function (nonBoolean) {
1137
			t['throws'](
1138
				function () { ES.CreateIterResultObject({}, nonBoolean); },
1139
				TypeError,
1140
				'"done" argument must be a boolean; ' + debug(nonBoolean) + ' is not'
1141
			);
1142
		});
1143
1144
		var value = {};
1145
		t.deepEqual(
1146
			ES.CreateIterResultObject(value, true),
1147
			{ value: value, done: true },
1148
			'creates a "done" iteration result'
1149
		);
1150
		t.deepEqual(
1151
			ES.CreateIterResultObject(value, false),
1152
			{ value: value, done: false },
1153
			'creates a "not done" iteration result'
1154
		);
1155
1156
		t.end();
1157
	});
1158
1159
	test('RegExpExec', function (t) {
1160
		forEach(v.primitives, function (primitive) {
1161
			t['throws'](
1162
				function () { ES.RegExpExec(primitive); },
1163
				TypeError,
1164
				'"R" argument must be an object; ' + debug(primitive) + ' is not'
1165
			);
1166
		});
1167
1168
		forEach(v.nonStrings, function (nonString) {
1169
			t['throws'](
1170
				function () { ES.RegExpExec({}, nonString); },
1171
				TypeError,
1172
				'"S" argument must be a String; ' + debug(nonString) + ' is not'
1173
			);
1174
		});
1175
1176
		t.test('gets and calls a callable "exec"', function (st) {
1177
			var str = '123';
1178
			var o = {
1179
				exec: function (S) {
1180
					st.equal(this, o, '"exec" receiver is R');
1181
					st.equal(S, str, '"exec" argument is S');
1182
1183
					return null;
1184
				}
1185
			};
1186
			st.plan(2);
1187
			ES.RegExpExec(o, str);
1188
			st.end();
1189
		});
1190
1191
		t.test('throws if a callable "exec" returns a non-null non-object', function (st) {
1192
			var str = '123';
1193
			st.plan(v.nonNullPrimitives.length);
1194
			forEach(v.nonNullPrimitives, function (nonNullPrimitive) {
1195
				st['throws'](
1196
					function () { ES.RegExpExec({ exec: function () { return nonNullPrimitive; } }, str); },
1197
					TypeError,
1198
					'"exec" method must return `null` or an Object; ' + debug(nonNullPrimitive) + ' is not'
1199
				);
1200
			});
1201
			st.end();
1202
		});
1203
1204
		t.test('actual regex that should match against a string', function (st) {
1205
			var S = 'aabc';
1206
			var R = /a/g;
1207
			var match1 = ES.RegExpExec(R, S);
1208
			var match2 = ES.RegExpExec(R, S);
1209
			var match3 = ES.RegExpExec(R, S);
1210
			st.deepEqual(match1, assign(['a'], groups({ index: 0, input: S })), 'match object 1 is as expected');
1211
			st.deepEqual(match2, assign(['a'], groups({ index: 1, input: S })), 'match object 2 is as expected');
1212
			st.equal(match3, null, 'match 3 is null as expected');
1213
			st.end();
1214
		});
1215
1216
		t.test('actual regex that should match against a string, with shadowed "exec"', function (st) {
1217
			var S = 'aabc';
1218
			var R = /a/g;
1219
			R.exec = undefined;
1220
			var match1 = ES.RegExpExec(R, S);
1221
			var match2 = ES.RegExpExec(R, S);
1222
			var match3 = ES.RegExpExec(R, S);
1223
			st.deepEqual(match1, assign(['a'], groups({ index: 0, input: S })), 'match object 1 is as expected');
1224
			st.deepEqual(match2, assign(['a'], groups({ index: 1, input: S })), 'match object 2 is as expected');
1225
			st.equal(match3, null, 'match 3 is null as expected');
1226
			st.end();
1227
		});
1228
		t.end();
1229
	});
1230
1231
	test('ArraySpeciesCreate', function (t) {
1232
		t.test('errors', function (st) {
1233
			var testNonNumber = function (nonNumber) {
1234
				st['throws'](
1235
					function () { ES.ArraySpeciesCreate([], nonNumber); },
1236
					TypeError,
1237
					debug(nonNumber) + ' is not a number'
1238
				);
1239
			};
1240
			forEach(v.nonNumbers, testNonNumber);
1241
1242
			st['throws'](
1243
				function () { ES.ArraySpeciesCreate([], -1); },
1244
				TypeError,
1245
				'-1 is not >= 0'
1246
			);
1247
			st['throws'](
1248
				function () { ES.ArraySpeciesCreate([], -Infinity); },
1249
				TypeError,
1250
				'-Infinity is not >= 0'
1251
			);
1252
1253
			var testNonIntegers = function (nonInteger) {
1254
				st['throws'](
1255
					function () { ES.ArraySpeciesCreate([], nonInteger); },
1256
					TypeError,
1257
					debug(nonInteger) + ' is not an integer'
1258
				);
1259
			};
1260
			forEach(v.nonIntegerNumbers, testNonIntegers);
1261
1262
			st.end();
1263
		});
1264
1265
		t.test('works with a non-array', function (st) {
1266
			forEach(v.objects.concat(v.primitives), function (nonArray) {
1267
				var arr = ES.ArraySpeciesCreate(nonArray, 0);
1268
				st.ok(ES.IsArray(arr), 'is an array');
1269
				st.equal(arr.length, 0, 'length is correct');
1270
				st.equal(arr.constructor, Array, 'constructor is correct');
1271
			});
1272
1273
			st.end();
1274
		});
1275
1276
		t.test('works with a normal array', function (st) {
1277
			var len = 2;
1278
			var orig = [1, 2, 3];
1279
			var arr = ES.ArraySpeciesCreate(orig, len);
1280
1281
			st.ok(ES.IsArray(arr), 'is an array');
1282
			st.equal(arr.length, len, 'length is correct');
1283
			st.equal(arr.constructor, orig.constructor, 'constructor is correct');
1284
1285
			st.end();
1286
		});
1287
1288
		t.test('-0 length produces +0 length', function (st) {
1289
			var len = -0;
1290
			st.ok(is(len, -0), '-0 is negative zero');
1291
			st.notOk(is(len, 0), '-0 is not positive zero');
1292
1293
			var orig = [1, 2, 3];
1294
			var arr = ES.ArraySpeciesCreate(orig, len);
1295
1296
			st.equal(ES.IsArray(arr), true);
1297
			st.ok(is(arr.length, 0));
1298
			st.equal(arr.constructor, orig.constructor);
1299
1300
			st.end();
1301
		});
1302
1303
		t.test('works with species construtor', { skip: !hasSpecies }, function (st) {
1304
			var sentinel = {};
1305
			var Foo = function Foo(len) {
1306
				this.length = len;
1307
				this.sentinel = sentinel;
1308
			};
1309
			var Bar = getArraySubclassWithSpeciesConstructor(Foo);
1310
			var bar = new Bar();
1311
1312
			t.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1313
1314
			var arr = ES.ArraySpeciesCreate(bar, 3);
1315
			st.equal(arr.constructor, Foo, 'result used species constructor');
1316
			st.equal(arr.length, 3, 'length property is correct');
1317
			st.equal(arr.sentinel, sentinel, 'Foo constructor was exercised');
1318
1319
			st.end();
1320
		});
1321
1322
		t.test('works with null species constructor', { skip: !hasSpecies }, function (st) {
1323
			var Bar = getArraySubclassWithSpeciesConstructor(null);
1324
			var bar = new Bar();
1325
1326
			t.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1327
1328
			var arr = ES.ArraySpeciesCreate(bar, 3);
1329
			st.equal(arr.constructor, Array, 'result used default constructor');
1330
			st.equal(arr.length, 3, 'length property is correct');
1331
1332
			st.end();
1333
		});
1334
1335
		t.test('works with undefined species constructor', { skip: !hasSpecies }, function (st) {
1336
			var Bar = getArraySubclassWithSpeciesConstructor();
1337
			var bar = new Bar();
1338
1339
			t.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1340
1341
			var arr = ES.ArraySpeciesCreate(bar, 3);
1342
			st.equal(arr.constructor, Array, 'result used default constructor');
1343
			st.equal(arr.length, 3, 'length property is correct');
1344
1345
			st.end();
1346
		});
1347
1348
		t.test('throws with object non-construtor species constructor', { skip: !hasSpecies }, function (st) {
1349
			forEach(v.objects, function (obj) {
1350
				var Bar = getArraySubclassWithSpeciesConstructor(obj);
1351
				var bar = new Bar();
1352
1353
				st.equal(ES.IsArray(bar), true, 'Bar instance is an array');
1354
1355
				st['throws'](
1356
					function () { ES.ArraySpeciesCreate(bar, 3); },
1357
					TypeError,
1358
					debug(obj) + ' is not a constructor'
1359
				);
1360
			});
1361
1362
			st.end();
1363
		});
1364
1365
		t.end();
1366
	});
1367
1368
	test('CreateDataProperty', function (t) {
1369
		forEach(v.primitives, function (primitive) {
1370
			t['throws'](
1371
				function () { ES.CreateDataProperty(primitive); },
1372
				TypeError,
1373
				debug(primitive) + ' is not an object'
1374
			);
1375
		});
1376
1377
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1378
			t['throws'](
1379
				function () { ES.CreateDataProperty({}, nonPropertyKey); },
1380
				TypeError,
1381
				debug(nonPropertyKey) + ' is not a property key'
1382
			);
1383
		});
1384
1385
		var sentinel = {};
1386
		forEach(v.propertyKeys, function (propertyKey) {
1387
			var obj = {};
1388
			var status = ES.CreateDataProperty(obj, propertyKey, sentinel);
1389
			t.equal(status, true, 'status is true');
1390
			t.equal(
1391
				obj[propertyKey],
1392
				sentinel,
1393
				debug(sentinel) + ' is installed on "' + debug(propertyKey) + '" on the object'
1394
			);
1395
1396
			if (typeof Object.defineProperty === 'function') {
1397
				var nonWritable = Object.defineProperty({}, propertyKey, { configurable: true, writable: false });
1398
1399
				var nonWritableStatus = ES.CreateDataProperty(nonWritable, propertyKey, sentinel);
1400
				t.equal(nonWritableStatus, false, 'create data property failed');
1401
				t.notEqual(
1402
					nonWritable[propertyKey],
1403
					sentinel,
1404
					debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object when key is nonwritable'
1405
				);
1406
1407
				var nonConfigurable = Object.defineProperty({}, propertyKey, { configurable: false, writable: true });
1408
1409
				var nonConfigurableStatus = ES.CreateDataProperty(nonConfigurable, propertyKey, sentinel);
1410
				t.equal(nonConfigurableStatus, false, 'create data property failed');
1411
				t.notEqual(
1412
					nonConfigurable[propertyKey],
1413
					sentinel,
1414
					debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object when key is nonconfigurable'
1415
				);
1416
			}
1417
		});
1418
1419
		t.end();
1420
	});
1421
1422
	test('CreateDataPropertyOrThrow', function (t) {
1423
		forEach(v.primitives, function (primitive) {
1424
			t['throws'](
1425
				function () { ES.CreateDataPropertyOrThrow(primitive); },
1426
				TypeError,
1427
				debug(primitive) + ' is not an object'
1428
			);
1429
		});
1430
1431
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1432
			t['throws'](
1433
				function () { ES.CreateDataPropertyOrThrow({}, nonPropertyKey); },
1434
				TypeError,
1435
				debug(nonPropertyKey) + ' is not a property key'
1436
			);
1437
		});
1438
1439
		var sentinel = {};
1440
		forEach(v.propertyKeys, function (propertyKey) {
1441
			var obj = {};
1442
			var status = ES.CreateDataPropertyOrThrow(obj, propertyKey, sentinel);
1443
			t.equal(status, true, 'status is true');
1444
			t.equal(
1445
				obj[propertyKey],
1446
				sentinel,
1447
				debug(sentinel) + ' is installed on "' + debug(propertyKey) + '" on the object'
1448
			);
1449
1450
			if (typeof Object.preventExtensions === 'function') {
1451
				var notExtensible = {};
1452
				Object.preventExtensions(notExtensible);
1453
1454
				t['throws'](
1455
					function () { ES.CreateDataPropertyOrThrow(notExtensible, propertyKey, sentinel); },
1456
					TypeError,
1457
					'can not install ' + debug(propertyKey) + ' on non-extensible object'
1458
				);
1459
				t.notEqual(
1460
					notExtensible[propertyKey],
1461
					sentinel,
1462
					debug(sentinel) + ' is not installed on "' + debug(propertyKey) + '" on the object'
1463
				);
1464
			}
1465
		});
1466
1467
		t.end();
1468
	});
1469
1470
	test('ObjectCreate', function (t) {
1471
		forEach(v.nonNullPrimitives, function (value) {
1472
			t['throws'](
1473
				function () { ES.ObjectCreate(value); },
1474
				TypeError,
1475
				debug(value) + ' is not null, or an object'
1476
			);
1477
		});
1478
1479
		t.test('proto arg', function (st) {
1480
			var Parent = function Parent() {};
1481
			Parent.prototype.foo = {};
1482
			var child = ES.ObjectCreate(Parent.prototype);
1483
			st.equal(child instanceof Parent, true, 'child is instanceof Parent');
1484
			st.equal(child.foo, Parent.prototype.foo, 'child inherits properties from Parent.prototype');
1485
1486
			st.end();
1487
		});
1488
1489
		t.test('internal slots arg', function (st) {
1490
			st.doesNotThrow(function () { ES.ObjectCreate(null, []); }, 'an empty slot list is valid');
1491
1492
			st['throws'](
1493
				function () { ES.ObjectCreate(null, ['a']); },
1494
				SyntaxError,
1495
				'internal slots are not supported'
1496
			);
1497
1498
			st.end();
1499
		});
1500
1501
		t.test('null proto', { skip: !Object.create }, function (st) {
1502
			st.equal('toString' in ({}), true, 'normal objects have toString');
1503
			st.equal('toString' in ES.ObjectCreate(null), false, 'makes a null object');
1504
1505
			st.end();
1506
		});
1507
1508
		t.test('null proto when no native Object.create', { skip: Object.create }, function (st) {
1509
			st['throws'](
1510
				function () { ES.ObjectCreate(null); },
1511
				SyntaxError,
1512
				'without a native Object.create, can not create null objects'
1513
			);
1514
1515
			st.end();
1516
		});
1517
1518
		t.end();
1519
	});
1520
1521
	test('AdvanceStringIndex', function (t) {
1522
		forEach(v.nonStrings, function (nonString) {
1523
			t['throws'](
1524
				function () { ES.AdvanceStringIndex(nonString); },
1525
				TypeError,
1526
				'"S" argument must be a String; ' + debug(nonString) + ' is not'
1527
			);
1528
		});
1529
1530
		var notInts = v.nonNumbers.concat(
1531
			v.nonIntegerNumbers,
1532
			[Infinity, -Infinity, NaN, [], new Date(), Math.pow(2, 53), -1]
1533
		);
1534
		forEach(notInts, function (nonInt) {
1535
			t['throws'](
1536
				function () { ES.AdvanceStringIndex('abc', nonInt); },
1537
				TypeError,
1538
				'"index" argument must be an integer, ' + debug(nonInt) + ' is not.'
1539
			);
1540
		});
1541
1542
		forEach(v.nonBooleans, function (nonBoolean) {
1543
			t['throws'](
1544
				function () { ES.AdvanceStringIndex('abc', 0, nonBoolean); },
1545
				TypeError,
1546
				debug(nonBoolean) + ' is not a Boolean'
1547
			);
1548
		});
1549
1550
		var str = 'a\uD83D\uDCA9c';
1551
1552
		t.test('non-unicode mode', function (st) {
1553
			for (var i = 0; i < str.length + 2; i += 1) {
1554
				st.equal(ES.AdvanceStringIndex(str, i, false), i + 1, i + ' advances to ' + (i + 1));
1555
			}
1556
1557
			st.end();
1558
		});
1559
1560
		t.test('unicode mode', function (st) {
1561
			st.equal(ES.AdvanceStringIndex(str, 0, true), 1, '0 advances to 1');
1562
			st.equal(ES.AdvanceStringIndex(str, 1, true), 3, '1 advances to 3');
1563
			st.equal(ES.AdvanceStringIndex(str, 2, true), 3, '2 advances to 3');
1564
			st.equal(ES.AdvanceStringIndex(str, 3, true), 4, '3 advances to 4');
1565
			st.equal(ES.AdvanceStringIndex(str, 4, true), 5, '4 advances to 5');
1566
1567
			st.end();
1568
		});
1569
1570
		t.test('lone surrogates', function (st) {
1571
			var halfPoo = 'a\uD83Dc';
1572
1573
			st.equal(ES.AdvanceStringIndex(halfPoo, 0, true), 1, '0 advances to 1');
1574
			st.equal(ES.AdvanceStringIndex(halfPoo, 1, true), 2, '1 advances to 2');
1575
			st.equal(ES.AdvanceStringIndex(halfPoo, 2, true), 3, '2 advances to 3');
1576
			st.equal(ES.AdvanceStringIndex(halfPoo, 3, true), 4, '3 advances to 4');
1577
1578
			st.end();
1579
		});
1580
1581
		t.test('surrogate pairs', function (st) {
1582
			var lowestPair = String.fromCharCode('0xD800') + String.fromCharCode('0xDC00');
1583
			var highestPair = String.fromCharCode('0xDBFF') + String.fromCharCode('0xDFFF');
1584
			var poop = String.fromCharCode('0xD83D') + String.fromCharCode('0xDCA9');
1585
1586
			st.equal(ES.AdvanceStringIndex(lowestPair, 0, true), 2, 'lowest surrogate pair, 0 -> 2');
1587
			st.equal(ES.AdvanceStringIndex(highestPair, 0, true), 2, 'highest surrogate pair, 0 -> 2');
1588
			st.equal(ES.AdvanceStringIndex(poop, 0, true), 2, 'poop, 0 -> 2');
1589
1590
			st.end();
1591
		});
1592
1593
		t.end();
1594
	});
1595
1596
	test('CreateMethodProperty', function (t) {
1597
		forEach(v.primitives, function (primitive) {
1598
			t['throws'](
1599
				function () { ES.CreateMethodProperty(primitive, 'key'); },
1600
				TypeError,
1601
				'O must be an Object'
1602
			);
1603
		});
1604
1605
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1606
			t['throws'](
1607
				function () { ES.CreateMethodProperty({}, nonPropertyKey); },
1608
				TypeError,
1609
				debug(nonPropertyKey) + ' is not a Property Key'
1610
			);
1611
		});
1612
1613
		t.test('defines correctly', function (st) {
1614
			var obj = {};
1615
			var key = 'the key';
1616
			var value = { foo: 'bar' };
1617
1618
			st.equal(ES.CreateMethodProperty(obj, key, value), true, 'defines property successfully');
1619
			st.test('property descriptor', { skip: !Object.getOwnPropertyDescriptor }, function (s2t) {
1620
				s2t.deepEqual(
1621
					Object.getOwnPropertyDescriptor(obj, key),
1622
					{
1623
						configurable: true,
1624
						enumerable: false,
1625
						value: value,
1626
						writable: true
1627
					},
1628
					'sets the correct property descriptor'
1629
				);
1630
1631
				s2t.end();
1632
			});
1633
			st.equal(obj[key], value, 'sets the correct value');
1634
1635
			st.end();
1636
		});
1637
1638
		t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1639
			var obj = Object.freeze({ foo: 'bar' });
1640
			st['throws'](
1641
				function () { ES.CreateMethodProperty(obj, 'foo', { value: 'baz' }); },
1642
				TypeError,
1643
				'nonconfigurable key can not be defined'
1644
			);
1645
1646
			st.end();
1647
		});
1648
1649
		var hasNonConfigurableFunctionName = !Object.getOwnPropertyDescriptor
1650
			|| !Object.getOwnPropertyDescriptor(function () {}, 'name').configurable;
1651
		t.test('fails as expected on a function with a nonconfigurable name', { skip: !hasNonConfigurableFunctionName }, function (st) {
1652
			st['throws'](
1653
				function () { ES.CreateMethodProperty(function () {}, 'name', { value: 'baz' }); },
1654
				TypeError,
1655
				'nonconfigurable function name can not be defined'
1656
			);
1657
			st.end();
1658
		});
1659
1660
		t.end();
1661
	});
1662
1663
	test('DefinePropertyOrThrow', function (t) {
1664
		forEach(v.primitives, function (primitive) {
1665
			t['throws'](
1666
				function () { ES.DefinePropertyOrThrow(primitive, 'key', {}); },
1667
				TypeError,
1668
				'O must be an Object'
1669
			);
1670
		});
1671
1672
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1673
			t['throws'](
1674
				function () { ES.DefinePropertyOrThrow({}, nonPropertyKey, {}); },
1675
				TypeError,
1676
				debug(nonPropertyKey) + ' is not a Property Key'
1677
			);
1678
		});
1679
1680
		t.test('defines correctly', function (st) {
1681
			var obj = {};
1682
			var key = 'the key';
1683
			var descriptor = {
1684
				configurable: true,
1685
				enumerable: false,
1686
				value: { foo: 'bar' },
1687
				writable: true
1688
			};
1689
1690
			st.equal(ES.DefinePropertyOrThrow(obj, key, descriptor), true, 'defines property successfully');
1691
			st.test('property descriptor', { skip: !Object.getOwnPropertyDescriptor }, function (s2t) {
1692
				s2t.deepEqual(
1693
					Object.getOwnPropertyDescriptor(obj, key),
1694
					descriptor,
1695
					'sets the correct property descriptor'
1696
				);
1697
1698
				s2t.end();
1699
			});
1700
			st.deepEqual(obj[key], descriptor.value, 'sets the correct value');
1701
1702
			st.end();
1703
		});
1704
1705
		t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1706
			var obj = Object.freeze({ foo: 'bar' });
1707
			st['throws'](
1708
				function () {
1709
					ES.DefinePropertyOrThrow(obj, 'foo', { configurable: true, value: 'baz' });
1710
				},
1711
				TypeError,
1712
				'nonconfigurable key can not be defined'
1713
			);
1714
1715
			st.end();
1716
		});
1717
1718
		var hasNonConfigurableFunctionName = !Object.getOwnPropertyDescriptor
1719
			|| !Object.getOwnPropertyDescriptor(function () {}, 'name').configurable;
1720
		t.test('fails as expected on a function with a nonconfigurable name', { skip: !hasNonConfigurableFunctionName }, function (st) {
1721
			st['throws'](
1722
				function () {
1723
					ES.DefinePropertyOrThrow(function () {}, 'name', { configurable: true, value: 'baz' });
1724
				},
1725
				TypeError,
1726
				'nonconfigurable function name can not be defined'
1727
			);
1728
			st.end();
1729
		});
1730
1731
		t.end();
1732
	});
1733
1734
	test('DeletePropertyOrThrow', function (t) {
1735
		forEach(v.primitives, function (primitive) {
1736
			t['throws'](
1737
				function () { ES.DeletePropertyOrThrow(primitive, 'key', {}); },
1738
				TypeError,
1739
				'O must be an Object'
1740
			);
1741
		});
1742
1743
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1744
			t['throws'](
1745
				function () { ES.DeletePropertyOrThrow({}, nonPropertyKey, {}); },
1746
				TypeError,
1747
				debug(nonPropertyKey) + ' is not a Property Key'
1748
			);
1749
		});
1750
1751
		t.test('defines correctly', function (st) {
1752
			var obj = { 'the key': 42 };
1753
			var key = 'the key';
1754
1755
			st.equal(ES.DeletePropertyOrThrow(obj, key), true, 'deletes property successfully');
1756
			st.equal(key in obj, false, 'key is no longer in the object');
1757
1758
			st.end();
1759
		});
1760
1761
		t.test('fails as expected on a frozen object', { skip: !Object.freeze }, function (st) {
1762
			var obj = Object.freeze({ foo: 'bar' });
1763
			st['throws'](
1764
				function () { ES.DeletePropertyOrThrow(obj, 'foo'); },
1765
				TypeError,
1766
				'nonconfigurable key can not be deleted'
1767
			);
1768
1769
			st.end();
1770
		});
1771
1772
		var hasNonConfigurableFunctionName = !Object.getOwnPropertyDescriptor
1773
			|| !Object.getOwnPropertyDescriptor(function () {}, 'name').configurable;
1774
		t.test('fails as expected on a function with a nonconfigurable name', { skip: !hasNonConfigurableFunctionName }, function (st) {
1775
			st['throws'](
1776
				function () { ES.DeletePropertyOrThrow(function () {}, 'name'); },
1777
				TypeError,
1778
				'nonconfigurable function name can not be deleted'
1779
			);
1780
			st.end();
1781
		});
1782
1783
		t.end();
1784
	});
1785
1786
	test('EnumerableOwnNames', { skip: skips && skips.EnumerableOwnNames }, function (t) {
1787
		var obj = testEnumerableOwnNames(t, function (O) { return ES.EnumerableOwnNames(O); });
1788
1789
		t.deepEqual(
1790
			ES.EnumerableOwnNames(obj),
1791
			['own'],
1792
			'returns enumerable own names'
1793
		);
1794
1795
		t.end();
1796
	});
1797
1798
	test('thisNumberValue', function (t) {
1799
		forEach(v.nonNumbers, function (nonNumber) {
1800
			t['throws'](
1801
				function () { ES.thisNumberValue(nonNumber); },
1802
				TypeError,
1803
				debug(nonNumber) + ' is not a Number'
1804
			);
1805
		});
1806
1807
		forEach(v.numbers, function (number) {
1808
			t.equal(ES.thisNumberValue(number), number, debug(number) + ' is its own thisNumberValue');
1809
			var obj = Object(number);
1810
			t.equal(ES.thisNumberValue(obj), number, debug(obj) + ' is the boxed thisNumberValue');
1811
		});
1812
1813
		t.end();
1814
	});
1815
1816
	test('thisBooleanValue', function (t) {
1817
		forEach(v.nonBooleans, function (nonBoolean) {
1818
			t['throws'](
1819
				function () { ES.thisBooleanValue(nonBoolean); },
1820
				TypeError,
1821
				debug(nonBoolean) + ' is not a Boolean'
1822
			);
1823
		});
1824
1825
		forEach(v.booleans, function (boolean) {
1826
			t.equal(ES.thisBooleanValue(boolean), boolean, debug(boolean) + ' is its own thisBooleanValue');
1827
			var obj = Object(boolean);
1828
			t.equal(ES.thisBooleanValue(obj), boolean, debug(obj) + ' is the boxed thisBooleanValue');
1829
		});
1830
1831
		t.end();
1832
	});
1833
1834
	test('thisStringValue', function (t) {
1835
		forEach(v.nonStrings, function (nonString) {
1836
			t['throws'](
1837
				function () { ES.thisStringValue(nonString); },
1838
				TypeError,
1839
				debug(nonString) + ' is not a String'
1840
			);
1841
		});
1842
1843
		forEach(v.strings, function (string) {
1844
			t.equal(ES.thisStringValue(string), string, debug(string) + ' is its own thisStringValue');
1845
			var obj = Object(string);
1846
			t.equal(ES.thisStringValue(obj), string, debug(obj) + ' is the boxed thisStringValue');
1847
		});
1848
1849
		t.end();
1850
	});
1851
1852
	test('thisTimeValue', function (t) {
1853
		forEach(v.primitives.concat(v.objects), function (nonDate) {
1854
			t['throws'](
1855
				function () { ES.thisTimeValue(nonDate); },
1856
				TypeError,
1857
				debug(nonDate) + ' is not a Date'
1858
			);
1859
		});
1860
1861
		forEach(v.timestamps, function (timestamp) {
1862
			var date = new Date(timestamp);
1863
1864
			t.equal(ES.thisTimeValue(date), timestamp, debug(date) + ' is its own thisTimeValue');
1865
		});
1866
1867
		t.end();
1868
	});
1869
1870
	test('SetIntegrityLevel', function (t) {
1871
		forEach(v.primitives, function (primitive) {
1872
			t['throws'](
1873
				function () { ES.SetIntegrityLevel(primitive); },
1874
				TypeError,
1875
				debug(primitive) + ' is not an Object'
1876
			);
1877
		});
1878
1879
		t['throws'](
1880
			function () { ES.SetIntegrityLevel({}); },
1881
			/^TypeError: Assertion failed: `level` must be `"sealed"` or `"frozen"`$/,
1882
			'`level` must be `"sealed"` or `"frozen"`'
1883
		);
1884
1885
		var O = { a: 1 };
1886
		t.equal(ES.SetIntegrityLevel(O, 'sealed'), true);
1887
		t['throws'](
1888
			function () { O.b = 2; },
1889
			/^TypeError: (Cannot|Can't) add property b, object is not extensible$/,
1890
			'sealing prevent new properties from being added'
1891
		);
1892
		O.a = 2;
1893
		t.equal(O.a, 2, 'pre-frozen, existing properties are mutable');
1894
1895
		t.equal(ES.SetIntegrityLevel(O, 'frozen'), true);
1896
		t['throws'](
1897
			function () { O.a = 3; },
1898
			/^TypeError: Cannot assign to read only property 'a' of /,
1899
			'freezing prevents existing properties from being mutated'
1900
		);
1901
1902
		t.end();
1903
	});
1904
1905
	test('TestIntegrityLevel', function (t) {
1906
		forEach(v.primitives, function (primitive) {
1907
			t['throws'](
1908
				function () { ES.TestIntegrityLevel(primitive); },
1909
				TypeError,
1910
				debug(primitive) + ' is not an Object'
1911
			);
1912
		});
1913
1914
		t['throws'](
1915
			function () { ES.TestIntegrityLevel({ a: 1 }); },
1916
			/^TypeError: Assertion failed: `level` must be `"sealed"` or `"frozen"`$/,
1917
			'`level` must be `"sealed"` or `"frozen"`'
1918
		);
1919
1920
		t.equal(ES.TestIntegrityLevel({ a: 1 }, 'sealed'), false, 'basic object is not sealed');
1921
		t.equal(ES.TestIntegrityLevel({ a: 1 }, 'frozen'), false, 'basic object is not frozen');
1922
1923
		t.test('preventExtensions', { skip: !Object.preventExtensions }, function (st) {
1924
			var o = Object.preventExtensions({ a: 1 });
1925
			st.equal(ES.TestIntegrityLevel(o, 'sealed'), false, 'nonextensible object is not sealed');
1926
			st.equal(ES.TestIntegrityLevel(o, 'frozen'), false, 'nonextensible object is not frozen');
1927
1928
			var empty = Object.preventExtensions({});
1929
			st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty nonextensible object is sealed');
1930
			st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty nonextensible object is frozen');
1931
			st.end();
1932
		});
1933
1934
		t.test('seal', { skip: !Object.seal }, function (st) {
1935
			var o = Object.seal({ a: 1 });
1936
			st.equal(ES.TestIntegrityLevel(o, 'sealed'), true, 'sealed object is sealed');
1937
			st.equal(ES.TestIntegrityLevel(o, 'frozen'), false, 'sealed object is not frozen');
1938
1939
			var empty = Object.seal({});
1940
			st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty sealed object is sealed');
1941
			st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty sealed object is frozen');
1942
1943
			st.end();
1944
		});
1945
1946
		t.test('freeze', { skip: !Object.freeze }, function (st) {
1947
			var o = Object.freeze({ a: 1 });
1948
			st.equal(ES.TestIntegrityLevel(o, 'sealed'), true, 'frozen object is sealed');
1949
			st.equal(ES.TestIntegrityLevel(o, 'frozen'), true, 'frozen object is frozen');
1950
1951
			var empty = Object.freeze({});
1952
			st.equal(ES.TestIntegrityLevel(empty, 'sealed'), true, 'empty frozen object is sealed');
1953
			st.equal(ES.TestIntegrityLevel(empty, 'frozen'), true, 'empty frozen object is frozen');
1954
1955
			st.end();
1956
		});
1957
1958
		t.end();
1959
	});
1960
1961
	test('OrdinaryHasInstance', function (t) {
1962
		forEach(v.nonFunctions, function (nonFunction) {
1963
			t.equal(ES.OrdinaryHasInstance(nonFunction, {}), false, debug(nonFunction) + ' is not callable');
1964
		});
1965
1966
		forEach(v.primitives, function (primitive) {
1967
			t.equal(ES.OrdinaryHasInstance(function () {}, primitive), false, debug(primitive) + ' is not an object');
1968
		});
1969
1970
		var C = function C() {};
1971
		var D = function D() {};
1972
		t.equal(ES.OrdinaryHasInstance(C, new C()), true, 'constructor function has an instance of itself');
1973
		t.equal(ES.OrdinaryHasInstance(C, new D()), false, 'constructor/instance mismatch is false');
1974
		t.equal(ES.OrdinaryHasInstance(D, new C()), false, 'instance/constructor mismatch is false');
1975
		t.equal(ES.OrdinaryHasInstance(C, {}), false, 'plain object is not an instance of a constructor');
1976
		t.equal(ES.OrdinaryHasInstance(Object, {}), true, 'plain object is an instance of Object');
1977
1978
		t.end();
1979
	});
1980
1981
	test('OrdinaryHasProperty', function (t) {
1982
		forEach(v.primitives, function (primitive) {
1983
			t['throws'](
1984
				function () { ES.OrdinaryHasProperty(primitive, ''); },
1985
				TypeError,
1986
				debug(primitive) + ' is not an object'
1987
			);
1988
		});
1989
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
1990
			t['throws'](
1991
				function () { ES.OrdinaryHasProperty({}, nonPropertyKey); },
1992
				TypeError,
1993
				'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
1994
			);
1995
		});
1996
1997
		t.equal(ES.OrdinaryHasProperty({ a: 1 }, 'a'), true, 'own property is true');
1998
		t.equal(ES.OrdinaryHasProperty({}, 'toString'), true, 'inherited property is true');
1999
		t.equal(ES.OrdinaryHasProperty({}, 'nope'), false, 'absent property is false');
2000
2001
		t.end();
2002
	});
2003
2004
	test('InstanceofOperator', function (t) {
2005
		forEach(v.primitives, function (primitive) {
2006
			t['throws'](
2007
				function () { ES.InstanceofOperator(primitive, function () {}); },
2008
				TypeError,
2009
				debug(primitive) + ' is not an object'
2010
			);
2011
		});
2012
2013
		forEach(v.nonFunctions, function (nonFunction) {
2014
			t['throws'](
2015
				function () { ES.InstanceofOperator({}, nonFunction); },
2016
				TypeError,
2017
				debug(nonFunction) + ' is not callable'
2018
			);
2019
		});
2020
2021
		var C = function C() {};
2022
		var D = function D() {};
2023
2024
		t.equal(ES.InstanceofOperator(new C(), C), true, 'constructor function has an instance of itself');
2025
		t.equal(ES.InstanceofOperator(new D(), C), false, 'constructor/instance mismatch is false');
2026
		t.equal(ES.InstanceofOperator(new C(), D), false, 'instance/constructor mismatch is false');
2027
		t.equal(ES.InstanceofOperator({}, C), false, 'plain object is not an instance of a constructor');
2028
		t.equal(ES.InstanceofOperator({}, Object), true, 'plain object is an instance of Object');
2029
2030
		t.test('Symbol.hasInstance', { skip: !v.hasSymbols || !Symbol.hasInstance }, function (st) {
2031
			st.plan(4);
2032
2033
			var O = {};
2034
			var C2 = function () {};
2035
			st.equal(ES.InstanceofOperator(O, C2), false, 'O is not an instance of C2');
2036
2037
			Object.defineProperty(C2, Symbol.hasInstance, {
2038
				value: function (obj) {
2039
					st.equal(this, C2, 'hasInstance receiver is C2');
2040
					st.equal(obj, O, 'hasInstance argument is O');
2041
2042
					return {}; // testing coercion to boolean
2043
				}
2044
			});
2045
2046
			st.equal(ES.InstanceofOperator(O, C2), true, 'O is now an instance of C2');
2047
2048
			st.end();
2049
		});
2050
2051
		t.end();
2052
	});
2053
2054
	test('Abstract Equality Comparison', function (t) {
2055
		t.test('same types use ===', function (st) {
2056
			forEach(v.primitives.concat(v.objects), function (value) {
2057
				st.equal(ES['Abstract Equality Comparison'](value, value), value === value, debug(value) + ' is abstractly equal to itself');
2058
			});
2059
			st.end();
2060
		});
2061
2062
		t.test('different types coerce', function (st) {
2063
			var pairs = [
2064
				[null, undefined],
2065
				[3, '3'],
2066
				[true, '3'],
2067
				[true, 3],
2068
				[false, 0],
2069
				[false, '0'],
2070
				[3, [3]],
2071
				['3', [3]],
2072
				[true, [1]],
2073
				[false, [0]],
2074
				[String(v.coercibleObject), v.coercibleObject],
2075
				[Number(String(v.coercibleObject)), v.coercibleObject],
2076
				[Number(v.coercibleObject), v.coercibleObject],
2077
				[String(Number(v.coercibleObject)), v.coercibleObject]
2078
			];
2079
			forEach(pairs, function (pair) {
2080
				var a = pair[0];
2081
				var b = pair[1];
2082
				// eslint-disable-next-line eqeqeq
2083
				st.equal(ES['Abstract Equality Comparison'](a, b), a == b, debug(a) + ' == ' + debug(b));
2084
				// eslint-disable-next-line eqeqeq
2085
				st.equal(ES['Abstract Equality Comparison'](b, a), b == a, debug(b) + ' == ' + debug(a));
2086
			});
2087
			st.end();
2088
		});
2089
2090
		t.end();
2091
	});
2092
2093
	test('Strict Equality Comparison', function (t) {
2094
		t.test('same types use ===', function (st) {
2095
			forEach(v.primitives.concat(v.objects), function (value) {
2096
				st.equal(ES['Strict Equality Comparison'](value, value), value === value, debug(value) + ' is strictly equal to itself');
2097
			});
2098
			st.end();
2099
		});
2100
2101
		t.test('different types are not ===', function (st) {
2102
			var pairs = [
2103
				[null, undefined],
2104
				[3, '3'],
2105
				[true, '3'],
2106
				[true, 3],
2107
				[false, 0],
2108
				[false, '0'],
2109
				[3, [3]],
2110
				['3', [3]],
2111
				[true, [1]],
2112
				[false, [0]],
2113
				[String(v.coercibleObject), v.coercibleObject],
2114
				[Number(String(v.coercibleObject)), v.coercibleObject],
2115
				[Number(v.coercibleObject), v.coercibleObject],
2116
				[String(Number(v.coercibleObject)), v.coercibleObject]
2117
			];
2118
			forEach(pairs, function (pair) {
2119
				var a = pair[0];
2120
				var b = pair[1];
2121
				st.equal(ES['Strict Equality Comparison'](a, b), a === b, debug(a) + ' === ' + debug(b));
2122
				st.equal(ES['Strict Equality Comparison'](b, a), b === a, debug(b) + ' === ' + debug(a));
2123
			});
2124
			st.end();
2125
		});
2126
2127
		t.end();
2128
	});
2129
2130
	test('Abstract Relational Comparison', function (t) {
2131
		t.test('at least one operand is NaN', function (st) {
2132
			st.equal(ES['Abstract Relational Comparison'](NaN, {}, true), undefined, 'LeftFirst: first is NaN, returns undefined');
2133
			st.equal(ES['Abstract Relational Comparison']({}, NaN, true), undefined, 'LeftFirst: second is NaN, returns undefined');
2134
			st.equal(ES['Abstract Relational Comparison'](NaN, {}, false), undefined, '!LeftFirst: first is NaN, returns undefined');
2135
			st.equal(ES['Abstract Relational Comparison']({}, NaN, false), undefined, '!LeftFirst: second is NaN, returns undefined');
2136
			st.end();
2137
		});
2138
2139
		t.equal(ES['Abstract Relational Comparison'](3, 4, true), true, 'LeftFirst: 3 is less than 4');
2140
		t.equal(ES['Abstract Relational Comparison'](4, 3, true), false, 'LeftFirst: 3 is not less than 4');
2141
		t.equal(ES['Abstract Relational Comparison'](3, 4, false), true, '!LeftFirst: 3 is less than 4');
2142
		t.equal(ES['Abstract Relational Comparison'](4, 3, false), false, '!LeftFirst: 3 is not less than 4');
2143
2144
		t.equal(ES['Abstract Relational Comparison']('3', '4', true), true, 'LeftFirst: "3" is less than "4"');
2145
		t.equal(ES['Abstract Relational Comparison']('4', '3', true), false, 'LeftFirst: "3" is not less than "4"');
2146
		t.equal(ES['Abstract Relational Comparison']('3', '4', false), true, '!LeftFirst: "3" is less than "4"');
2147
		t.equal(ES['Abstract Relational Comparison']('4', '3', false), false, '!LeftFirst: "3" is not less than "4"');
2148
2149
		t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, true), true, 'LeftFirst: coercible object is less than 42');
2150
		t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, true), false, 'LeftFirst: 42 is not less than coercible object');
2151
		t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, 42, false), true, '!LeftFirst: coercible object is less than 42');
2152
		t.equal(ES['Abstract Relational Comparison'](42, v.coercibleObject, false), false, '!LeftFirst: 42 is not less than coercible object');
2153
2154
		t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', true), false, 'LeftFirst: coercible object is not less than "3"');
2155
		t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, true), false, 'LeftFirst: "3" is not less than coercible object');
2156
		t.equal(ES['Abstract Relational Comparison'](v.coercibleObject, '3', false), false, '!LeftFirst: coercible object is not less than "3"');
2157
		t.equal(ES['Abstract Relational Comparison']('3', v.coercibleObject, false), false, '!LeftFirst: "3" is not less than coercible object');
2158
2159
		t.end();
2160
	});
2161
2162
	test('ValidateAndApplyPropertyDescriptor', function (t) {
2163
		forEach(v.nonUndefinedPrimitives, function (nonUndefinedPrimitive) {
2164
			t['throws'](
2165
				function () { ES.ValidateAndApplyPropertyDescriptor(nonUndefinedPrimitive, '', false, v.genericDescriptor(), v.genericDescriptor()); },
2166
				TypeError,
2167
				'O: ' + debug(nonUndefinedPrimitive) + ' is not undefined or an Object'
2168
			);
2169
		});
2170
2171
		forEach(v.nonBooleans, function (nonBoolean) {
2172
			t['throws'](
2173
				function () {
2174
					return ES.ValidateAndApplyPropertyDescriptor(
2175
						undefined,
2176
						null,
2177
						nonBoolean,
2178
						v.genericDescriptor(),
2179
						v.genericDescriptor()
2180
					);
2181
				},
2182
				TypeError,
2183
				'extensible: ' + debug(nonBoolean) + ' is not a Boolean'
2184
			);
2185
		});
2186
2187
		forEach(v.primitives, function (primitive) {
2188
			// Desc must be a Property Descriptor
2189
			t['throws'](
2190
				function () {
2191
					return ES.ValidateAndApplyPropertyDescriptor(
2192
						undefined,
2193
						null,
2194
						false,
2195
						primitive,
2196
						v.genericDescriptor()
2197
					);
2198
				},
2199
				TypeError,
2200
				'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
2201
			);
2202
		});
2203
2204
		forEach(v.nonUndefinedPrimitives, function (primitive) {
2205
			// current must be undefined or a Property Descriptor
2206
			t['throws'](
2207
				function () {
2208
					return ES.ValidateAndApplyPropertyDescriptor(
2209
						undefined,
2210
						null,
2211
						false,
2212
						v.genericDescriptor(),
2213
						primitive
2214
					);
2215
				},
2216
				TypeError,
2217
				'current: ' + debug(primitive) + ' is not a Property Descriptor or undefined'
2218
			);
2219
		});
2220
2221
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
2222
			// if O is an object, P must be a property key
2223
			t['throws'](
2224
				function () {
2225
					return ES.ValidateAndApplyPropertyDescriptor(
2226
						{},
2227
						nonPropertyKey,
2228
						false,
2229
						v.genericDescriptor(),
2230
						v.genericDescriptor()
2231
					);
2232
				},
2233
				TypeError,
2234
				'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
2235
			);
2236
		});
2237
2238
		t.test('current is undefined', function (st) {
2239
			var propertyKey = 'howdy';
2240
2241
			st.test('generic descriptor', function (s2t) {
2242
				var generic = v.genericDescriptor();
2243
				generic['[[Enumerable]]'] = true;
2244
				var O = {};
2245
				ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, generic);
2246
				s2t.equal(
2247
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, generic),
2248
					false,
2249
					'when extensible is false, nothing happens'
2250
				);
2251
				s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
2252
				s2t.equal(
2253
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, generic),
2254
					true,
2255
					'operation is successful'
2256
				);
2257
				var expected = {};
2258
				expected[propertyKey] = undefined;
2259
				s2t.deepEqual(O, expected, 'generic descriptor has been defined as an own data property');
2260
				s2t.end();
2261
			});
2262
2263
			st.test('data descriptor', function (s2t) {
2264
				var data = v.dataDescriptor();
2265
				data['[[Enumerable]]'] = true;
2266
2267
				var O = {};
2268
				ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, data);
2269
				s2t.equal(
2270
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, data),
2271
					false,
2272
					'when extensible is false, nothing happens'
2273
				);
2274
				s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
2275
				s2t.equal(
2276
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, data),
2277
					true,
2278
					'operation is successful'
2279
				);
2280
				var expected = {};
2281
				expected[propertyKey] = data['[[Value]]'];
2282
				s2t.deepEqual(O, expected, 'data descriptor has been defined as an own data property');
2283
				s2t.end();
2284
			});
2285
2286
			st.test('accessor descriptor', function (s2t) {
2287
				var count = 0;
2288
				var accessor = v.accessorDescriptor();
2289
				accessor['[[Enumerable]]'] = true;
2290
				accessor['[[Get]]'] = function () {
2291
					count += 1;
2292
					return count;
2293
				};
2294
2295
				var O = {};
2296
				ES.ValidateAndApplyPropertyDescriptor(undefined, propertyKey, true, accessor);
2297
				s2t.equal(
2298
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, false, accessor),
2299
					false,
2300
					'when extensible is false, nothing happens'
2301
				);
2302
				s2t.deepEqual(O, {}, 'no changes applied when O is undefined or extensible is false');
2303
				s2t.equal(
2304
					ES.ValidateAndApplyPropertyDescriptor(O, propertyKey, true, accessor),
2305
					true,
2306
					'operation is successful'
2307
				);
2308
				var expected = {};
2309
				expected[propertyKey] = accessor['[[Get]]']() + 1;
2310
				s2t.deepEqual(O, expected, 'accessor descriptor has been defined as an own accessor property');
2311
				s2t.end();
2312
			});
2313
2314
			st.end();
2315
		});
2316
2317
		t.test('every field in Desc is absent', { skip: 'it is unclear if having no fields qualifies Desc to be a Property Descriptor' });
2318
2319
		forEach([v.dataDescriptor, v.accessorDescriptor, v.mutatorDescriptor], function (getDescriptor) {
2320
			t.equal(
2321
				ES.ValidateAndApplyPropertyDescriptor(undefined, 'property key', true, getDescriptor(), getDescriptor()),
2322
				true,
2323
				'when Desc and current are the same, early return true'
2324
			);
2325
		});
2326
2327
		t.test('current is nonconfigurable', function (st) {
2328
			// note: these must not be generic descriptors, or else the algorithm returns an early true
2329
			st.equal(
2330
				ES.ValidateAndApplyPropertyDescriptor(
2331
					undefined,
2332
					'property key',
2333
					true,
2334
					v.descriptors.configurable(v.dataDescriptor()),
2335
					v.descriptors.nonConfigurable(v.dataDescriptor())
2336
				),
2337
				false,
2338
				'false if Desc is configurable'
2339
			);
2340
2341
			st.equal(
2342
				ES.ValidateAndApplyPropertyDescriptor(
2343
					undefined,
2344
					'property key',
2345
					true,
2346
					v.descriptors.enumerable(v.dataDescriptor()),
2347
					v.descriptors.nonEnumerable(v.dataDescriptor())
2348
				),
2349
				false,
2350
				'false if Desc is Enumerable and current is not'
2351
			);
2352
2353
			st.equal(
2354
				ES.ValidateAndApplyPropertyDescriptor(
2355
					undefined,
2356
					'property key',
2357
					true,
2358
					v.descriptors.nonEnumerable(v.dataDescriptor()),
2359
					v.descriptors.enumerable(v.dataDescriptor())
2360
				),
2361
				false,
2362
				'false if Desc is not Enumerable and current is'
2363
			);
2364
2365
			var descLackingEnumerable = v.accessorDescriptor();
2366
			delete descLackingEnumerable['[[Enumerable]]'];
2367
			st.equal(
2368
				ES.ValidateAndApplyPropertyDescriptor(
2369
					undefined,
2370
					'property key',
2371
					true,
2372
					descLackingEnumerable,
2373
					v.descriptors.enumerable(v.accessorDescriptor())
2374
				),
2375
				true,
2376
				'not false if Desc lacks Enumerable'
2377
			);
2378
2379
			st.end();
2380
		});
2381
2382
		t.test('Desc and current: one is a data descriptor, one is not', { skip: !Object.defineProperty }, function (st) {
2383
			// note: Desc must be configurable if current is nonconfigurable, to hit this branch
2384
			st.equal(
2385
				ES.ValidateAndApplyPropertyDescriptor(
2386
					undefined,
2387
					'property key',
2388
					true,
2389
					v.descriptors.configurable(v.accessorDescriptor()),
2390
					v.descriptors.nonConfigurable(v.dataDescriptor())
2391
				),
2392
				false,
2393
				'false if current (data) is nonconfigurable'
2394
			);
2395
2396
			st.equal(
2397
				ES.ValidateAndApplyPropertyDescriptor(
2398
					undefined,
2399
					'property key',
2400
					true,
2401
					v.descriptors.configurable(v.dataDescriptor()),
2402
					v.descriptors.nonConfigurable(v.accessorDescriptor())
2403
				),
2404
				false,
2405
				'false if current (not data) is nonconfigurable'
2406
			);
2407
2408
			// one is data and one is not,
2409
			//	// if current is data, convert to accessor
2410
			//	// else convert to data
2411
2412
			var startsWithData = {
2413
				'property key': 42
2414
			};
2415
			st.equal(
2416
				ES.ValidateAndApplyPropertyDescriptor(
2417
					startsWithData,
2418
					'property key',
2419
					true,
2420
					v.descriptors.enumerable(v.descriptors.configurable(v.accessorDescriptor())),
2421
					v.descriptors.enumerable(v.descriptors.configurable(v.dataDescriptor()))
2422
				),
2423
				true,
2424
				'operation is successful: current is data, Desc is accessor'
2425
			);
2426
			var shouldBeAccessor = Object.getOwnPropertyDescriptor(startsWithData, 'property key');
2427
			st.equal(typeof shouldBeAccessor.get, 'function', 'has a getter');
2428
2429
			var key = 'property key';
2430
			var startsWithAccessor = {};
2431
			Object.defineProperty(startsWithAccessor, key, {
2432
				configurable: true,
2433
				enumerable: true,
2434
				get: function get() { return 42; }
2435
			});
2436
			st.equal(
2437
				ES.ValidateAndApplyPropertyDescriptor(
2438
					startsWithAccessor,
2439
					key,
2440
					true,
2441
					v.descriptors.enumerable(v.descriptors.configurable(v.dataDescriptor())),
2442
					v.descriptors.enumerable(v.descriptors.configurable(v.accessorDescriptor(42)))
2443
				),
2444
				true,
2445
				'operation is successful: current is accessor, Desc is data'
2446
			);
2447
			var shouldBeData = Object.getOwnPropertyDescriptor(startsWithAccessor, 'property key');
2448
			st.deepEqual(shouldBeData, { configurable: true, enumerable: true, value: 42, writable: false }, 'is a data property');
2449
2450
			st.end();
2451
		});
2452
2453
		t.test('Desc and current are both data descriptors', function (st) {
2454
			st.equal(
2455
				ES.ValidateAndApplyPropertyDescriptor(
2456
					undefined,
2457
					'property key',
2458
					true,
2459
					v.descriptors.writable(v.dataDescriptor()),
2460
					v.descriptors.nonWritable(v.descriptors.nonConfigurable(v.dataDescriptor()))
2461
				),
2462
				false,
2463
				'false if frozen current and writable Desc'
2464
			);
2465
2466
			st.equal(
2467
				ES.ValidateAndApplyPropertyDescriptor(
2468
					undefined,
2469
					'property key',
2470
					true,
2471
					v.descriptors.configurable({ '[[Value]]': 42 }),
2472
					v.descriptors.nonWritable({ '[[Value]]': 7 })
2473
				),
2474
				false,
2475
				'false if nonwritable current has a different value than Desc'
2476
			);
2477
2478
			st.end();
2479
		});
2480
2481
		t.test('current is nonconfigurable; Desc and current are both accessor descriptors', function (st) {
2482
			st.equal(
2483
				ES.ValidateAndApplyPropertyDescriptor(
2484
					undefined,
2485
					'property key',
2486
					true,
2487
					v.mutatorDescriptor(),
2488
					v.descriptors.nonConfigurable(v.mutatorDescriptor())
2489
				),
2490
				false,
2491
				'false if both Sets are not equal'
2492
			);
2493
2494
			st.equal(
2495
				ES.ValidateAndApplyPropertyDescriptor(
2496
					undefined,
2497
					'property key',
2498
					true,
2499
					v.accessorDescriptor(),
2500
					v.descriptors.nonConfigurable(v.accessorDescriptor())
2501
				),
2502
				false,
2503
				'false if both Gets are not equal'
2504
			);
2505
2506
			st.end();
2507
		});
2508
2509
		t.end();
2510
	});
2511
2512
	test('OrdinaryGetOwnProperty', function (t) {
2513
		forEach(v.primitives, function (primitive) {
2514
			t['throws'](
2515
				function () { ES.OrdinaryGetOwnProperty(primitive, ''); },
2516
				TypeError,
2517
				'O: ' + debug(primitive) + ' is not an Object'
2518
			);
2519
		});
2520
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
2521
			t['throws'](
2522
				function () { ES.OrdinaryGetOwnProperty({}, nonPropertyKey); },
2523
				TypeError,
2524
				'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
2525
			);
2526
		});
2527
2528
		t.equal(ES.OrdinaryGetOwnProperty({}, 'not in the object'), undefined, 'missing property yields undefined');
2529
		t.equal(ES.OrdinaryGetOwnProperty({}, 'toString'), undefined, 'inherited non-own property yields undefined');
2530
2531
		t.deepEqual(
2532
			ES.OrdinaryGetOwnProperty({ a: 1 }, 'a'),
2533
			ES.ToPropertyDescriptor({
2534
				configurable: true,
2535
				enumerable: true,
2536
				value: 1,
2537
				writable: true
2538
			}),
2539
			'own assigned data property yields expected descriptor'
2540
		);
2541
2542
		t.deepEqual(
2543
			ES.OrdinaryGetOwnProperty(/a/, 'lastIndex'),
2544
			ES.ToPropertyDescriptor({
2545
				configurable: false,
2546
				enumerable: false,
2547
				value: 0,
2548
				writable: true
2549
			}),
2550
			'regex lastIndex yields expected descriptor'
2551
		);
2552
2553
		t.deepEqual(
2554
			ES.OrdinaryGetOwnProperty([], 'length'),
2555
			ES.ToPropertyDescriptor({
2556
				configurable: false,
2557
				enumerable: false,
2558
				value: 0,
2559
				writable: true
2560
			}),
2561
			'array length yields expected descriptor'
2562
		);
2563
2564
		t.deepEqual(
2565
			ES.OrdinaryGetOwnProperty(Object.prototype, 'toString'),
2566
			ES.ToPropertyDescriptor({
2567
				configurable: true,
2568
				enumerable: false,
2569
				value: Object.prototype.toString,
2570
				writable: true
2571
			}),
2572
			'own non-enumerable data property yields expected descriptor'
2573
		);
2574
2575
		t.test('ES5+', { skip: !Object.defineProperty }, function (st) {
2576
			var O = {};
2577
			Object.defineProperty(O, 'foo', {
2578
				configurable: false,
2579
				enumerable: false,
2580
				value: O,
2581
				writable: true
2582
			});
2583
2584
			t.deepEqual(
2585
				ES.OrdinaryGetOwnProperty(O, 'foo'),
2586
				ES.ToPropertyDescriptor({
2587
					configurable: false,
2588
					enumerable: false,
2589
					value: O,
2590
					writable: true
2591
				}),
2592
				'defined own property yields expected descriptor'
2593
			);
2594
2595
			st.end();
2596
		});
2597
2598
		t.end();
2599
	});
2600
2601
	test('OrdinaryDefineOwnProperty', { skip: !Object.defineProperty }, function (t) {
2602
		forEach(v.primitives, function (primitive) {
2603
			t['throws'](
2604
				function () { ES.CopyDataProperties(primitive, {}, []); },
2605
				TypeError,
2606
				'O: ' + debug(primitive) + ' is not an Object'
2607
			);
2608
		});
2609
		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
2610
			t['throws'](
2611
				function () { ES.OrdinaryDefineOwnProperty({}, nonPropertyKey, v.genericDescriptor()); },
2612
				TypeError,
2613
				'P: ' + debug(nonPropertyKey) + ' is not a Property Key'
2614
			);
2615
		});
2616
		forEach(v.primitives, function (primitive) {
2617
			t['throws'](
2618
				function () { ES.OrdinaryDefineOwnProperty(primitive, '', v.genericDescriptor()); },
2619
				TypeError,
2620
				'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
2621
			);
2622
		});
2623
2624
		var O = {};
2625
		var P = 'property key';
2626
		var Desc = v.accessorDescriptor();
2627
		t.equal(
2628
			ES.OrdinaryDefineOwnProperty(O, P, Desc),
2629
			true,
2630
			'operation is successful'
2631
		);
2632
		t.deepEqual(
2633
			Object.getOwnPropertyDescriptor(O, P),
2634
			ES.FromPropertyDescriptor(ES.CompletePropertyDescriptor(Desc)),
2635
			'expected property descriptor is defined'
2636
		);
2637
2638
		t.end();
2639
	});
2640
2641
	test('ArrayCreate', function (t) {
2642
		forEach(v.nonIntegerNumbers.concat([-1]), function (nonIntegerNumber) {
2643
			t['throws'](
2644
				function () { ES.ArrayCreate(nonIntegerNumber); },
2645
				TypeError,
2646
				'length must be an integer number >= 0'
2647
			);
2648
		});
2649
2650
		t['throws'](
2651
			function () { ES.ArrayCreate(Math.pow(2, 32)); },
2652
			RangeError,
2653
			'length must be < 2**32'
2654
		);
2655
2656
		t.deepEqual(ES.ArrayCreate(-0), [], 'length of -0 creates an empty array');
2657
		t.deepEqual(ES.ArrayCreate(0), [], 'length of +0 creates an empty array');
2658
		// eslint-disable-next-line no-sparse-arrays, comma-spacing
2659
		t.deepEqual(ES.ArrayCreate(1), [,], 'length of 1 creates a sparse array of length 1');
2660
		// eslint-disable-next-line no-sparse-arrays, comma-spacing
2661
		t.deepEqual(ES.ArrayCreate(2), [,,], 'length of 2 creates a sparse array of length 2');
2662
2663
		// eslint-disable-next-line no-proto
2664
		t.test('proto argument', { skip: [].__proto__ !== Array.prototype }, function (st) {
2665
			var fakeProto = {
2666
				push: { toString: function () { return 'not array push'; } }
2667
			};
2668
			st.equal(ES.ArrayCreate(0, fakeProto).push, fakeProto.push, 'passing the proto argument works');
2669
			st.end();
2670
		});
2671
2672
		t.end();
2673
	});
2674
2675
	test('ArraySetLength', function (t) {
2676
		forEach(v.primitives.concat(v.objects), function (nonArray) {
2677
			t['throws'](
2678
				function () { ES.ArraySetLength(nonArray, 0); },
2679
				TypeError,
2680
				'A: ' + debug(nonArray) + ' is not an Array'
2681
			);
2682
		});
2683
2684
		forEach(v.nonUndefinedPrimitives, function (primitive) {
2685
			t['throws'](
2686
				function () { ES.ArraySetLength([], primitive); },
2687
				TypeError,
2688
				'Desc: ' + debug(primitive) + ' is not a Property Descriptor'
2689
			);
2690
		});
2691
2692
		t.test('making length nonwritable', { skip: !Object.defineProperty }, function (st) {
2693
			var a = [];
2694
			ES.ArraySetLength(a, { '[[Writable]]': false });
2695
			st.deepEqual(
2696
				Object.getOwnPropertyDescriptor(a, 'length'),
2697
				{
2698
					configurable: false,
2699
					enumerable: false,
2700
					value: 0,
2701
					writable: false
2702
				},
2703
				'without a value, length becomes nonwritable'
2704
			);
2705
			st.end();
2706
		});
2707
2708
		var arr = [];
2709
		ES.ArraySetLength(arr, { '[[Value]]': 7 });
2710
		t.equal(arr.length, 7, 'array now has a length of 7');
2711
2712
		t.end();
2713
	});
2714
2715
	test('CreateHTML', function (t) {
2716
		forEach(v.nonStrings, function (nonString) {
2717
			t['throws'](
2718
				function () { ES.CreateHTML('', nonString, '', ''); },
2719
				TypeError,
2720
				'tag: ' + debug(nonString) + ' is not a String'
2721
			);
2722
			t['throws'](
2723
				function () { ES.CreateHTML('', '', nonString, ''); },
2724
				TypeError,
2725
				'attribute: ' + debug(nonString) + ' is not a String'
2726
			);
2727
		});
2728
2729
		t.equal(
2730
			ES.CreateHTML(
2731
				{ toString: function () { return 'the string'; } },
2732
				'some HTML tag!',
2733
				''
2734
			),
2735
			'<some HTML tag!>the string</some HTML tag!>',
2736
			'works with an empty string attribute value'
2737
		);
2738
2739
		t.equal(
2740
			ES.CreateHTML(
2741
				{ toString: function () { return 'the string'; } },
2742
				'some HTML tag!',
2743
				'attr',
2744
				'value "with quotes"'
2745
			),
2746
			'<some HTML tag! attr="value &quot;with quotes&quot;">the string</some HTML tag!>',
2747
			'works with an attribute, and a value with quotes'
2748
		);
2749
2750
		t.end();
2751
	});
2752
2753
	test('GetOwnPropertyKeys', function (t) {
2754
		forEach(v.primitives, function (primitive) {
2755
			t['throws'](
2756
				function () { ES.GetOwnPropertyKeys(primitive, 'String'); },
2757
				TypeError,
2758
				'O: ' + debug(primitive) + ' is not an Object'
2759
			);
2760
		});
2761
2762
		t['throws'](
2763
			function () { ES.GetOwnPropertyKeys({}, 'not string or symbol'); },
2764
			TypeError,
2765
			'Type: must be "String" or "Symbol"'
2766
		);
2767
2768
		t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
2769
			var O = { a: 1 };
2770
			O[Symbol.iterator] = true;
2771
			var s = Symbol('test');
2772
			Object.defineProperty(O, s, { enumerable: false, value: true });
2773
2774
			st.deepEqual(
2775
				ES.GetOwnPropertyKeys(O, 'Symbol'),
2776
				[Symbol.iterator, s],
2777
				'works with Symbols, enumerable or not'
2778
			);
2779
2780
			st.end();
2781
		});
2782
2783
		t.test('non-enumerable names', { skip: !Object.defineProperty }, function (st) {
2784
			var O = { a: 1 };
2785
			Object.defineProperty(O, 'b', { enumerable: false, value: 2 });
2786
			if (v.hasSymbols) {
2787
				O[Symbol.iterator] = true;
2788
			}
2789
2790
			st.deepEqual(
2791
				ES.GetOwnPropertyKeys(O, 'String').sort(),
2792
				['a', 'b'].sort(),
2793
				'works with Strings, enumerable or not'
2794
			);
2795
2796
			st.end();
2797
		});
2798
2799
		t.deepEqual(
2800
			ES.GetOwnPropertyKeys({ a: 1, b: 2 }, 'String').sort(),
2801
			['a', 'b'].sort(),
2802
			'works with enumerable keys'
2803
		);
2804
2805
		t.end();
2806
	});
2807
2808
	test('SymbolDescriptiveString', function (t) {
2809
		forEach(v.nonSymbolPrimitives.concat(v.objects), function (nonSymbol) {
2810
			t['throws'](
2811
				function () { ES.SymbolDescriptiveString(nonSymbol); },
2812
				TypeError,
2813
				debug(nonSymbol) + ' is not a Symbol'
2814
			);
2815
		});
2816
2817
		t.test('Symbols', { skip: !v.hasSymbols }, function (st) {
2818
			st.equal(ES.SymbolDescriptiveString(Symbol()), 'Symbol()', 'undefined description');
2819
			st.equal(ES.SymbolDescriptiveString(Symbol('')), 'Symbol()', 'empty string description');
2820
			st.equal(ES.SymbolDescriptiveString(Symbol.iterator), 'Symbol(Symbol.iterator)', 'well-known symbol');
2821
			st.equal(ES.SymbolDescriptiveString(Symbol('foo')), 'Symbol(foo)', 'string description');
2822
2823
			st.end();
2824
		});
2825
2826
		t.end();
2827
	});
2828
2829
	test('GetSubstitution', { skip: skips && skips.GetSubstitution }, function (t) {
2830
		forEach(v.nonStrings, function (nonString) {
2831
			t['throws'](
2832
				function () { ES.GetSubstitution(nonString, '', 0, [], ''); },
2833
				TypeError,
2834
				'`matched`: ' + debug(nonString) + ' is not a String'
2835
			);
2836
2837
			t['throws'](
2838
				function () { ES.GetSubstitution('', nonString, 0, [], ''); },
2839
				TypeError,
2840
				'`str`: ' + debug(nonString) + ' is not a String'
2841
			);
2842
2843
			t['throws'](
2844
				function () { ES.GetSubstitution('', '', 0, [], nonString); },
2845
				TypeError,
2846
				'`replacement`: ' + debug(nonString) + ' is not a String'
2847
			);
2848
2849
			t['throws'](
2850
				function () { ES.GetSubstitution('', '', 0, [nonString], ''); },
2851
				TypeError,
2852
				'`captures`: ' + debug([nonString]) + ' is not an Array of strings'
2853
			);
2854
		});
2855
2856
		forEach(v.nonIntegerNumbers.concat([-1, -42, -Infinity]), function (nonNonNegativeInteger) {
2857
			t['throws'](
2858
				function () { ES.GetSubstitution('', '', nonNonNegativeInteger, [], ''); },
2859
				TypeError,
2860
				'`position`: ' + debug(nonNonNegativeInteger) + ' is not a non-negative integer'
2861
			);
2862
		});
2863
2864
		forEach(v.nonArrays, function (nonArray) {
2865
			t['throws'](
2866
				function () { ES.GetSubstitution('', '', 0, nonArray, ''); },
2867
				TypeError,
2868
				'`captures`: ' + debug(nonArray) + ' is not an Array'
2869
			);
2870
		});
2871
2872
		t.equal(
2873
			ES.GetSubstitution('def', 'abcdefghi', 3, [], '123'),
2874
			'123',
2875
			'returns the substitution'
2876
		);
2877
		t.equal(
2878
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '$$2$'),
2879
			'$2$',
2880
			'supports $$, and trailing $'
2881
		);
2882
2883
		t.equal(
2884
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$&<'),
2885
			'>abcdef<',
2886
			'supports $&'
2887
		);
2888
2889
		t.equal(
2890
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$`<'),
2891
			'><',
2892
			'supports $` at position 0'
2893
		);
2894
		t.equal(
2895
			ES.GetSubstitution('def', 'abcdefghi', 3, [], '>$`<'),
2896
			'>ab<',
2897
			'supports $` at position > 0'
2898
		);
2899
2900
		t.equal(
2901
			ES.GetSubstitution('def', 'abcdefghi', 7, [], ">$'<"),
2902
			'><',
2903
			"supports $' at a position where there's less than `matched.length` chars left"
2904
		);
2905
		t.equal(
2906
			ES.GetSubstitution('def', 'abcdefghi', 3, [], ">$'<"),
2907
			'>ghi<',
2908
			"supports $' at a position where there's more than `matched.length` chars left"
2909
		);
2910
2911
		for (var i = 0; i < 100; i += 1) {
2912
			var captures = [];
2913
			captures[i] = 'test';
2914
			if (i > 0) {
2915
				t.equal(
2916
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$' + i + '<'),
2917
					'>undefined<',
2918
					'supports $' + i + ' with no captures'
2919
				);
2920
				t.equal(
2921
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$' + i),
2922
					'>undefined',
2923
					'supports $' + i + ' at the end of the replacement, with no captures'
2924
				);
2925
				t.equal(
2926
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$' + i + '<'),
2927
					'><',
2928
					'supports $' + i + ' with a capture at that index'
2929
				);
2930
				t.equal(
2931
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$' + i),
2932
					'>',
2933
					'supports $' + i + ' at the end of the replacement, with a capture at that index'
2934
				);
2935
			}
2936
			if (i < 10) {
2937
				t.equal(
2938
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$0' + i + '<'),
2939
					i === 0 ? '><' : '>undefined<',
2940
					'supports $0' + i + ' with no captures'
2941
				);
2942
				t.equal(
2943
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], '>$0' + i),
2944
					i === 0 ? '>' : '>undefined',
2945
					'supports $0' + i + ' at the end of the replacement, with no captures'
2946
				);
2947
				t.equal(
2948
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$0' + i + '<'),
2949
					'><',
2950
					'supports $0' + i + ' with a capture at that index'
2951
				);
2952
				t.equal(
2953
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, '>$0' + i),
2954
					'>',
2955
					'supports $0' + i + ' at the end of the replacement, with a capture at that index'
2956
				);
2957
			}
2958
		}
2959
2960
		t.end();
2961
	});
2962
};
2963
2964
var es2016 = function ES2016(ES, ops, expectedMissing, skips) {
2965
	es2015(ES, ops, expectedMissing, skips);
2966
2967
	test('SameValueNonNumber', function (t) {
2968
		var willThrow = [
2969
			[3, 4],
2970
			[NaN, 4],
2971
			[4, ''],
2972
			['abc', true],
2973
			[{}, false]
2974
		];
2975
		forEach(willThrow, function (nums) {
2976
			t['throws'](function () { return ES.SameValueNonNumber.apply(ES, nums); }, TypeError, 'value must be same type and non-number');
2977
		});
2978
2979
		forEach(v.objects.concat(v.nonNumberPrimitives), function (val) {
2980
			t.equal(val === val, ES.SameValueNonNumber(val, val), debug(val) + ' is SameValueNonNumber to itself');
2981
		});
2982
2983
		t.end();
2984
	});
2985
2986
	test('IterableToArrayLike', { skip: skips && skips.IterableToArrayLike }, function (t) {
2987
		t.test('custom iterables', { skip: !v.hasSymbols }, function (st) {
2988
			var O = {};
2989
			O[Symbol.iterator] = function () {
2990
				var i = -1;
2991
				return {
2992
					next: function () {
2993
						i += 1;
2994
						return {
2995
							done: i >= 5,
2996
							value: i
2997
						};
2998
					}
2999
				};
3000
			};
3001
			st.deepEqual(
3002
				ES.IterableToArrayLike(O),
3003
				[0, 1, 2, 3, 4],
3004
				'Symbol.iterator method is called and values collected'
3005
			);
3006
3007
			st.end();
3008
		});
3009
3010
		t.deepEqual(ES.IterableToArrayLike('abc'), ['a', 'b', 'c'], 'a string of code units spreads');
3011
		t.deepEqual(ES.IterableToArrayLike('💩'), ['💩'], 'a string of code points spreads');
3012
		t.deepEqual(ES.IterableToArrayLike('a💩c'), ['a', '💩', 'c'], 'a string of code points and units spreads');
3013
3014
		var arr = [1, 2, 3];
3015
		t.deepEqual(ES.IterableToArrayLike(arr), arr, 'an array becomes a similar array');
3016
		t.notEqual(ES.IterableToArrayLike(arr), arr, 'an array becomes a different, but similar, array');
3017
3018
		var O = {};
3019
		t.equal(ES.IterableToArrayLike(O), O, 'a non-iterable non-array non-string object is returned directly');
3020
3021
		t.end();
3022
	});
3023
};
3024
3025
var es2017 = function ES2017(ES, ops, expectedMissing, skips) {
3026
	es2016(ES, ops, expectedMissing, assign({}, skips, {
3027
		EnumerableOwnNames: true,
3028
		IterableToArrayLike: true
3029
	}));
3030
3031
	test('ToIndex', function (t) {
3032
		t.ok(is(ES.ToIndex(), 0), 'no value gives 0');
3033
		t.ok(is(ES.ToIndex(undefined), 0), 'undefined value gives 0');
3034
3035
		t['throws'](function () { ES.ToIndex(-1); }, RangeError, 'negative numbers throw');
3036
3037
		t['throws'](function () { ES.ToIndex(MAX_SAFE_INTEGER + 1); }, RangeError, 'too large numbers throw');
3038
3039
		t.equal(ES.ToIndex(3), 3, 'numbers work');
3040
		t.equal(ES.ToIndex(v.valueOfOnlyObject), 4, 'coercible objects are coerced');
3041
3042
		t.end();
3043
	});
3044
3045
	test('EnumerableOwnProperties', { skip: skips && skips.EnumerableOwnProperties }, function (t) {
3046
		var obj = testEnumerableOwnNames(t, function (O) {
3047
			return ES.EnumerableOwnProperties(O, 'key');
3048
		});
3049
3050
		t.deepEqual(
3051
			ES.EnumerableOwnProperties(obj, 'value'),
3052
			[obj.own],
3053
			'returns enumerable own values'
3054
		);
3055
3056
		t.deepEqual(
3057
			ES.EnumerableOwnProperties(obj, 'key+value'),
3058
			[['own', obj.own]],
3059
			'returns enumerable own entries'
3060
		);
3061
3062
		t.end();
3063
	});
3064
3065
	test('IterableToList', function (t) {
3066
		var customIterator = function () {
3067
			var i = -1;
3068
			return {
3069
				next: function () {
3070
					i += 1;
3071
					return {
3072
						done: i >= 5,
3073
						value: i
3074
					};
3075
				}
3076
			};
3077
		};
3078
3079
		t.deepEqual(
3080
			ES.IterableToList({}, customIterator),
3081
			[0, 1, 2, 3, 4],
3082
			'iterator method is called and values collected'
3083
		);
3084
3085
		t.test('Symbol support', { skip: !v.hasSymbols }, function (st) {
3086
			st.deepEqual(ES.IterableToList('abc', String.prototype[Symbol.iterator]), ['a', 'b', 'c'], 'a string of code units spreads');
3087
			st.deepEqual(ES.IterableToList('☃', String.prototype[Symbol.iterator]), ['☃'], 'a string of code points spreads');
3088
3089
			var arr = [1, 2, 3];
3090
			st.deepEqual(ES.IterableToList(arr, arr[Symbol.iterator]), arr, 'an array becomes a similar array');
3091
			st.notEqual(ES.IterableToList(arr, arr[Symbol.iterator]), arr, 'an array becomes a different, but similar, array');
3092
3093
			st.end();
3094
		});
3095
3096
		t['throws'](
3097
			function () { ES.IterableToList({}, void 0); },
3098
			TypeError,
3099
			'non-function iterator method'
3100
		);
3101
3102
		t.end();
3103
	});
3104
};
3105
3106
var es2018 = function ES2018(ES, ops, expectedMissing, skips) {
3107
	es2017(ES, ops, expectedMissing, assign({}, skips, {
3108
		EnumerableOwnProperties: true,
3109
		GetSubstitution: true,
3110
		IsPropertyDescriptor: true
3111
	}));
3112
3113
	test('thisSymbolValue', function (t) {
3114
		forEach(v.nonSymbolPrimitives.concat(v.objects), function (nonSymbol) {
3115
			t['throws'](
3116
				function () { ES.thisSymbolValue(nonSymbol); },
3117
				v.hasSymbols ? TypeError : SyntaxError,
3118
				debug(nonSymbol) + ' is not a Symbol'
3119
			);
3120
		});
3121
3122
		t.test('no native Symbols', { skip: v.hasSymbols }, function (st) {
3123
			forEach(v.objects.concat(v.primitives), function (value) {
3124
				st['throws'](
3125
					function () { ES.thisSymbolValue(value); },
3126
					SyntaxError,
3127
					'Symbols are not supported'
3128
				);
3129
			});
3130
			st.end();
3131
		});
3132
3133
		t.test('symbol values', { skip: !v.hasSymbols }, function (st) {
3134
			forEach(v.symbols, function (symbol) {
3135
				st.equal(ES.thisSymbolValue(symbol), symbol, 'Symbol value of ' + debug(symbol) + ' is same symbol');
3136
3137
				st.equal(
3138
					ES.thisSymbolValue(Object(symbol)),
3139
					symbol,
3140
					'Symbol value of ' + debug(Object(symbol)) + ' is ' + debug(symbol)
3141
				);
3142
			});
3143
3144
			st.end();
3145
		});
3146
3147
		t.end();
3148
	});
3149
3150
	test('IsStringPrefix', function (t) {
3151
		forEach(v.nonStrings, function (nonString) {
3152
			t['throws'](
3153
				function () { ES.IsStringPrefix(nonString, 'a'); },
3154
				TypeError,
3155
				'first arg: ' + debug(nonString) + ' is not a string'
3156
			);
3157
			t['throws'](
3158
				function () { ES.IsStringPrefix('a', nonString); },
3159
				TypeError,
3160
				'second arg: ' + debug(nonString) + ' is not a string'
3161
			);
3162
		});
3163
3164
		forEach(v.strings, function (string) {
3165
			t.equal(ES.IsStringPrefix(string, string), true, debug(string) + ' is a prefix of itself');
3166
3167
			t.equal(ES.IsStringPrefix('', string), true, 'the empty string is a prefix of everything');
3168
		});
3169
3170
		t.equal(ES.IsStringPrefix('abc', 'abcd'), true, '"abc" is a prefix of "abcd"');
3171
		t.equal(ES.IsStringPrefix('abcd', 'abc'), false, '"abcd" is not a prefix of "abc"');
3172
3173
		t.equal(ES.IsStringPrefix('a', 'bc'), false, '"a" is not a prefix of "bc"');
3174
3175
		t.end();
3176
	});
3177
3178
	test('NumberToString', function (t) {
3179
		forEach(v.nonNumbers, function (nonNumber) {
3180
			t['throws'](
3181
				function () { ES.NumberToString(nonNumber); },
3182
				TypeError,
3183
				debug(nonNumber) + ' is not a Number'
3184
			);
3185
		});
3186
3187
		forEach(v.numbers, function (number) {
3188
			t.equal(ES.NumberToString(number), String(number), debug(number) + ' stringifies to ' + number);
3189
		});
3190
3191
		t.end();
3192
	});
3193
3194
	test('CopyDataProperties', function (t) {
3195
		t.test('first argument: target', function (st) {
3196
			forEach(v.primitives, function (primitive) {
3197
				st['throws'](
3198
					function () { ES.CopyDataProperties(primitive, {}, []); },
3199
					TypeError,
3200
					debug(primitive) + ' is not an Object'
3201
				);
3202
			});
3203
			st.end();
3204
		});
3205
3206
		t.test('second argument: source', function (st) {
3207
			var frozenTarget = Object.freeze ? Object.freeze({}) : {};
3208
			forEach(v.nullPrimitives, function (nullish) {
3209
				st.equal(
3210
					ES.CopyDataProperties(frozenTarget, nullish, []),
3211
					frozenTarget,
3212
					debug(nullish) + ' "source" yields identical, unmodified target'
3213
				);
3214
			});
3215
3216
			forEach(v.nonNullPrimitives, function (objectCoercible) {
3217
				var target = {};
3218
				var result = ES.CopyDataProperties(target, objectCoercible, []);
3219
				st.equal(result, target, 'result === target');
3220
				st.deepEqual(keys(result), keys(Object(objectCoercible)), 'target ends up with keys of ' + debug(objectCoercible));
3221
			});
3222
3223
			st.end();
3224
		});
3225
3226
		t.test('third argument: excludedItems', function (st) {
3227
			forEach(v.objects.concat(v.primitives), function (nonArray) {
3228
				st['throws'](
3229
					function () { ES.CopyDataProperties({}, {}, nonArray); },
3230
					TypeError,
3231
					debug(nonArray) + ' is not an Array'
3232
				);
3233
			});
3234
3235
			forEach(v.nonPropertyKeys, function (nonPropertyKey) {
3236
				st['throws'](
3237
					function () { ES.CopyDataProperties({}, {}, [nonPropertyKey]); },
3238
					TypeError,
3239
					debug(nonPropertyKey) + ' is not a Property Key'
3240
				);
3241
			});
3242
3243
			var result = ES.CopyDataProperties({}, { a: 1, b: 2, c: 3 }, ['b']);
3244
			st.deepEqual(keys(result), ['a', 'c'], 'excluded string keys are excluded');
3245
3246
			st.test('excluding symbols', { skip: !v.hasSymbols }, function (s2t) {
3247
				var source = {};
3248
				forEach(v.symbols, function (symbol) {
3249
					source[symbol] = true;
3250
				});
3251
3252
				var includedSymbols = v.symbols.slice(1);
3253
				var excludedSymbols = v.symbols.slice(0, 1);
3254
				var target = ES.CopyDataProperties({}, source, excludedSymbols);
3255
3256
				forEach(includedSymbols, function (symbol) {
3257
					s2t.equal(has(target, symbol), true, debug(symbol) + ' is included');
3258
				});
3259
3260
				forEach(excludedSymbols, function (symbol) {
3261
					s2t.equal(has(target, symbol), false, debug(symbol) + ' is excluded');
3262
				});
3263
3264
				s2t.end();
3265
			});
3266
3267
			st.end();
3268
		});
3269
3270
		t.end();
3271
	});
3272
3273
	test('PromiseResolve', function (t) {
3274
		t.test('Promises unsupported', { skip: typeof Promise === 'function' }, function (st) {
3275
			st['throws'](
3276
				function () { ES.PromiseResolve(); },
3277
				SyntaxError,
3278
				'Promises are not supported'
3279
			);
3280
			st.end();
3281
		});
3282
3283
		t.test('Promises supported', { skip: typeof Promise !== 'function' }, function (st) {
3284
			st.plan(2);
3285
3286
			var a = {};
3287
			var b = {};
3288
			var fulfilled = Promise.resolve(a);
3289
			var rejected = Promise.reject(b);
3290
3291
			ES.PromiseResolve(Promise, fulfilled).then(function (x) {
3292
				st.equal(x, a, 'fulfilled promise resolves to fulfilled');
3293
			});
3294
3295
			ES.PromiseResolve(Promise, rejected)['catch'](function (e) {
3296
				st.equal(e, b, 'rejected promise resolves to rejected');
3297
			});
3298
		});
3299
3300
		t.end();
3301
	});
3302
3303
	test('EnumerableOwnPropertyNames', { skip: skips && skips.EnumerableOwnPropertyNames }, function (t) {
3304
		var obj = testEnumerableOwnNames(t, function (O) {
3305
			return ES.EnumerableOwnPropertyNames(O, 'key');
3306
		});
3307
3308
		t.deepEqual(
3309
			ES.EnumerableOwnPropertyNames(obj, 'value'),
3310
			[obj.own],
3311
			'returns enumerable own values'
3312
		);
3313
3314
		t.deepEqual(
3315
			ES.EnumerableOwnPropertyNames(obj, 'key+value'),
3316
			[['own', obj.own]],
3317
			'returns enumerable own entries'
3318
		);
3319
3320
		t.end();
3321
	});
3322
3323
	test('IsPromise', { skip: typeof Promise !== 'function' }, function (t) {
3324
		forEach(v.objects.concat(v.primitives), function (nonPromise) {
3325
			t.equal(ES.IsPromise(nonPromise), false, debug(nonPromise) + ' is not a Promise');
3326
		});
3327
3328
		var thenable = { then: Promise.prototype.then };
3329
		t.equal(ES.IsPromise(thenable), false, 'generic thenable is not a Promise');
3330
3331
		t.equal(ES.IsPromise(Promise.resolve()), true, 'Promise is a Promise');
3332
3333
		t.end();
3334
	});
3335
3336
	test('GetSubstitution (ES2018+)', function (t) {
3337
		forEach(v.nonStrings, function (nonString) {
3338
			t['throws'](
3339
				function () { ES.GetSubstitution(nonString, '', 0, [], undefined, ''); },
3340
				TypeError,
3341
				'`matched`: ' + debug(nonString) + ' is not a String'
3342
			);
3343
3344
			t['throws'](
3345
				function () { ES.GetSubstitution('', nonString, 0, [], undefined, ''); },
3346
				TypeError,
3347
				'`str`: ' + debug(nonString) + ' is not a String'
3348
			);
3349
3350
			t['throws'](
3351
				function () { ES.GetSubstitution('', '', 0, [], undefined, nonString); },
3352
				TypeError,
3353
				'`replacement`: ' + debug(nonString) + ' is not a String'
3354
			);
3355
3356
			t['throws'](
3357
				function () { ES.GetSubstitution('', '', 0, [nonString], undefined, ''); },
3358
				TypeError,
3359
				'`captures`: ' + debug([nonString]) + ' is not an Array of strings'
3360
			);
3361
		});
3362
3363
		forEach(v.nonIntegerNumbers.concat([-1, -42, -Infinity]), function (nonNonNegativeInteger) {
3364
			t['throws'](
3365
				function () { ES.GetSubstitution('', '', nonNonNegativeInteger, [], undefined, ''); },
3366
				TypeError,
3367
				'`position`: ' + debug(nonNonNegativeInteger) + ' is not a non-negative integer'
3368
			);
3369
		});
3370
3371
		forEach(v.nonArrays, function (nonArray) {
3372
			t['throws'](
3373
				function () { ES.GetSubstitution('', '', 0, nonArray, undefined, ''); },
3374
				TypeError,
3375
				'`captures`: ' + debug(nonArray) + ' is not an Array'
3376
			);
3377
		});
3378
3379
		t.equal(
3380
			ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, '123'),
3381
			'123',
3382
			'returns the substitution'
3383
		);
3384
		t.equal(
3385
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '$$2$'),
3386
			'$2$',
3387
			'supports $$, and trailing $'
3388
		);
3389
3390
		t.equal(
3391
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$&<'),
3392
			'>abcdef<',
3393
			'supports $&'
3394
		);
3395
3396
		t.equal(
3397
			ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$`<'),
3398
			'><',
3399
			'supports $` at position 0'
3400
		);
3401
		t.equal(
3402
			ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, '>$`<'),
3403
			'>ab<',
3404
			'supports $` at position > 0'
3405
		);
3406
3407
		t.equal(
3408
			ES.GetSubstitution('def', 'abcdefghi', 7, [], undefined, ">$'<"),
3409
			'><',
3410
			"supports $' at a position where there's less than `matched.length` chars left"
3411
		);
3412
		t.equal(
3413
			ES.GetSubstitution('def', 'abcdefghi', 3, [], undefined, ">$'<"),
3414
			'>ghi<',
3415
			"supports $' at a position where there's more than `matched.length` chars left"
3416
		);
3417
3418
		for (var i = 0; i < 100; i += 1) {
3419
			var captures = [];
3420
			captures[i] = 'test';
3421
			if (i > 0) {
3422
				t.equal(
3423
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$' + i + '<'),
3424
					'>undefined<',
3425
					'supports $' + i + ' with no captures'
3426
				);
3427
				t.equal(
3428
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$' + i),
3429
					'>undefined',
3430
					'supports $' + i + ' at the end of the replacement, with no captures'
3431
				);
3432
				t.equal(
3433
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$' + i + '<'),
3434
					'><',
3435
					'supports $' + i + ' with a capture at that index'
3436
				);
3437
				t.equal(
3438
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$' + i),
3439
					'>',
3440
					'supports $' + i + ' at the end of the replacement, with a capture at that index'
3441
				);
3442
			}
3443
			if (i < 10) {
3444
				t.equal(
3445
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$0' + i + '<'),
3446
					i === 0 ? '><' : '>undefined<',
3447
					'supports $0' + i + ' with no captures'
3448
				);
3449
				t.equal(
3450
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, [], undefined, '>$0' + i),
3451
					i === 0 ? '>' : '>undefined',
3452
					'supports $0' + i + ' at the end of the replacement, with no captures'
3453
				);
3454
				t.equal(
3455
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$0' + i + '<'),
3456
					'><',
3457
					'supports $0' + i + ' with a capture at that index'
3458
				);
3459
				t.equal(
3460
					ES.GetSubstitution('abcdef', 'abcdefghi', 0, captures, undefined, '>$0' + i),
3461
					'>',
3462
					'supports $0' + i + ' at the end of the replacement, with a capture at that index'
3463
				);
3464
			}
3465
		}
3466
3467
		t.end();
3468
	});
3469
};
3470
3471
var es2019 = function ES2018(ES, ops, expectedMissing, skips) {
3472
	es2018(ES, ops, expectedMissing, assign({}, skips, {
3473
	}));
3474
3475
	test('AddEntriesFromIterable', function (t) {
3476
		t['throws'](
3477
			function () { ES.AddEntriesFromIterable({}, undefined, function () {}); },
3478
			TypeError,
3479
			'iterable must not be undefined'
3480
		);
3481
		t['throws'](
3482
			function () { ES.AddEntriesFromIterable({}, null, function () {}); },
3483
			TypeError,
3484
			'iterable must not be null'
3485
		);
3486
		forEach(v.nonFunctions, function (nonFunction) {
3487
			t['throws'](
3488
				function () { ES.AddEntriesFromIterable({}, {}, nonFunction); },
3489
				TypeError,
3490
				debug(nonFunction) + ' is not a function'
3491
			);
3492
		});
3493
3494
		t.test('Symbol support', { skip: !v.hasSymbols }, function (st) {
3495
			st.plan(4);
3496
3497
			var O = {};
3498
			st.equal(ES.AddEntriesFromIterable(O, [], function () {}), O, 'returns the target');
3499
3500
			var adder = function (key, value) {
3501
				st.equal(this, O, 'adder gets proper receiver');
3502
				st.equal(key, 0, 'k is key');
3503
				st.equal(value, 'a', 'v is value');
3504
			};
3505
			ES.AddEntriesFromIterable(O, ['a'].entries(), adder);
3506
3507
			st.end();
3508
		});
3509
3510
		t.end();
3511
	});
3512
3513
	test('FlattenIntoArray', function (t) {
3514
		t.test('no mapper function', function (st) {
3515
			var testDepth = function testDepth(tt, depth, expected) {
3516
				var a = [];
3517
				var o = [[1], 2, , [[3]], [], 4, [[[[5]]]]]; // eslint-disable-line no-sparse-arrays
3518
				ES.FlattenIntoArray(a, o, o.length, 0, depth);
3519
				tt.deepEqual(a, expected, 'depth: ' + depth);
3520
			};
3521
3522
			testDepth(st, 1, [1, 2, [3], 4, [[[5]]]]);
3523
			testDepth(st, 2, [1, 2, 3, 4, [[5]]]);
3524
			testDepth(st, 3, [1, 2, 3, 4, [5]]);
3525
			testDepth(st, 4, [1, 2, 3, 4, 5]);
3526
			testDepth(st, Infinity, [1, 2, 3, 4, 5]);
3527
			st.end();
3528
		});
3529
3530
		t.test('mapper function', function (st) {
3531
			var testMapper = function testMapper(tt, mapper, expected, thisArg) {
3532
				var a = [];
3533
				var o = [[1], 2, , [[3]], [], 4, [[[[5]]]]]; // eslint-disable-line no-sparse-arrays
3534
				ES.FlattenIntoArray(a, o, o.length, 0, 1, mapper, thisArg);
3535
				tt.deepEqual(a, expected);
3536
			};
3537
3538
			var double = function double(x) {
3539
				return typeof x === 'number' ? 2 * x : x;
3540
			};
3541
			testMapper(
3542
				st,
3543
				double,
3544
				[1, 4, [3], 8, [[[5]]]]
3545
			);
3546
			testMapper(
3547
				st,
3548
				function (x) { return [this, double(x)]; },
3549
				[42, [1], 42, 4, 42, [[3]], 42, [], 42, 8, 42, [[[[5]]]]],
3550
				42
3551
			);
3552
			st.end();
3553
		});
3554
3555
		t.end();
3556
	});
3557
3558
	test('TrimString', function (t) {
3559
		t.test('non-object string', function (st) {
3560
			forEach(v.nullPrimitives, function (nullish) {
3561
				st['throws'](
3562
					function () { ES.TrimString(nullish); },
3563
					debug(nullish) + ' is not an Object'
3564
				);
3565
			});
3566
			st.end();
3567
		});
3568
3569
		var string = ' \n abc  \n ';
3570
		t.equal(ES.TrimString(string, 'start'), string.slice(string.indexOf('a')));
3571
		t.equal(ES.TrimString(string, 'end'), string.slice(0, string.lastIndexOf('c') + 1));
3572
		t.equal(ES.TrimString(string, 'start+end'), string.slice(string.indexOf('a'), string.lastIndexOf('c') + 1));
3573
3574
		t.end();
3575
	});
3576
};
3577
3578
module.exports = {
3579
	es2015: es2015,
3580
	es2016: es2016,
3581
	es2017: es2017,
3582
	es2018: es2018,
3583
	es2019: es2019
3584
};
3585