Skip to content

Commit 7079a22

Browse files
authored
Bugfix: support Object.create(null) (#123)
- Allow use of `Object.create(null)` to work without error. Fixes #64 - Add customized tests.
1 parent b34988f commit 7079a22

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## UNRELEASED
4+
5+
**Bugfixes:**
6+
7+
- Fix Object with null prototype errors [#64](https://github.com/FormidableLabs/react-fast-compare/issues/64).
8+
39
## 3.2.0 (2020-05-28)
410

511
- [#80](https://github.com/FormidableLabs/react-fast-compare/pull/80). Update types to use generic `any`s.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ $ npm install react-fast-compare
3333
- handles React-specific circular references, like elements
3434
- checks equality Date and RegExp objects
3535
- should as fast as [fast-deep-equal](https://github.com/epoberezkin/fast-deep-equal) via a single unified library, and with added guardrails for circular references.
36-
- small: under 650 bytes minified+gzipped
36+
- small: under 660 bytes minified+gzipped
3737

3838
## Usage
3939

@@ -160,6 +160,6 @@ Please see our [contributions guide](./CONTRIBUTING.md).
160160
[npm_site]: http://badge.fury.io/js/react-fast-compare
161161
[appveyor_img]: https://ci.appveyor.com/api/projects/status/github/formidablelabs/react-fast-compare?branch=master&svg=true
162162
[appveyor_site]: https://ci.appveyor.com/project/FormidableLabs/react-fast-compare
163-
[bundle_img]: https://img.shields.io/badge/minzipped%20size-639%20B-flatgreen.svg
163+
[bundle_img]: https://img.shields.io/badge/minzipped%20size-656%20B-flatgreen.svg
164164
[downloads_img]: https://img.shields.io/npm/dm/react-fast-compare.svg
165165
[maintenance_img]: https://img.shields.io/badge/maintenance-active-flatgreen.svg

index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var hasArrayBuffer = typeof ArrayBuffer === 'function' && !!ArrayBuffer.isView;
88
// Note: We **don't** need `envHasBigInt64Array` in fde es6/index.js
99

1010
function equal(a, b) {
11-
// START: fast-deep-equal es6/index.js 3.1.1
11+
// START: fast-deep-equal es6/index.js 3.1.3
1212
if (a === b) return true;
1313

1414
if (a && b && typeof a == 'object' && typeof b == 'object') {
@@ -73,8 +73,13 @@ function equal(a, b) {
7373
}
7474

7575
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
76-
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
77-
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
76+
// START: Modifications:
77+
// Apply guards for `Object.create(null)` handling. See:
78+
// - https://github.com/FormidableLabs/react-fast-compare/issues/64
79+
// - https://github.com/epoberezkin/fast-deep-equal/issues/49
80+
if (a.valueOf !== Object.prototype.valueOf && typeof a.valueOf === 'function' && typeof b.valueOf === 'function') return a.valueOf() === b.valueOf();
81+
if (a.toString !== Object.prototype.toString && typeof a.toString === 'function' && typeof b.toString === 'function') return a.toString() === b.toString();
82+
// END: Modifications
7883

7984
keys = Object.keys(a);
8085
length = keys.length;

test/node/tests.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,57 @@ const react = [
6464
}
6565
];
6666

67+
// Additional customized behavior.
68+
const custom = [
69+
{
70+
description: 'Custom tests',
71+
tests: [
72+
{
73+
description: 'Object.create(null) equal',
74+
value1: Object.create(null),
75+
value2: Object.create(null),
76+
equal: true
77+
},
78+
{
79+
description: 'Object.create(null) unequal to empty object',
80+
value1: Object.create(null),
81+
value2: {},
82+
equal: false
83+
},
84+
{
85+
description: 'Object.create(null) unequal to non-empty object',
86+
value1: Object.create(null),
87+
value2: { a: 1 },
88+
equal: false
89+
},
90+
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#null-prototype_objects
91+
{
92+
description: 'Object.create(null) equal to vanilla null prototype deep objects',
93+
value1: Object.assign(Object.create(null), { a: 1, b: { c: true } }),
94+
value2: { __proto__: null, a: 1, b: { c: true } },
95+
equal: true
96+
},
97+
// Object.create(null) has a different `constructor` than a vanilla, non-null object.
98+
{
99+
description: 'Object.create(null) unequal to vanilla deep objects',
100+
value1: Object.assign(Object.create(null), { a: 1, b: { c: true } }),
101+
value2: { a: 1, b: { c: true } },
102+
equal: false
103+
},
104+
{
105+
description: 'Object.create(null) equal for deep objects',
106+
value1: Object.assign(Object.create(null), { a: 1, b: { c: true } }),
107+
value2: Object.assign(Object.create(null), { b: { c: true }, a: 1 }),
108+
equal: true
109+
}
110+
]
111+
}
112+
];
113+
67114
module.exports = {
68115
generic,
69116
es6,
70117
react,
71-
all: [...generic, ...es6, ...react],
118+
custom,
119+
all: [].concat(generic, es6, react, custom),
72120
};

0 commit comments

Comments
 (0)