Skip to content

Commit

Permalink
[Breaking] non-Date objects with different [[Prototypes]] are not equal
Browse files Browse the repository at this point in the history
Date objects are equal when:
 - the timestamp is the same
 - if strict, the [[Prototype]] is the same
 - own properties match, same as normal objects
  • Loading branch information
ljharb committed Jul 31, 2019
1 parent 81488e5 commit 77c430f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"files": ["example/**", "test/**"],
"rules": {
"array-bracket-newline": 0,
"max-lines": 0,
"max-params": 0,
"max-statements": 0,
"no-console": 0,
Expand Down
13 changes: 9 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var isArray = require('isarray');
var isDate = require('is-date-object');

var getTime = Date.prototype.getTime;
var gPO = Object.getPrototypeOf;

function deepEqual(actual, expected, options) {
var opts = options || {};
Expand Down Expand Up @@ -51,7 +52,7 @@ function isBuffer(x) {
}

function objEquiv(a, b, opts) {
/* eslint max-statements: [2, 50] */
/* eslint max-statements: [2, 60] */
var i, key;
if (typeof a !== typeof b) { return false; }
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) { return false; }
Expand All @@ -72,9 +73,13 @@ function objEquiv(a, b, opts) {
return a.source === b.source && flags(a) === flags(b);
}

if (isDate(a) && isDate(b)) {
return getTime.call(a) === getTime.call(b);
}
var aIsDate = isDate(a);
var bIsDate = isDate(b);
if (aIsDate !== bIsDate) { return false; }
if (aIsDate || bIsDate) { // && would work too, because both are true or both false here
if (getTime.call(a) !== getTime.call(b)) { return false; }
if (opts.strict && gPO && gPO(a) !== gPO(b)) { return false; }
} else if (gPO && gPO(a) !== gPO(b)) { return false; } // non-Dates always compare [[Prototype]]s

var aIsBuffer = isBuffer(a);
var bIsBuffer = isBuffer(b);
Expand Down
34 changes: 33 additions & 1 deletion test/cmp.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,13 @@ test('arguments class', function (t) {
test('dates', function (t) {
var d0 = new Date(1387585278000);
var d1 = new Date('Fri Dec 20 2013 16:21:18 GMT-0800 (PST)');
t.deepEqualTest(d0, d1, 'equivalent Dates', true, true);

t.deepEqualTest(d0, d1, 'two Dates with the same timestamp', true, true);

d1.a = true;

t.deepEqualTest(d0, d1, 'two Dates with the same timestamp but different own properties', false, false);

t.end();
});

Expand Down Expand Up @@ -342,3 +348,29 @@ test('functions', function (t) {

t.end();
});

test('[[Prototypes]]', { skip: !Object.getPrototypeOf }, function (t) {
function C() {}
var instance = new C();
delete instance.constructor;

t.deepEqualTest({}, instance, 'two identical objects with different [[Prototypes]]', false, false);

t.test('Dates with different prototypes', { skip: !Object.setPrototypeOf }, function (st) {
var d1 = new Date(0);
var d2 = new Date(0);

t.deepEqualTest(d1, d2, 'two dates with the same timestamp', true, true);

var newProto = {};
Object.setPrototypeOf(newProto, Date.prototype);
Object.setPrototypeOf(d2, newProto);
st.ok(d2 instanceof Date, 'd2 is still a Date instance after tweaking [[Prototype]]');

t.deepEqualTest(d1, d2, 'two dates with the same timestamp and different [[Prototype]]', true, false);

st.end();
});

t.end();
});

0 comments on commit 77c430f

Please sign in to comment.