Skip to content

Commit

Permalink
Merge b6aad8c into b791fac
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Nov 30, 2019
2 parents b791fac + b6aad8c commit a42246e
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.yml
Expand Up @@ -24,3 +24,9 @@ rules:
callback-return: 2
no-path-concat: 2
no-empty: 0
globals:
document: false
Element: false
beforeEach: false
afterEach: false
xit: false
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -65,3 +65,4 @@ yarn.lock

# generated files
index.js
react.js
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -39,6 +39,13 @@ var equal = require('fast-deep-equal/es6');
console.log(equal(Int16Array([1, 2]), Int16Array([1, 2]))); // true
```

For better support for React use:

```javascript
var equal = require('fast-deep-equal/react');
var equal = require('fast-deep-equal/es6/react');
```


## Performance benchmark

Expand Down
2 changes: 2 additions & 0 deletions build.js
Expand Up @@ -6,5 +6,7 @@ doT.templateSettings.strip = false;

var jst = doT.compile(fs.readFileSync('./src/index.jst', 'utf8'));
fs.writeFileSync('./index.js', jst({es6: false}));
fs.writeFileSync('./react.js', jst({es6: false, react: true}));
try { fs.mkdirSync('./es6'); } catch(e) {}
fs.writeFileSync('./es6/index.js', jst({es6: true}));
fs.writeFileSync('./es6/react.js', jst({es6: true, react: true}));
2 changes: 2 additions & 0 deletions es6/index.d.ts
@@ -0,0 +1,2 @@
const equal: (a: any, b: any) => boolean;
export = equal;
2 changes: 2 additions & 0 deletions es6/react.d.ts
@@ -0,0 +1,2 @@
const equal: (a: any, b: any) => boolean;
export = equal;
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -35,6 +35,9 @@
"mocha": "^3.4.2",
"nyc": "^11.0.2",
"pre-commit": "^1.2.2",
"react": "^16.12.0",
"react-test-renderer": "^16.12.0",
"sinon": "^7.5.0",
"typescript": "^2.6.1"
},
"nyc": {
Expand Down
2 changes: 2 additions & 0 deletions react.d.ts
@@ -0,0 +1,2 @@
const equal: (a: any, b: any) => boolean;
export = equal;
5 changes: 5 additions & 0 deletions spec/index.spec.js
@@ -1,12 +1,17 @@
'use strict';

var equal = require('..');
var equalReact = require('../react');
var es6equal = require('../es6');
var es6equalReact = require('../es6/react');
var assert = require('assert');

testCases(equal, 'equal - standard tests', require('./tests'));
testCases(equalReact, 'equal react - standard tests', require('./tests'));
testCases(es6equal, 'es6 equal - standard tests', require('./tests'));
testCases(es6equalReact, 'es6 equal react - standard tests', require('./tests'));
testCases(es6equal, 'es6 equal - es6 tests', require('./es6tests'));
testCases(es6equalReact, 'es6 equal react - es6 tests', require('./es6tests'));

function testCases(equalFunc, suiteName, suiteTests) {
describe(suiteName, function() {
Expand Down
71 changes: 71 additions & 0 deletions spec/react.spec.js
@@ -0,0 +1,71 @@
'use strict';

const assert = require('assert');
const sinon = require('sinon');
const React = require('react');
const ReactTestRenderer = require('react-test-renderer');

const equal1 = require('../es6/react');
const equal2 = require('../react');

const run = equal => {
class ChildWithShouldComponentUpdate extends React.Component {
shouldComponentUpdate(nextProps) {
// this.props.children is a h1 with a circular reference to its owner, Container
return !equal(this.props, nextProps);
}
render() {
return null;
}
}

class Container extends React.Component {
render() {
return React.createElement(ChildWithShouldComponentUpdate, {
children: [
React.createElement('h1', this.props.title || ''),
React.createElement('h2', this.props.subtitle || '')
]
});
}
}

describe('advanced', () => {
let sandbox;
let warnStub;
let childRenderSpy;

beforeEach(() => {
sandbox = sinon.createSandbox();
warnStub = sandbox.stub(console, 'warn');
childRenderSpy = sandbox.spy(ChildWithShouldComponentUpdate.prototype, 'render');
});

afterEach(() => {
sandbox.restore();
});

describe('React', () => {
describe('element (with circular references)', () => {
it('compares without warning or errors', () => {
const testRenderer = ReactTestRenderer.create(React.createElement(Container));
testRenderer.update(React.createElement(Container));
assert.strictEqual(warnStub.callCount, 0);
});
it('elements of same type and props are equal', () => {
const testRenderer = ReactTestRenderer.create(React.createElement(Container));
testRenderer.update(React.createElement(Container));
assert.strictEqual(childRenderSpy.callCount, 1);
});
it('elements of same type with different props are not equal', () => {
const testRenderer = ReactTestRenderer.create(React.createElement(Container));
testRenderer.update(React.createElement(Container, { title: 'New' }));
assert.strictEqual(childRenderSpy.callCount, 2);
});
});
});
});
};

run(equal1);
run(equal2);
8 changes: 8 additions & 0 deletions src/index.jst
Expand Up @@ -60,6 +60,14 @@ module.exports = function equal(a, b) {

for (i = length; i-- !== 0;) {
var key = keys[i];
{{? it.react }}
if (key === '_owner' && a.$$typeof) {
// React-specific: avoid traversing React elements' _owner.
// _owner contains circular references
// and is not needed when comparing the actual elements (and not their owners)
continue;
}
{{?}}
if (!equal(a[key], b[key])) return false;
}

Expand Down

0 comments on commit a42246e

Please sign in to comment.