UNPKG

25.9 kBJavaScriptView Raw
1'use strict';
2
3var test = require('tape');
4require('./_tape');
5var assign = require('object.assign');
6var gOPDs = require('object.getownpropertydescriptors');
7var hasSymbols = require('has-symbols')();
8var hasTypedArrays = require('has-typed-arrays')();
9var semver = require('semver');
10
11var safeBuffer = typeof Buffer === 'function' ? Buffer.from && Buffer.from.length > 1 ? Buffer.from : Buffer : null;
12var buffersAreTypedArrays = typeof Buffer === 'function' && new Buffer(0) instanceof Uint8Array;
13
14var isNode = typeof process === 'object' && typeof process.version === 'string';
15
16function tag(obj, value) {
17 if (hasSymbols && Symbol.toStringTag && Object.defineProperty) {
18 Object.defineProperty(obj, Symbol.toStringTag, {
19 value: value
20 });
21 }
22 return obj;
23}
24
25// eslint-disable-next-line no-proto
26var hasDunderProto = [].__proto__ === Array.prototype;
27
28test('equal', function (t) {
29 t.deepEqualTest(
30 { a: [2, 3], b: [4] },
31 { a: [2, 3], b: [4] },
32 'two equal objects',
33 true,
34 true,
35 false
36 );
37
38 t.deepEqualTest(
39 { a: 2, b: '4' },
40 { a: 2, b: 4 },
41 'two loosely equal, strictly inequal objects',
42 true,
43 false
44 );
45
46 t.deepEqualTest(
47 { a: 2, b: 4 },
48 { a: 2, B: 4 },
49 'two inequal objects',
50 false,
51 false
52 );
53
54 t.deepEqualTest(
55 '-000',
56 false,
57 '`false` and `"-000"`',
58 true,
59 false
60 );
61
62 t.end();
63});
64
65test('Maps', { skip: typeof Map !== 'function' }, function (t) {
66 t.deepEqualTest(
67 new Map([['a', 1], ['b', 2]]),
68 new Map([['b', 2], ['a', 1]]),
69 'two equal Maps',
70 true,
71 true
72 );
73
74 t.deepEqualTest(
75 new Map([['a', [1, 2]]]),
76 new Map([['a', [2, 1]]]),
77 'two Maps with inequal values on the same key',
78 false,
79 false
80 );
81
82 t.deepEqualTest(
83 new Map([['a', 1]]),
84 new Map([['b', 1]]),
85 'two inequal Maps',
86 false,
87 false
88 );
89
90 t.deepEqualTest(
91 new Map([[{}, 3], [{}, 2], [{}, 1]]),
92 new Map([[{}, 1], [{}, 2], [{}, 3]]),
93 'two equal Maps in different orders with object keys',
94 true,
95 true
96 );
97
98 t.deepEqualTest(
99 new Map([[undefined, undefined]]),
100 new Map([[undefined, null]]),
101 'undefined keys, nullish values, loosely equal, strictly inequal',
102 true,
103 false
104 );
105
106 t.deepEqualTest(
107 new Map([[{}, null], [true, 2], [{}, 1], [undefined, {}]]),
108 new Map([[{}, 1], [true, 2], [{}, null], [undefined, {}]]),
109 'two equal Maps in different orders with primitive keys',
110 true,
111 true
112 );
113
114 t.deepEqualTest(
115 new Map([[false, 3], [{}, 2], [{}, 1]]),
116 new Map([[{}, 1], [{}, 2], [false, 3]]),
117 'two equal Maps in different orders with a mix of keys',
118 true,
119 true
120 );
121
122 t.deepEqualTest(
123 new Map([[null, undefined]]),
124 new Map([[null, null]]),
125 'null keys, nullish values, loosely equal, strictly inequal',
126 true,
127 false
128 );
129
130 t.deepEqualTest(
131 new Map([[undefined, 3]]),
132 new Map([[null, 3]]),
133 'nullish keys, loosely equal, strictly inequal',
134 true,
135 false
136 );
137
138 t.deepEqualTest(
139 new Map([[{}, null], [true, 2], [{}, 1], [undefined, {}]]),
140 new Map([[{}, 1], [true, 2], [{}, null], [undefined, {}]]),
141 'two equal Maps in different orders with primitive keys',
142 true,
143 true
144 );
145
146 t.deepEqualTest(
147 new Map([[false, 3], [{}, 2], [{}, 1]]),
148 new Map([[{}, 1], [{}, 2], [false, 3]]),
149 'two equal Maps in different orders with a mix of keys',
150 true,
151 true
152 );
153
154 t.deepEqualTest(
155 new Map(),
156 new Map([[{}, 1]]),
157 'two inequal Maps',
158 false,
159 false
160 );
161
162 t.deepEqualTest(
163 new Map([[{}, null], [false, 3]]),
164 new Map([[{}, null], [true, 2]]),
165 'two inequal maps, same size, primitive key, start with object key',
166 false,
167 false
168 );
169
170 t.deepEqualTest(
171 new Map([[false, 3], [{}, null]]),
172 new Map([[true, 2], [{}, null]]),
173 'two inequal maps, same size, primitive key, start with primitive key',
174 false,
175 false
176 );
177
178 t.deepEqualTest(
179 new Map([[undefined, null], ['+000', 2]]),
180 new Map([[null, undefined], [false, '2']]),
181 'primitive comparisons',
182 true,
183 false
184 );
185
186 t.end();
187});
188
189test('WeakMaps', { skip: typeof WeakMap !== 'function' }, function (t) {
190 t.deepEqualTest(
191 new WeakMap([[Object, null], [Function, true]]),
192 new WeakMap([[Function, true], [Object, null]]),
193 'two equal WeakMaps',
194 true,
195 true
196 );
197
198 t.deepEqualTest(
199 new WeakMap([[Object, null]]),
200 new WeakMap([[Object, true]]),
201 'two WeakMaps with inequal values on the same key',
202 true,
203 true
204 );
205
206 t.deepEqualTest(
207 new WeakMap([[Object, null], [Function, true]]),
208 new WeakMap([[Object, null]]),
209 'two inequal WeakMaps',
210 true,
211 true
212 );
213
214 t.end();
215});
216
217test('Sets', { skip: typeof Set !== 'function' }, function (t) {
218 t.deepEqualTest(
219 new Set(['a', 1, 'b', 2]),
220 new Set(['b', 2, 'a', 1]),
221 'two equal Sets',
222 true,
223 true
224 );
225
226 t.deepEqualTest(
227 new Set(['a', 1]),
228 new Set(['b', 1]),
229 'two inequal Sets',
230 false,
231 false
232 );
233
234 t.deepEqualTest(
235 new Set([{}, 1, {}, {}, 2]),
236 new Set([{}, 1, {}, 2, {}]),
237 'two equal Sets in different orders',
238 true,
239 true
240 );
241
242 t.deepEqualTest(
243 new Set(),
244 new Set([1]),
245 'two inequally sized Sets',
246 false,
247 false
248 );
249
250 t.deepEqualTest(
251 new Set([{ a: 1 }, 2]),
252 new Set(['2', { a: '1' }]),
253 'two loosely equal, strictly inequal Sets',
254 true,
255 false
256 );
257
258 t.deepEqualTest(
259 new Set([{ a: 1 }, 2]),
260 new Set(['2', { a: 2 }]),
261 'two inequal Sets',
262 false,
263 false
264 );
265
266 t.deepEqualTest(
267 new Set([null, '', 1, 5, 2, false]),
268 new Set([undefined, 0, '5', true, '2', '-000']),
269 'more primitive comparisons',
270 true,
271 false
272 );
273
274 t.end();
275});
276
277test('Set and Map', { skip: !Object.defineProperty || typeof Set !== 'function' || typeof Map !== 'function' }, function (t) {
278 t.deepEqualTest(
279 new Set(),
280 new Map(),
281 'Map and Set',
282 false,
283 false
284 );
285
286 var maplikeSet = new Set();
287 Object.defineProperty(maplikeSet, 'constructor', { enumerable: false, value: Map });
288 maplikeSet.__proto__ = Map.prototype; // eslint-disable-line no-proto
289 t.deepEqualTest(
290 maplikeSet,
291 new Map(),
292 'Map-like Set, and Map',
293 false,
294 false
295 );
296
297 t.end();
298});
299
300test('WeakSets', { skip: typeof WeakSet !== 'function' }, function (t) {
301 t.deepEqualTest(
302 new WeakSet([Object, Function]),
303 new WeakSet([Function, Object]),
304 'two equal WeakSets',
305 true,
306 true
307 );
308
309 t.deepEqualTest(
310 new WeakSet([Object, Function]),
311 new WeakSet([Object]),
312 'two inequal WeakSets',
313 true,
314 true
315 );
316
317 t.end();
318});
319
320test('not equal', function (t) {
321 t.deepEqualTest(
322 { x: 5, y: [6] },
323 { x: 5, y: 6 },
324 'two inequal objects are',
325 false,
326 false
327 );
328
329 t.end();
330});
331
332test('nested nulls', function (t) {
333 t.deepEqualTest(
334 [null, null, null],
335 [null, null, null],
336 'same-length arrays of nulls',
337 true,
338 true,
339 true
340 );
341 t.end();
342});
343
344test('objects with strings vs numbers', function (t) {
345 t.deepEqualTest(
346 [{ a: 3 }, { b: 4 }],
347 [{ a: '3' }, { b: '4' }],
348 'objects with equivalent string/number values',
349 true,
350 false
351 );
352 t.end();
353});
354
355test('non-objects', function (t) {
356 t.deepEqualTest(3, 3, 'same numbers', true, true, true);
357 t.deepEqualTest('beep', 'beep', 'same strings', true, true, true);
358 t.deepEqualTest('3', 3, 'numeric string and number', true, false);
359 t.deepEqualTest('3', [3], 'numeric string and array containing number', false, false);
360 t.deepEqualTest(3, [3], 'number and array containing number', false, false);
361
362 t.end();
363});
364
365test('infinities', function (t) {
366 t.deepEqualTest(Infinity, Infinity, '∞ and ∞', true, true, true);
367 t.deepEqualTest(-Infinity, -Infinity, '-∞ and -∞', true, true, true);
368 t.deepEqualTest(Infinity, -Infinity, '∞ and -∞', false, false);
369
370 t.end();
371});
372
373test('arguments class', function (t) {
374 function getArgs() {
375 return arguments;
376 }
377
378 t.deepEqualTest(
379 getArgs(1, 2, 3),
380 getArgs(1, 2, 3),
381 'equivalent arguments objects are equal',
382 true,
383 true,
384 true
385 );
386
387 t.deepEqualTest(
388 getArgs(1, 2, 3),
389 [1, 2, 3],
390 'array and arguments with same contents',
391 false,
392 false
393 );
394
395 var args = getArgs();
396 var notArgs = tag({ length: 0 }, 'Arguments');
397 t.deepEqualTest(
398 args,
399 notArgs,
400 'args and similar arraylike object',
401 false,
402 false
403 );
404
405 t.end();
406});
407
408test('Dates', function (t) {
409 var d0 = new Date(1387585278000);
410 var d1 = new Date('Fri Dec 20 2013 16:21:18 GMT-0800 (PST)');
411
412 t.deepEqualTest(d0, d1, 'two Dates with the same timestamp', true, true);
413
414 d1.a = true;
415
416 t.deepEqualTest(d0, d1, 'two Dates with the same timestamp but different own properties', false, false);
417
418 t.test('overriding `getTime`', { skip: !Object.defineProperty }, function (st) {
419 var a = new Date('2000');
420 var b = new Date('2000');
421 Object.defineProperty(a, 'getTime', { value: function () { return 5; } });
422 st.deepEqualTest(a, b, 'two Dates with the same timestamp but one has overridden `getTime`', true, true);
423 st.end();
424 });
425
426 t.test('fake Date', { skip: !hasDunderProto }, function (st) {
427 var a = new Date(2000);
428 var b = tag(Object.create(
429 a.__proto__, // eslint-disable-line no-proto
430 gOPDs(a)
431 ), 'Date');
432
433 st.deepEqualTest(
434 a,
435 b,
436 'Date, and fake Date',
437 false,
438 false
439 );
440
441 st.end();
442 });
443
444 var a = new Date('2000');
445 var b = new Date('2000');
446 b.foo = true;
447 t.deepEqualTest(
448 a,
449 b,
450 'two identical Dates, one with an extra property',
451 false,
452 false
453 );
454
455 t.deepEqualTest(
456 new Date('2000'),
457 new Date('2001'),
458 'two inequal Dates',
459 false,
460 false
461 );
462
463 t.end();
464});
465
466test('buffers', { skip: typeof Buffer !== 'function' }, function (t) {
467 /* eslint no-buffer-constructor: 1, new-cap: 1 */
468 t.deepEqualTest(
469 safeBuffer('xyz'),
470 safeBuffer('xyz'),
471 'buffers with same contents are equal',
472 true,
473 true
474 );
475
476 t.deepEqualTest(
477 safeBuffer('xyz'),
478 safeBuffer('xyy'),
479 'buffers with same length and different contents are inequal',
480 false,
481 false
482 );
483
484 t.deepEqualTest(
485 safeBuffer('xyz'),
486 safeBuffer('xy'),
487 'buffers with different length are inequal',
488 false,
489 false
490 );
491
492 t.deepEqualTest(
493 safeBuffer('abc'),
494 safeBuffer('xyz'),
495 'buffers with different contents',
496 false,
497 false
498 );
499
500 var emptyBuffer = safeBuffer('');
501
502 t.deepEqualTest(
503 emptyBuffer,
504 [],
505 'empty buffer and empty array',
506 false,
507 false
508 );
509
510 t.test('bufferlikes', { skip: !Object.defineProperty || !hasTypedArrays }, function (st) {
511 var fakeBuffer = {
512 0: 'a',
513 length: 1,
514 __proto__: emptyBuffer.__proto__, // eslint-disable-line no-proto
515 copy: emptyBuffer.copy,
516 slice: emptyBuffer.slice
517 };
518 Object.defineProperty(fakeBuffer, '0', { enumerable: false });
519 Object.defineProperty(fakeBuffer, 'length', { enumerable: false });
520 Object.defineProperty(fakeBuffer, 'copy', { enumerable: false });
521 Object.defineProperty(fakeBuffer, 'slice', { enumerable: false });
522
523 st.deepEqualTest(
524 safeBuffer('a'),
525 fakeBuffer,
526 'real buffer, and mildly fake buffer',
527 false,
528 false
529 );
530
531 st.test('bufferlike', { skip: buffersAreTypedArrays ? !hasSymbols || !Symbol.toStringTag : false }, function (s2t) {
532 var bufferlike = buffersAreTypedArrays ? new Uint8Array() : {};
533 Object.defineProperty(bufferlike, 'length', {
534 enumerable: false,
535 value: bufferlike.length || 0
536 });
537 Object.defineProperty(bufferlike, 'copy', {
538 enumerable: false,
539 value: emptyBuffer.copy
540 });
541 bufferlike.__proto__ = emptyBuffer.__proto__; // eslint-disable-line no-proto
542
543 s2t.deepEqualTest(
544 emptyBuffer,
545 bufferlike,
546 'empty buffer and empty bufferlike',
547 true,
548 true
549 );
550 s2t.end();
551 });
552
553 st.end();
554 });
555
556 t.end();
557});
558
559test('Arrays', function (t) {
560 var a = [];
561 var b = [];
562 b.foo = true;
563
564 t.deepEqualTest(
565 a,
566 b,
567 'two identical arrays, one with an extra property',
568 false,
569 false
570 );
571
572 t.end();
573});
574
575test('booleans', function (t) {
576 t.deepEqualTest(
577 true,
578 true,
579 'trues',
580 true,
581 true,
582 false
583 );
584
585 t.deepEqualTest(
586 false,
587 false,
588 'falses',
589 true,
590 true,
591 false
592 );
593
594 t.deepEqualTest(
595 true,
596 false,
597 'true and false',
598 false,
599 false
600 );
601
602 t.end();
603});
604
605test('booleans and arrays', function (t) {
606 t.deepEqualTest(
607 true,
608 [],
609 'true and an empty array',
610 false,
611 false
612 );
613 t.deepEqualTest(
614 false,
615 [],
616 'false and an empty array',
617 false,
618 false
619 );
620 t.end();
621});
622
623test('arrays initiated', function (t) {
624 var a0 = [
625 undefined,
626 null,
627 -1,
628 0,
629 1,
630 false,
631 true,
632 undefined,
633 '',
634 'abc',
635 null,
636 undefined
637 ];
638 var a1 = [
639 undefined,
640 null,
641 -1,
642 0,
643 1,
644 false,
645 true,
646 undefined,
647 '',
648 'abc',
649 null,
650 undefined
651 ];
652
653 t.deepEqualTest(
654 a0,
655 a1,
656 'arrays with equal contents are equal',
657 true,
658 true,
659 true
660 );
661 t.end();
662});
663
664test('arrays assigned', function (t) {
665 var a0 = [
666 undefined,
667 null,
668 -1,
669 0,
670 1,
671 false,
672 true,
673 undefined,
674 '',
675 'abc',
676 null,
677 undefined
678 ];
679 var a1 = [];
680
681 a1[0] = undefined;
682 a1[1] = null;
683 a1[2] = -1;
684 a1[3] = 0;
685 a1[4] = 1;
686 a1[5] = false;
687 a1[6] = true;
688 a1[7] = undefined;
689 a1[8] = '';
690 a1[9] = 'abc';
691 a1[10] = null;
692 a1[11] = undefined;
693 a1.length = 12;
694
695 t.deepEqualTest(a0, a1, 'a literal array and an assigned array', true, true);
696 t.end();
697});
698
699test('arrays push', function (t) {
700 var a0 = [
701 undefined,
702 null,
703 -1,
704 0,
705 1,
706 false,
707 true,
708 undefined,
709 '',
710 'abc',
711 null,
712 undefined
713 ],
714 a1 = [];
715
716 a1.push(undefined);
717 a1.push(null);
718 a1.push(-1);
719 a1.push(0);
720 a1.push(1);
721 a1.push(false);
722 a1.push(true);
723 a1.push(undefined);
724 a1.push('');
725 a1.push('abc');
726 a1.push(null);
727 a1.push(undefined);
728 a1.length = 12;
729
730 t.deepEqualTest(a0, a1, 'a literal array and a pushed array', true, true);
731 t.end();
732});
733
734test('null == undefined', function (t) {
735 t.deepEqualTest(null, undefined, 'null and undefined', true, false);
736 t.deepEqualTest([null], [undefined], '[null] and [undefined]', true, false);
737
738 t.end();
739});
740
741// node 14 changed `deepEqual` to make two NaNs loosely equal. TODO, semver-major: change deep-equal in the same way.
742var isNode14 = isNode && process.env.ASSERT && semver.satisfies(process.version, '>= 14');
743test('NaNs', function (t) {
744 t.deepEqualTest(
745 NaN,
746 NaN,
747 'two NaNs',
748 isNode14,
749 true
750 );
751
752 t.deepEqualTest(
753 { a: NaN },
754 { a: NaN },
755 'two equiv objects with a NaN value',
756 isNode14,
757 true
758 );
759
760 t.deepEqualTest(NaN, 1, 'NaN and 1', false, false);
761
762 t.end();
763});
764
765test('zeroes', function (t) {
766 t.deepEqualTest(0, -0, '0 and -0', true, false);
767
768 t.deepEqualTest({ a: 0 }, { a: -0 }, 'two objects with a same-keyed 0/-0 value', true, false);
769
770 t.end();
771});
772
773test('Object.create', { skip: !Object.create }, function (t) {
774 var a = { a: 'A' };
775 var b = Object.create(a);
776 b.b = 'B';
777 var c = Object.create(a);
778 c.b = 'C';
779
780 t.deepEqualTest(
781 b,
782 c,
783 'two objects with the same [[Prototype]] but a different own property',
784 false,
785 false
786 );
787
788 t.end();
789});
790
791test('Object.create(null)', { skip: !Object.create }, function (t) {
792 t.deepEqualTest(
793 Object.create(null),
794 Object.create(null),
795 'two empty null objects',
796 true,
797 true,
798 true
799 );
800
801 t.deepEqualTest(
802 Object.create(null, { a: { value: 'b' } }),
803 Object.create(null, { a: { value: 'b' } }),
804 'two null objects with the same property pair',
805 true,
806 true,
807 true
808 );
809
810 t.end();
811});
812
813test('regexes vs dates', function (t) {
814 var d = new Date(1387585278000);
815 var r = /abc/;
816
817 t.deepEqualTest(d, r, 'Date and RegExp', false, false);
818
819 t.end();
820});
821
822test('regexen', function (t) {
823 t.deepEqualTest(/abc/, /xyz/, 'two different regexes', false, false);
824 t.deepEqualTest(/abc/, /abc/, 'two abc regexes', true, true, false);
825 t.deepEqualTest(/xyz/, /xyz/, 'two xyz regexes', true, true, false);
826
827 t.test('fake RegExp', { skip: !hasDunderProto }, function (st) {
828 var a = /abc/g;
829 var b = tag(Object.create(
830 a.__proto__, // eslint-disable-line no-proto
831 gOPDs(a)
832 ), 'RegExp');
833
834 st.deepEqualTest(a, b, 'regex and fake regex', false, false);
835
836 st.end();
837 });
838
839 var a = /abc/gi;
840 var b = /abc/gi;
841 b.foo = true;
842 t.deepEqualTest(
843 a,
844 b,
845 'two identical regexes, one with an extra property',
846 false,
847 false
848 );
849
850 t.end();
851});
852
853test('object literals', function (t) {
854 t.deepEqualTest(
855 { prototype: 2 },
856 { prototype: '2' },
857 'two loosely equal, strictly inequal prototype properties',
858 true,
859 false
860 );
861
862 t.end();
863});
864
865test('arrays and objects', function (t) {
866 t.deepEqualTest([], {}, 'empty array and empty object', false, false);
867 t.deepEqualTest([], { length: 0 }, 'empty array and empty arraylike object', false, false);
868 t.deepEqualTest([1], { 0: 1 }, 'array and similar object', false, false);
869
870 t.end();
871});
872
873test('functions', function (t) {
874 function f() {}
875
876 t.deepEqualTest(f, f, 'a function and itself', true, true, true);
877 t.deepEqualTest([f], [f], 'a function and itself in an array', true, true, true);
878
879 t.deepEqualTest(function () {}, function () {}, 'two distinct functions', false, false, true);
880 t.deepEqualTest([function () {}], [function () {}], 'two distinct functions in an array', false, false, true);
881
882 t.deepEqualTest(f, {}, 'function and object', false, false, true);
883 t.deepEqualTest([f], [{}], 'function and object in an array', false, false, true);
884
885 t.end();
886});
887
888test('Errors', function (t) {
889 t.deepEqualTest(new Error('xyz'), new Error('xyz'), 'two errors of the same type with the same message', true, true, false);
890 t.deepEqualTest(new Error('xyz'), new TypeError('xyz'), 'two errors of different types with the same message', false, false);
891 t.deepEqualTest(new Error('xyz'), new Error('zyx'), 'two errors of the same type with a different message', false, false);
892
893 t.test('errorlike', { skip: !Object.defineProperty }, function (st) {
894 var err = new Error('foo');
895 // TODO: add `__proto__` when brand check is available
896 var errorlike = tag({ message: err.message, stack: err.stack, name: err.name, constructor: err.constructor }, 'Error');
897 Object.defineProperty(errorlike, 'message', { enumerable: false });
898 Object.defineProperty(errorlike, 'stack', { enumerable: false });
899 Object.defineProperty(errorlike, 'name', { enumerable: false });
900 Object.defineProperty(errorlike, 'constructor', { enumerable: false });
901 st.notOk(errorlike instanceof Error);
902 st.ok(err instanceof Error);
903 st.deepEqualTest(
904 err,
905 errorlike,
906 'error, and errorlike object',
907 false,
908 false
909 );
910
911 st.end();
912 });
913
914 t.deepEqualTest(
915 new Error('a'),
916 assign(new Error('a'), { code: 10 }),
917 'two otherwise equal errors with different own properties',
918 false,
919 false
920 );
921
922 t.test('fake error', { skip: !process.env.ASSERT || !hasDunderProto }, function (st) {
923 var a = tag({
924 __proto__: null
925 }, 'Error');
926 var b = new RangeError('abc');
927 b.__proto__ = null; // eslint-disable-line no-proto
928
929 st.deepEqualTest(
930 a,
931 b,
932 'null object faking as an Error, RangeError with null proto',
933 false,
934 false
935 );
936 st.end();
937 });
938
939 t.end();
940});
941
942test('object and null', function (t) {
943 t.deepEqualTest(
944 {},
945 null,
946 'null and an object',
947 false,
948 false
949 );
950
951 t.end();
952});
953
954test('errors', function (t) {
955
956 t.end();
957});
958
959test('error = Object', function (t) {
960 t.deepEqualTest(
961 new Error('a'),
962 { message: 'a' },
963 false,
964 false
965 );
966
967 t.end();
968});
969
970test('[[Prototypes]]', function (t) {
971 function C() {}
972 var instance = new C();
973 delete instance.constructor;
974
975 t.deepEqualTest({}, instance, 'two identical objects with different [[Prototypes]]', true, false);
976
977 t.test('Dates with different prototypes', { skip: !hasDunderProto }, function (st) {
978 var d1 = new Date(0);
979 var d2 = new Date(0);
980
981 st.deepEqualTest(d1, d2, 'two dates with the same timestamp', true, true);
982
983 var newProto = {
984 __proto__: Date.prototype
985 };
986 d2.__proto__ = newProto; // eslint-disable-line no-proto
987 st.ok(d2 instanceof Date, 'd2 is still a Date instance after tweaking [[Prototype]]');
988
989 st.deepEqualTest(d1, d2, 'two dates with the same timestamp and different [[Prototype]]', true, false);
990
991 st.end();
992 });
993
994 t.end();
995});
996
997test('toStringTag', { skip: !hasSymbols || !Symbol.toStringTag }, function (t) {
998 var o1 = {};
999 t.equal(Object.prototype.toString.call(o1), '[object Object]', 'o1: Symbol.toStringTag works');
1000
1001 var o2 = {};
1002 t.equal(Object.prototype.toString.call(o2), '[object Object]', 'o2: original Symbol.toStringTag works');
1003
1004 t.deepEqualTest(o1, o2, 'two normal empty objects', true, true);
1005
1006 o2[Symbol.toStringTag] = 'jifasnif';
1007 t.equal(Object.prototype.toString.call(o2), '[object jifasnif]', 'o2: modified Symbol.toStringTag works');
1008
1009 t.deepEqualTest(o1, o2, 'two normal empty objects with different toStringTags', false, false);
1010
1011 t.end();
1012});
1013
1014test('boxed primitives', function (t) {
1015 t.deepEqualTest(Object(false), false, 'boxed and primitive `false`', false, false);
1016 t.deepEqualTest(Object(true), true, 'boxed and primitive `true`', false, false);
1017 t.deepEqualTest(Object(3), 3, 'boxed and primitive `3`', false, false);
1018 t.deepEqualTest(Object(NaN), NaN, 'boxed and primitive `NaN`', false, false);
1019 t.deepEqualTest(Object(''), '', 'boxed and primitive `""`', false, false);
1020 t.deepEqualTest(Object('str'), 'str', 'boxed and primitive `"str"`', false, false);
1021
1022 t.test('symbol', { skip: !hasSymbols }, function (st) {
1023 var s = Symbol('');
1024 st.deepEqualTest(Object(s), s, 'boxed and primitive `Symbol()`', false, false);
1025 st.end();
1026 });
1027
1028 t.test('bigint', { skip: typeof BigInt !== 'function' }, function (st) {
1029 var hhgtg = BigInt(42);
1030 st.deepEqualTest(Object(hhgtg), hhgtg, 'boxed and primitive `BigInt(42)`', false, false);
1031 st.end();
1032 });
1033
1034 t.test('`valueOf` is called for boxed primitives', function (st) {
1035 var a = Object(5);
1036 a.valueOf = function () { throw new Error('failed'); };
1037 var b = Object(5);
1038 b.valueOf = function () { throw new Error('failed'); };
1039
1040 st.deepEqualTest(a, b, 'two boxed numbers with a thrower valueOf', false, false);
1041
1042 st.end();
1043 });
1044
1045 t.end();
1046});
1047
1048test('getters', { skip: !Object.defineProperty }, function (t) {
1049 var a = {};
1050 Object.defineProperty(a, 'a', { enumerable: true, get: function () { return 5; } });
1051 var b = {};
1052 Object.defineProperty(b, 'a', { enumerable: true, get: function () { return 6; } });
1053
1054 t.deepEqualTest(a, b, 'two objects with the same getter but producing different values', false, false);
1055
1056 t.end();
1057});
1058
1059var isBrokenNode = isNode && process.env.ASSERT && semver.satisfies(process.version, '<= 13.3.0');
1060test('fake arrays: extra keys will be tested', { skip: !hasDunderProto || isBrokenNode }, function (t) {
1061 var a = tag({
1062 __proto__: Array.prototype,
1063 0: 1,
1064 1: 1,
1065 2: 'broken',
1066 length: 2
1067 }, 'Array');
1068 if (Object.defineProperty) {
1069 Object.defineProperty(a, 'length', {
1070 enumerable: false
1071 });
1072 }
1073
1074 t.deepEqualTest(a, [1, 1], 'fake and real array with same contents and [[Prototype]]', false, false);
1075
1076 var b = tag(/abc/, 'Array');
1077 b.__proto__ = Array.prototype; // eslint-disable-line no-proto
1078 b.length = 3;
1079 if (Object.defineProperty) {
1080 Object.defineProperty(b, 'length', {
1081 enumerable: false
1082 });
1083 }
1084 t.deepEqualTest(b, ['a', 'b', 'c'], 'regex faking as array, and array', false, false);
1085
1086 t.end();
1087});
1088
1089test('circular references', function (t) {
1090 var b = {};
1091 b.b = b;
1092
1093 var c = {};
1094 c.b = c;
1095
1096 t.deepEqualTest(
1097 b,
1098 c,
1099 'two self-referencing objects',
1100 true,
1101 true
1102 );
1103
1104 var d = {};
1105 d.a = 1;
1106 d.b = d;
1107
1108 var e = {};
1109 e.a = 1;
1110 e.b = e.a;
1111
1112 t.deepEqualTest(
1113 d,
1114 e,
1115 'two deeply self-referencing objects',
1116 false,
1117 false
1118 );
1119
1120 t.end();
1121});
1122
1123// io.js v2 is the only version where `console.log(b)` below is catchable
1124var isNodeWhereBufferBreaks = isNode && semver.satisfies(process.version, '< 3');
1125var isNode06 = isNode && semver.satisfies(process.version, '<= 0.6'); // segfaults in node 0.6, it seems
1126
1127test('TypedArrays', { skip: !hasTypedArrays }, function (t) {
1128 t.test('Buffer faked as Uint8Array', { skip: typeof Buffer !== 'function' || !Object.create || !hasDunderProto || isNode06 }, function (st) {
1129 var a = safeBuffer('test');
1130 var b = tag(Object.create(
1131 a.__proto__, // eslint-disable-line no-proto
1132 assign(gOPDs(a), {
1133 length: {
1134 enumerable: false,
1135 value: 4
1136 }
1137 })
1138 ), 'Uint8Array');
1139
1140 st.deepEqualTest(
1141 a,
1142 b,
1143 'Buffer and Uint8Array',
1144 isNodeWhereBufferBreaks,
1145 isNodeWhereBufferBreaks
1146 );
1147
1148 st.end();
1149 });
1150
1151 t.test('one TypedArray faking as another', { skip: !hasDunderProto }, function (st) {
1152 /* globals Uint8Array, Int8Array */
1153 var a = new Uint8Array(10);
1154 var b = tag(new Int8Array(10), 'Uint8Array');
1155 b.__proto__ = Uint8Array.prototype; // eslint-disable-line no-proto
1156
1157 st.deepEqualTest(
1158 a,
1159 b,
1160 'Uint8Array, and Int8Array pretending to be a Uint8Array',
1161 false,
1162 false
1163 );
1164
1165 st.end();
1166 });
1167
1168 t.end();
1169});