From 947a326ab867f41c58744a9e5bb61a6d106d0864 Mon Sep 17 00:00:00 2001 From: Eran Hammer Date: Wed, 28 Nov 2018 14:31:22 -0800 Subject: [PATCH] Ignore symbols in deepEqual() by default. Closes #281 --- API.md | 2 +- lib/deep-equal.js | 38 ++++++++++++++++++++------------------ test/index.js | 30 +++++++++++++++++------------- 3 files changed, 38 insertions(+), 32 deletions(-) mode change 100644 => 100755 lib/deep-equal.js diff --git a/API.md b/API.md index 3996deba..3c9e18a2 100755 --- a/API.md +++ b/API.md @@ -162,7 +162,7 @@ var config = Hoek.applyToDefaultsWithShallow(defaults, options, [['db', 'server' ### deepEqual(b, a, [options]) Performs a deep comparison of the two values including support for circular dependencies, prototype, and enumerable properties. -To skip prototype comparisons, use `options.prototype = false` +To skip prototype comparisons, use `options.prototype = false` and to include symbols, used `options.symbols = true`. ```javascript Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true diff --git a/lib/deep-equal.js b/lib/deep-equal.js old mode 100644 new mode 100755 index 6856d9e4..8611b987 --- a/lib/deep-equal.js +++ b/lib/deep-equal.js @@ -228,31 +228,33 @@ internals.isDeepEqualObj = function (instanceType, obj, ref, options, seen) { // Check symbols - const objSymbols = getOwnPropertySymbols(obj); - const refSymbols = new Set(getOwnPropertySymbols(ref)); + if (options.symbols) { + const objSymbols = getOwnPropertySymbols(obj); + const refSymbols = new Set(getOwnPropertySymbols(ref)); - for (let i = 0; i < objSymbols.length; ++i) { - const key = objSymbols[i]; + for (let i = 0; i < objSymbols.length; ++i) { + const key = objSymbols[i]; - if (hasOwnEnumerableProperty(obj, key)) { - if (!hasOwnEnumerableProperty(ref, key)) { - return false; - } + if (hasOwnEnumerableProperty(obj, key)) { + if (!hasOwnEnumerableProperty(ref, key)) { + return false; + } - if (!isDeepEqual(obj[key], ref[key], options, seen)) { + if (!isDeepEqual(obj[key], ref[key], options, seen)) { + return false; + } + } + else if (hasOwnEnumerableProperty(ref, key)) { return false; } - } - else if (hasOwnEnumerableProperty(ref, key)) { - return false; - } - refSymbols.delete(key); - } + refSymbols.delete(key); + } - for (const key of refSymbols) { - if (hasOwnEnumerableProperty(ref, key)) { - return false; + for (const key of refSymbols) { + if (hasOwnEnumerableProperty(ref, key)) { + return false; + } } } diff --git a/test/index.js b/test/index.js index 4a5ba2a3..956c6467 100755 --- a/test/index.js +++ b/test/index.js @@ -750,7 +750,7 @@ describe('cloneWithShallow()', () => { c: { d: 6 }, - e() {} + e() { } }; const copy = Hoek.cloneWithShallow(source, ['c', 'e']); @@ -1135,18 +1135,22 @@ describe('deepEqual()', () => { const ne = {}; Object.defineProperty(ne, sym, { value: true }); - expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: true } })).to.be.true(); - expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: false } })).to.be.false(); - expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: true })).to.be.false(); - expect(Hoek.deepEqual({ [sym]: undefined }, { [sym]: undefined })).to.be.true(); - expect(Hoek.deepEqual({ [sym]: undefined }, {})).to.be.false(); - expect(Hoek.deepEqual({}, { [sym]: undefined })).to.be.false(); + expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: true } }, { symbols: true })).to.be.true(); + expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: false } }, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: true }, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual({ [sym]: undefined }, { [sym]: undefined }, { symbols: true })).to.be.true(); + expect(Hoek.deepEqual({ [sym]: undefined }, {}, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual({}, { [sym]: undefined }, { symbols: true })).to.be.false(); - expect(Hoek.deepEqual({}, ne)).to.be.true(); - expect(Hoek.deepEqual(ne, {})).to.be.true(); - expect(Hoek.deepEqual({ [sym]: true }, ne)).to.be.false(); - expect(Hoek.deepEqual(ne, { [sym]: true })).to.be.false(); - expect(Hoek.deepEqual(ne, { [Symbol()]: undefined })).to.be.false(); + expect(Hoek.deepEqual({}, ne, { symbols: true })).to.be.true(); + expect(Hoek.deepEqual(ne, {}, { symbols: true })).to.be.true(); + expect(Hoek.deepEqual({ [sym]: true }, ne, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual(ne, { [sym]: true }, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual(ne, { [Symbol()]: undefined }, { symbols: true })).to.be.false(); + + expect(Hoek.deepEqual({ [sym]: true }, { [sym]: true }, { symbols: true })).to.be.true(); + expect(Hoek.deepEqual({ [sym]: true }, {}, { symbols: true })).to.be.false(); + expect(Hoek.deepEqual({ [sym]: true }, {}, { symbols: false })).to.be.true(); }); it('compares dates', () => { @@ -1367,7 +1371,7 @@ describe('deepEqual()', () => { it('handles valueOf() that throws', () => { - const throwing = class { + const throwing = class { constructor(value) {