Skip to content

Commit

Permalink
Feature: Add support for ES.next Set, Map, ArrayBuffer (#51)
Browse files Browse the repository at this point in the history
- Update library to include ES.next support for `Map`, `Set`, `ArrayBuffer`. Part of #36
- Update to `fast-deep-equal@3.1.1` with modified support for ES.next data types.
- Upgrade lots of `devDependenices`
- Use `fast-deep-equal` tests directly in our correctness tests.
- Update CI to modern Node.js versions.
- **Note**: There's a bug / limitation of `Set` comparisons whereby objects are compared by reference not value. Tracked at #50 . In our `yarn benchmark`, `lodash.isEqual` gets test differences because it correctly handles those.
  • Loading branch information
ryan-roemer committed Jan 29, 2020
1 parent 65c3eb7 commit 5d71c91
Show file tree
Hide file tree
Showing 17 changed files with 3,491 additions and 4,206 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ dist: trusty
language: node_js

node_js:
- "6"
- "8"
- "9"
- "10"
- "12"
- "13"

branches:
only:
Expand Down
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## UNRELEASED

**Features:**
- Update library to include ES.next support for `Map`, `Set`, `ArrayBuffer`. [#36](https://github.com/FormidableLabs/react-fast-compare/pull/36).

**Breaking changes:**
- Update to `fast-deep-equal@3.1.1` with modified support for ES.next data types.

**Infrastructure:**
- Upgrade lots of `devDependenices`
- Use `fast-deep-equal` tests directly in our correctness tests.
- Update CI to modern Node.js versions.
- Update Appveyor to use straight IE11 (not emulated IE9) because mocha no longer runs in IE9.

## 2.0.4 (2018-11-09)

- [#39](https://github.com/FormidableLabs/react-fast-compare/pull/39). Fix `react-native` bug introduced by DOM element checking.
Expand All @@ -11,7 +25,7 @@
## 2.0.2 (2018-08-21)

- [#28](https://github.com/FormidableLabs/react-fast-compare/pull/28). Fix for localized versions of IE11. Thanks @excentrik!
- [#34](https://github.com/FormidableLabs/react-fast-compare/pull/34). Fix typo. Thanks @Marviel!
- [#34](https://github.com/FormidableLabs/react-fast-compare/pull/34). Fix typo. Thanks @Marviel!

## 2.0.1 (2018-06-25)

Expand Down
29 changes: 22 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ This package is a fork of [fast-deep-equal](https://github.com/epoberezkin/fast-
We encourage pull requests concerning:

* React features not handled in this library
* Integrating updates from fast-deep-equal
* Integrating tests from fast-deep-equal
* Integrating updates from `fast-deep-equal`. This unfortunately, now requires more manual work to use the comment blocks in `index.js` to figure out what to paste and where.
* Integrating tests from `fast-deep-equal`. This usually entails upgrading the `git`-based dependencies of `fast-deep-equal-git` and `npm`-published package of `fast-deep-equal` in `package.json:devDependencies`.
* Bugs in this library
* New tests for React
* Documentation
Expand Down Expand Up @@ -65,7 +65,7 @@ $ yarn run test-node --watch

The same tests are then imported and built with `webpack` to a test bundle that
can be run in arbitrary browsers. So far in CI, we execute the tests in headless
Chrome on Linux in Travis and IE9-emulated IE11 in Appveyor.
Chrome on Linux in Travis and IE11 in Appveyor.

To run the browser tests on your machine (note: you must already have the
browser you're running installed):
Expand All @@ -76,7 +76,7 @@ $ yarn run test-browser
# Example: real Chrome + Firefox + Safari
$ yarn run test-browser --browsers Chrome,Firefox,Safari

# IE9 emulation (on Windows)
# IE11 (on Windows)
$ yarn run test-browser-ie
```

Expand All @@ -94,6 +94,21 @@ $ yarn run test-ts
$ yarn run eslint
```

### Size

You can check how we do with minification + compression with:

```sh
# Show minified output
$ yarn -s compress

# Display minified + gzip'ed size in bytes.
$ yarn size-min-gz
687
```

**Note**: If the min+gz size increases, please note it in the README. If it is a significant increase, please flag to your reviewers and have a discussion about whether or not the size addition is justified.

## Before submitting a PR...

Before you go ahead and submit a PR, make sure that you have done the following:
Expand All @@ -103,9 +118,9 @@ $ yarn run test
$ yarn run benchmark
```

Everything must be correct / pass checks. You should also check the benchmark
stats and make sure that we don't have any significant performance regressions
(check out `master` for a baseline comparison on _your_ machine).
1. Everything must be correct / pass checks.
2. You should also check the benchmark stats and make sure that we don't have any significant performance regressions (check out `master` for a baseline comparison on _your_ machine).
- Please **do** update the README benchmark numbers for changes in your PR so that we have much easier discussion points _and_ our users get up-to-date information.

## Releasing a new version to NPM

Expand Down
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ $ npm install react-fast-compare
* deeply compares any value (besides objects with circular references)
* handles React-specific circular references, like elements
* checks equality Date and RegExp objects
* should be just as fast as [fast-deep-equal](https://github.com/epoberezkin/fast-deep-equal) for general use, and faster for React use
* small: under 600 bytes minified+gzipped
* 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.
* small: under 700 bytes minified+gzipped

## Usage

Expand Down Expand Up @@ -86,11 +86,11 @@ simply because there are more tests in each operation.
### Generic Data

```
react-fast-compare x 207,503 ops/sec ±0.54% (92 runs sampled)
fast-deep-equal x 195,006 ops/sec ±0.70% (91 runs sampled)
lodash.isEqual x 43,778 ops/sec ±0.55% (91 runs sampled)
nano-equal x 198,036 ops/sec ±0.37% (95 runs sampled)
shallow-equal-fuzzy x 173,023 ops/sec ±0.59% (95 runs sampled)
react-fast-compare x 157,863 ops/sec ±0.54% (94 runs sampled)
fast-deep-equal x 149,877 ops/sec ±0.76% (93 runs sampled)
lodash.isEqual x 33,298 ops/sec ±0.70% (93 runs sampled)
nano-equal x 144,836 ops/sec ±0.51% (94 runs sampled)
shallow-equal-fuzzy x 110,192 ops/sec ±0.57% (95 runs sampled)
fastest: react-fast-compare
```

Expand All @@ -101,16 +101,14 @@ tests; any difference is just noise. `react-fast-compare` won't be faster than
### React and Generic Data

```
react-fast-compare x 187,628 ops/sec ±0.58% (93 runs sampled)
fast-deep-equal x 477 ops/sec ±0.55% (91 runs sampled)
lodash.isEqual x 35,100 ops/sec ±0.16% (95 runs sampled)
nano-equal x 468 ops/sec ±0.53% (94 runs sampled)
shallow-equal-fuzzy x 684 ops/sec ±0.43% (92 runs sampled)
fastest: react-fast-compare
react-fast-compare x 64,102 ops/sec ±0.36% (94 runs sampled)
fast-deep-equal x 63,844 ops/sec ±0.43% (94 runs sampled)
lodash.isEqual x 6,243 ops/sec ±0.72% (90 runs sampled)
fastest: react-fast-compare,fast-deep-equal
```

Three of these packages cannot handle comparing React elements (which are
circular): `fast-deep-equal`, `nano-equal`, and `shallow-equal-fuzzy`.
Two of these packages cannot handle comparing React elements (which are
circular): `nano-equal` and `shallow-equal-fuzzy`.

### Running Benchmarks

Expand All @@ -121,7 +119,12 @@ $ yarn run benchmark

## fast-deep-equal Versioning

react-fast-compare@2 tracks fast-deep-equal@2.0.1
react-fast-compare@3 tracks fast-deep-equal@3.1.1

Now that `fast-deep-equal` has separate es5, es6, and es6 + React entry points, the main differences with this library are:

* `try/catch` guardrails for stack overflows from undetected circular references.
* A single unified entry point for **all** uses. No matter what your target application is, `import equal fro 'react-fast-compare'` just works.

## License

Expand All @@ -133,7 +136,7 @@ Please see our [contributions guide](./CONTRIBUTING.md).

## Maintenance Status

**Active:** Formidable is actively working on this project, and we expect to continue for work for the foreseeable future. Bug reports, feature requests and pull requests are welcome.
**Active:** Formidable is actively working on this project, and we expect to continue for work for the foreseeable future. Bug reports, feature requests and pull requests are welcome.

[trav_img]: https://api.travis-ci.com/FormidableLabs/react-fast-compare.svg
[trav_site]: https://travis-ci.com/FormidableLabs/react-fast-compare
Expand Down
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Test against this version of Node.js
environment:
matrix:
- nodejs_version: "6"
- nodejs_version: "8"
- nodejs_version: "10"
- nodejs_version: "12"
- nodejs_version: "13"

# Install scripts. (runs after repo cloning)
install:
Expand Down
57 changes: 34 additions & 23 deletions benchmark/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ const Benchmark = require('benchmark');

const correctnessTests = [];
const genericSuite = new Benchmark.Suite;
const allSuite = new Benchmark.Suite;
const advancedSuite = new Benchmark.Suite;

const equalPackages = {
'react-fast-compare': require('../index'),
'fast-deep-equal': require('fast-deep-equal'),
'fast-deep-equal': require('fast-deep-equal/es6/react'),
'lodash.isEqual': require('lodash').isEqual,
'nano-equal': require('nano-equal'),
'shallow-equal-fuzzy': require('shallow-equal-fuzzy')
};

const advancedPkgs = new Set([
'react-fast-compare',
'fast-deep-equal',
'lodash.isEqual'
]);

for (const equalName in equalPackages) {
const equalFunc = equalPackages[equalName];

Expand All @@ -30,29 +36,31 @@ for (const equalName in equalPackages) {
}
});

allSuite.add(equalName, function() {
for (const testSuite of tests.all) {
for (const test of testSuite.tests) {
try {
equalFunc(test.value1, test.value2);
} catch (error) {
// swallow errors during benchmarking. they are reported in the test section
if (advancedPkgs.has(equalName)) {
advancedSuite.add(equalName, function() {
for (const testSuite of tests.all) {
for (const test of testSuite.tests) {
try {
equalFunc(test.value1, test.value2);
} catch (error) {
// swallow errors during benchmarking. they are reported in the test section
}
}
}
}
});
});

correctnessTests.push(() => console.log(equalName));
for (const testSuite of tests.all) {
for (const test of testSuite.tests) {
correctnessTests.push(() => {
try {
if (equalFunc(test.value1, test.value2) !== test.equal)
console.error('- different result:', equalName, testSuite.description, test.description);
} catch(error) {
console.error('- error:', testSuite.description, test.description, error.message);
}
});
correctnessTests.push(() => console.log(equalName));
for (const testSuite of tests.all) {
for (const test of testSuite.tests) {
correctnessTests.push(() => {
try {
if (equalFunc(test.value1, test.value2) !== test.equal)
console.error('- different result:', equalName, testSuite.description, test.description);
} catch(error) {
console.error('- error:', testSuite.description, test.description, error.message);
}
});
}
}
}
}
Expand All @@ -75,7 +83,7 @@ genericSuite

console.log('\n--- speed tests: generic and react ---\n');

allSuite
advancedSuite
.on('cycle', (event) => console.log(String(event.target)))
.on('complete', function () {
console.log(' fastest: ' + this.filter('fastest').map('name'));
Expand All @@ -86,6 +94,9 @@ allSuite
})
.run({async: false});

// **Note**: `lodash.isEqual` gets different results for Sets, Maps
// because it **is** correct and `fast-deep-equal` is not.
// See: https://github.com/FormidableLabs/react-fast-compare/issues/50
console.log('\n--- correctness tests: generic and react ---\n');

correctnessTests.forEach(test => test());
Expand Down

0 comments on commit 5d71c91

Please sign in to comment.