UNPKG

19.9 kBJavaScriptView Raw
1var arePropertyDescriptorsSupported = function () {
2 try {
3 Object.defineProperty({}, 'x', {});
4 return true;
5 } catch (e) { /* this is IE 8. */
6 return false;
7 }
8};
9var supportsDescriptors = !!Object.defineProperty && arePropertyDescriptorsSupported();
10var functionsHaveNames = function f() {}.name === 'f';
11
12var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';
13var ifSymbolsIt = hasSymbols ? it : xit;
14var describeIfGetProto = Object.getPrototypeOf ? describe : xdescribe;
15var describeIfSetProto = Object.setPrototypeOf ? describe : xdescribe;
16var describeIfES5 = supportsDescriptors ? describe : xdescribe;
17var describeIfExtensionsPreventible = Object.preventExtensions ? describe : xdescribe;
18var describeIfGetOwnPropertyNames = Object.getOwnPropertyNames ? describe : xdescribe;
19var ifExtensionsPreventibleIt = Object.preventExtensions ? it : xit;
20var ifES5It = supportsDescriptors ? it : xit;
21var ifFreezeIt = typeof Object.freeze === 'function' ? it : xit;
22var ifFunctionsHaveNamesIt = functionsHaveNames ? it : xit;
23var ifShimIt = (typeof process !== 'undefined' && process.env.NO_ES6_SHIM) ? it.skip : it;
24
25describe('Reflect', function () {
26 if (typeof Reflect === 'undefined') {
27 return it('exists', function () {
28 expect(this).to.have.property('Reflect');
29 });
30 }
31
32 var object = {
33 something: 1,
34 _value: 0
35 };
36
37 if (supportsDescriptors) {
38 /* eslint-disable accessor-pairs */
39 Object.defineProperties(object, {
40 value: {
41 get: function () {
42 return this._value;
43 }
44 },
45
46 setter: {
47 set: function (val) {
48 this._value = val;
49 }
50 },
51
52 bool: {
53 value: true
54 }
55 });
56 /* eslint-enable accessor-pairs */
57 }
58
59 var testXThrow = function (values, func) {
60 var checker = function checker(item) {
61 try {
62 func(item);
63 return false;
64 } catch (e) {
65 return e instanceof TypeError;
66 }
67 };
68
69 values.forEach(function (item) {
70 expect(item).to.satisfy(checker);
71 });
72 };
73
74 var testCallableThrow = testXThrow.bind(null, [null, undefined, 1, 'string', true, [], {}]);
75
76 var testPrimitiveThrow = testXThrow.bind(null, [null, undefined, 1, 'string', true]);
77
78 ifShimIt('is on the exported object', function () {
79 var exported = require('../');
80 expect(exported.Reflect).to.equal(Reflect);
81 });
82
83 describe('.apply()', function () {
84 if (typeof Reflect.apply === 'undefined') {
85 return it('exists', function () {
86 expect(Reflect).to.have.property('apply');
87 });
88 }
89
90 it('is a function', function () {
91 expect(typeof Reflect.apply).to.equal('function');
92 });
93
94 ifFunctionsHaveNamesIt('has the right name', function () {
95 expect(Reflect.apply.name).to.equal('apply');
96 });
97
98 it('throws if target isn’t callable', function () {
99 testCallableThrow(function (item) {
100 return Reflect.apply(item, null, []);
101 });
102 });
103
104 it('works also with redefined apply', function () {
105 expect(Reflect.apply(Array.prototype.push, [1, 2], [3, 4, 5])).to.equal(5);
106
107 var F = function F(a, b, c) {
108 return a + b + c;
109 };
110
111 F.apply = false;
112
113 expect(Reflect.apply(F, null, [1, 2, 3])).to.equal(6);
114
115 var G = function G(last) {
116 return this.x + 'lo' + last;
117 };
118
119 G.apply = function nop() {};
120
121 expect(Reflect.apply(G, { x: 'yel' }, ['!'])).to.equal('yello!');
122 });
123 });
124
125 describe('.construct()', function () {
126 if (typeof Reflect.construct === 'undefined') {
127 return it('exists', function () {
128 expect(Reflect).to.have.property('construct');
129 });
130 }
131
132 it('is a function', function () {
133 expect(typeof Reflect.construct).to.equal('function');
134 });
135
136 ifFunctionsHaveNamesIt('has the right name', function () {
137 expect(Reflect.construct.name).to.equal('construct');
138 });
139
140 it('throws if target isn’t callable', function () {
141 testCallableThrow(function (item) {
142 return Reflect.apply(item, null, []);
143 });
144 });
145
146 it('works also with redefined apply', function () {
147 var C = function C(a, b, c) {
148 this.qux = [a, b, c].join('|');
149 };
150
151 C.apply = undefined;
152
153 expect(Reflect.construct(C, ['foo', 'bar', 'baz']).qux).to.equal('foo|bar|baz');
154 });
155
156 it('correctly handles newTarget param', function () {
157 var F = function F() {};
158 expect(Reflect.construct(function () {}, [], F) instanceof F).to.equal(true);
159 });
160 });
161
162 describeIfES5('.defineProperty()', function () {
163 if (typeof Reflect.defineProperty === 'undefined') {
164 return it('exists', function () {
165 expect(Reflect).to.have.property('defineProperty');
166 });
167 }
168
169 it('is a function', function () {
170 expect(typeof Reflect.defineProperty).to.equal('function');
171 });
172
173 ifFunctionsHaveNamesIt('has the right name', function () {
174 expect(Reflect.defineProperty.name).to.equal('defineProperty');
175 });
176
177 it('throws if the target isn’t an object', function () {
178 testPrimitiveThrow(function (item) {
179 return Reflect.defineProperty(item, 'prop', { value: true });
180 });
181 });
182
183 ifExtensionsPreventibleIt('returns false for non-extensible objects', function () {
184 var o = Object.preventExtensions({});
185
186 expect(Reflect.defineProperty(o, 'prop', {})).to.equal(false);
187 });
188
189 it('can return true, even for non-configurable, non-writable properties', function () {
190 var o = {};
191 var desc = {
192 value: 13,
193 enumerable: false,
194 writable: false,
195 configurable: false
196 };
197
198 expect(Reflect.defineProperty(o, 'prop', desc)).to.equal(true);
199
200 // Defined as non-configurable, but descriptor is identical.
201 expect(Reflect.defineProperty(o, 'prop', desc)).to.equal(true);
202
203 desc.value = 37; // Change
204
205 expect(Reflect.defineProperty(o, 'prop', desc)).to.equal(false);
206 });
207
208 it('can change from one property type to another, if configurable', function () {
209 var o = {};
210
211 var desc1 = {
212 set: function () {},
213 configurable: true
214 };
215
216 var desc2 = {
217 value: 13,
218 configurable: false
219 };
220
221 var desc3 = {
222 get: function () {}
223 };
224
225 expect(Reflect.defineProperty(o, 'prop', desc1)).to.equal(true);
226
227 expect(Reflect.defineProperty(o, 'prop', desc2)).to.equal(true);
228
229 expect(Reflect.defineProperty(o, 'prop', desc3)).to.equal(false);
230 });
231 });
232
233 describe('.deleteProperty()', function () {
234 if (typeof Reflect.deleteProperty === 'undefined') {
235 return it('exists', function () {
236 expect(Reflect).to.have.property('deleteProperty');
237 });
238 }
239
240 it('is a function', function () {
241 expect(typeof Reflect.deleteProperty).to.equal('function');
242 });
243
244 ifFunctionsHaveNamesIt('has the right name', function () {
245 expect(Reflect.deleteProperty.name).to.equal('deleteProperty');
246 });
247
248 it('throws if the target isn’t an object', function () {
249 testPrimitiveThrow(function (item) {
250 return Reflect.deleteProperty(item, 'prop');
251 });
252 });
253
254 ifES5It('returns true for success and false for failure', function () {
255 var o = { a: 1 };
256
257 Object.defineProperty(o, 'b', { value: 2 });
258
259 expect(o).to.have.property('a');
260 expect(o).to.have.property('b');
261 expect(o.a).to.equal(1);
262 expect(o.b).to.equal(2);
263
264 expect(Reflect.deleteProperty(o, 'a')).to.equal(true);
265
266 expect(o).not.to.have.property('a');
267 expect(o.b).to.equal(2);
268
269 expect(Reflect.deleteProperty(o, 'b')).to.equal(false);
270
271 expect(o).to.have.property('b');
272 expect(o.b).to.equal(2);
273
274 expect(Reflect.deleteProperty(o, 'a')).to.equal(true);
275 });
276
277 it('cannot delete an array’s length property', function () {
278 expect(Reflect.deleteProperty([], 'length')).to.equal(false);
279 });
280 });
281
282 describeIfES5('.get()', function () {
283 if (typeof Reflect.get === 'undefined') {
284 return it('exists', function () {
285 expect(Reflect).to.have.property('get');
286 });
287 }
288
289 it('is a function', function () {
290 expect(typeof Reflect.get).to.equal('function');
291 });
292
293 ifFunctionsHaveNamesIt('has the right name', function () {
294 expect(Reflect.get.name).to.equal('get');
295 });
296
297 it('throws on null and undefined', function () {
298 [null, undefined].forEach(function (item) {
299 expect(function () {
300 return Reflect.get(item, 'property');
301 }).to['throw'](TypeError);
302 });
303 });
304
305 it('can retrieve a simple value, from the target', function () {
306 var p = { something: 2, bool: false };
307
308 expect(Reflect.get(object, 'something')).to.equal(1);
309 // p has no effect
310 expect(Reflect.get(object, 'something', p)).to.equal(1);
311
312 // Value-defined properties take the target's value,
313 // and ignore that of the receiver.
314 expect(Reflect.get(object, 'bool', p)).to.equal(true);
315
316 // Undefined values
317 expect(Reflect.get(object, 'undefined_property')).to.equal(undefined);
318 });
319
320 it('will invoke getters on the receiver rather than target', function () {
321 var other = { _value: 1337 };
322
323 expect(Reflect.get(object, 'value', other)).to.equal(1337);
324
325 // No getter for setter property
326 expect(Reflect.get(object, 'setter', other)).to.equal(undefined);
327 });
328
329 it('will search the prototype chain', function () {
330 var other = Object.create(object);
331 other._value = 17;
332
333 var yetAnother = { _value: 4711 };
334
335 expect(Reflect.get(other, 'value', yetAnother)).to.equal(4711);
336
337 expect(Reflect.get(other, 'bool', yetAnother)).to.equal(true);
338 });
339 });
340
341 describeIfES5('.set()', function () {
342 if (typeof Reflect.set === 'undefined') {
343 return it('exists', function () {
344 expect(Reflect).to.have.property('set');
345 });
346 }
347
348 it('is a function', function () {
349 expect(typeof Reflect.set).to.equal('function');
350 });
351
352 ifFunctionsHaveNamesIt('has the right name', function () {
353 expect(Reflect.set.name).to.equal('set');
354 });
355
356 it('throws if the target isn’t an object', function () {
357 testPrimitiveThrow(function (item) {
358 return Reflect.set(item, 'prop', 'value');
359 });
360 });
361
362 it('sets values on receiver', function () {
363 var target = {};
364 var receiver = {};
365
366 expect(Reflect.set(target, 'foo', 1, receiver)).to.equal(true);
367
368 expect('foo' in target).to.equal(false);
369 expect(receiver.foo).to.equal(1);
370
371 expect(Reflect.defineProperty(receiver, 'bar', {
372 value: 0,
373 writable: true,
374 enumerable: false,
375 configurable: true
376 })).to.equal(true);
377
378 expect(Reflect.set(target, 'bar', 1, receiver)).to.equal(true);
379 expect(receiver.bar).to.equal(1);
380 expect(Reflect.getOwnPropertyDescriptor(receiver, 'bar').enumerable).to.equal(false);
381
382 var out;
383 /* eslint-disable accessor-pairs */
384 target = Object.create({}, {
385 o: {
386 set: function () { out = this; }
387 }
388 });
389 /* eslint-enable accessor-pairs */
390
391 expect(Reflect.set(target, 'o', 17, receiver)).to.equal(true);
392 expect(out).to.equal(receiver);
393 });
394 });
395
396 describeIfES5('.getOwnPropertyDescriptor()', function () {
397 if (typeof Reflect.getOwnPropertyDescriptor === 'undefined') {
398 return it('exists', function () {
399 expect(Reflect).to.have.property('getOwnPropertyDescriptor');
400 });
401 }
402
403 it('is a function', function () {
404 expect(typeof Reflect.getOwnPropertyDescriptor).to.equal('function');
405 });
406
407 ifFunctionsHaveNamesIt('has the right name', function () {
408 expect(Reflect.getOwnPropertyDescriptor.name).to.equal('getOwnPropertyDescriptor');
409 });
410
411 it('throws if the target isn’t an object', function () {
412 testPrimitiveThrow(function (item) {
413 return Reflect.getOwnPropertyDescriptor(item, 'prop');
414 });
415 });
416
417 it('retrieves property descriptors', function () {
418 var obj = { a: 4711 };
419
420 var desc = Reflect.getOwnPropertyDescriptor(obj, 'a');
421
422 expect(desc).to.deep.equal({
423 value: 4711,
424 configurable: true,
425 writable: true,
426 enumerable: true
427 });
428 });
429 });
430
431 describeIfGetProto('.getPrototypeOf()', function () {
432 if (typeof Reflect.getPrototypeOf === 'undefined') {
433 return it('exists', function () {
434 expect(Reflect).to.have.property('getPrototypeOf');
435 });
436 }
437
438 it('is a function', function () {
439 expect(typeof Reflect.getPrototypeOf).to.equal('function');
440 });
441
442 ifFunctionsHaveNamesIt('has the right name', function () {
443 expect(Reflect.getPrototypeOf.name).to.equal('getPrototypeOf');
444 });
445
446 it('throws if the target isn’t an object', function () {
447 testPrimitiveThrow(function (item) {
448 return Reflect.getPrototypeOf(item);
449 });
450 });
451
452 it('retrieves prototypes', function () {
453 expect(Reflect.getPrototypeOf(Object.create(null))).to.equal(null);
454
455 expect(Reflect.getPrototypeOf([])).to.equal(Array.prototype);
456 });
457 });
458
459 describe('.has()', function () {
460 if (typeof Reflect.has === 'undefined') {
461 return it('exists', function () {
462 expect(Reflect).to.have.property('has');
463 });
464 }
465
466 it('is a function', function () {
467 expect(typeof Reflect.has).to.equal('function');
468 });
469
470 ifFunctionsHaveNamesIt('has the right name', function () {
471 expect(Reflect.has.name).to.equal('has');
472 });
473
474 it('throws if the target isn’t an object', function () {
475 testPrimitiveThrow(function (item) {
476 return Reflect.has(item, 'prop');
477 });
478 });
479
480 it('will detect own properties', function () {
481 var target = Object.create ? Object.create(null) : {};
482
483 expect(Reflect.has(target, 'prop')).to.equal(false);
484
485 target.prop = undefined;
486 expect(Reflect.has(target, 'prop')).to.equal(true);
487
488 delete target.prop;
489 expect(Reflect.has(target, 'prop')).to.equal(false);
490
491 expect(Reflect.has(Reflect.has, 'length')).to.equal(true);
492 });
493
494 ifES5It('will detect an own accessor property', function () {
495 var target = Object.create(null);
496 /* eslint-disable accessor-pairs */
497 Object.defineProperty(target, 'accessor', {
498 set: function () {}
499 });
500 /* eslint-enable accessor-pairs */
501
502 expect(Reflect.has(target, 'accessor')).to.equal(true);
503 });
504
505 it('will search the prototype chain', function () {
506 var Parent = function () {};
507 Parent.prototype.someProperty = undefined;
508
509 var Child = function () {};
510 Child.prototype = new Parent();
511
512 var target = new Child();
513 target.bool = true;
514
515 expect(Reflect.has(target, 'bool')).to.equal(true);
516 expect(Reflect.has(target, 'someProperty')).to.equal(true);
517 expect(Reflect.has(target, 'undefinedProperty')).to.equal(false);
518 });
519 });
520
521 describeIfExtensionsPreventible('.isExtensible()', function () {
522 if (typeof Reflect.isExtensible === 'undefined') {
523 return it('exists', function () {
524 expect(Reflect).to.have.property('isExtensible');
525 });
526 }
527
528 it('is a function', function () {
529 expect(typeof Reflect.isExtensible).to.equal('function');
530 });
531
532 ifFunctionsHaveNamesIt('has the right name', function () {
533 expect(Reflect.isExtensible.name).to.equal('isExtensible');
534 });
535
536 it('returns true for plain objects', function () {
537 expect(Reflect.isExtensible({})).to.equal(true);
538 expect(Reflect.isExtensible(Object.preventExtensions({}))).to.equal(false);
539 });
540
541 it('throws if the target isn’t an object', function () {
542 testPrimitiveThrow(function (item) {
543 return Reflect.isExtensible(item);
544 });
545 });
546 });
547
548 describeIfGetOwnPropertyNames('.ownKeys()', function () {
549 if (typeof Reflect.ownKeys === 'undefined') {
550 return it('exists', function () {
551 expect(Reflect).to.have.property('ownKeys');
552 });
553 }
554
555 it('is a function', function () {
556 expect(typeof Reflect.ownKeys).to.equal('function');
557 });
558
559 ifFunctionsHaveNamesIt('has the right name', function () {
560 expect(Reflect.ownKeys.name).to.equal('ownKeys');
561 });
562
563 it('throws if the target isn’t an object', function () {
564 testPrimitiveThrow(function (item) {
565 return Reflect.ownKeys(item);
566 });
567 });
568
569 it('should return the same result as Object.getOwnPropertyNames if there are no Symbols', function () {
570 var obj = { foo: 1, bar: 2 };
571
572 obj[1] = 'first';
573
574 var result = Object.getOwnPropertyNames(obj);
575
576 // Reflect.ownKeys depends on the implementation of
577 // Object.getOwnPropertyNames, at least for non-symbol keys.
578 expect(Reflect.ownKeys(obj)).to.deep.equal(result);
579
580 // We can only be sure of which keys should exist.
581 expect(result.sort()).to.deep.equal(['1', 'bar', 'foo']);
582 });
583
584 ifSymbolsIt('symbols come last', function () {
585 var s = Symbol();
586
587 var o = {
588 'non-symbol': true
589 };
590
591 o[s] = true;
592
593 expect(Reflect.ownKeys(o)).to.deep.equal(['non-symbol', s]);
594 });
595 });
596
597 describeIfExtensionsPreventible('.preventExtensions()', function () {
598 if (typeof Reflect.preventExtensions === 'undefined') {
599 return it('exists', function () {
600 expect(Reflect).to.have.property('preventExtensions');
601 });
602 }
603
604 it('is a function', function () {
605 expect(typeof Reflect.preventExtensions).to.equal('function');
606 });
607
608 ifFunctionsHaveNamesIt('has the right name', function () {
609 expect(Reflect.preventExtensions.name).to.equal('preventExtensions');
610 });
611
612 it('throws if the target isn’t an object', function () {
613 testPrimitiveThrow(function (item) {
614 return Reflect.preventExtensions(item);
615 });
616 });
617
618 it('prevents extensions on objects', function () {
619 var obj = {};
620 Reflect.preventExtensions(obj);
621 expect(Object.isExtensible(obj)).to.equal(false);
622 });
623 });
624
625 describeIfSetProto('.setPrototypeOf()', function () {
626 if (typeof Reflect.setPrototypeOf === 'undefined') {
627 return it('exists', function () {
628 expect(Reflect).to.have.property('setPrototypeOf');
629 });
630 }
631
632 it('is a function', function () {
633 expect(typeof Reflect.setPrototypeOf).to.equal('function');
634 });
635
636 ifFunctionsHaveNamesIt('has the right name', function () {
637 expect(Reflect.setPrototypeOf.name).to.equal('setPrototypeOf');
638 });
639
640 it('throws if the target isn’t an object', function () {
641 testPrimitiveThrow(function (item) {
642 return Reflect.setPrototypeOf(item, null);
643 });
644 });
645
646 it('throws if the prototype is neither object nor null', function () {
647 var o = {};
648
649 [undefined, 1, 'string', true].forEach(function (item) {
650 expect(function () {
651 return Reflect.setPrototypeOf(o, item);
652 }).to['throw'](TypeError);
653 });
654 });
655
656 it('can set prototypes, and returns true on success', function () {
657 var obj = {};
658
659 expect(Reflect.setPrototypeOf(obj, Array.prototype)).to.equal(true);
660 expect(obj).to.be.an.instanceOf(Array);
661
662 expect(obj.toString).not.to.equal(undefined);
663 expect(Reflect.setPrototypeOf(obj, null)).to.equal(true);
664 expect(obj.toString).to.equal(undefined);
665 });
666
667 ifFreezeIt('is returns false on failure', function () {
668 var obj = Object.freeze({});
669
670 expect(Reflect.setPrototypeOf(obj, null)).to.equal(false);
671 });
672
673 it('fails when attempting to create a circular prototype chain', function () {
674 var o = {};
675
676 expect(Reflect.setPrototypeOf(o, o)).to.equal(false);
677 });
678 });
679});