pax_global_header00006660000000000000000000000064131213073210014503gustar00rootroot0000000000000052 comment=b876854e5e56eb5baf79eb434d4bcb81f4c30b9a fast-deep-equal-1.0.0/000077500000000000000000000000001312130732100144565ustar00rootroot00000000000000fast-deep-equal-1.0.0/.eslintrc.yml000066400000000000000000000012231312130732100171000ustar00rootroot00000000000000env: node: true extends: 'eslint:recommended' rules: indent: [ 2, 2, { SwitchCase: 1 } ] no-trailing-spaces: 2 quotes: [ 2, single, avoid-escape ] linebreak-style: [ 2, unix ] semi: [ 2, always ] valid-jsdoc: [ 2, { requireReturn: false } ] no-invalid-this: 2 no-unused-vars: [ 2, { args: none } ] no-console: [ 2, { allow: [ warn, error ] } ] block-scoped-var: 2 curly: [ 2, multi-or-nest, consistent ] dot-location: [ 2, property ] dot-notation: 2 no-else-return: 2 no-eq-null: 2 no-fallthrough: 2 no-return-assign: 2 strict: [ 2, global ] no-use-before-define: [ 2, nofunc ] callback-return: 2 no-path-concat: 2 fast-deep-equal-1.0.0/.gitignore000066400000000000000000000015761312130732100164570ustar00rootroot00000000000000# Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # Typescript v1 declaration files typings/ # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .DS_Store fast-deep-equal-1.0.0/.travis.yml000066400000000000000000000001541312130732100165670ustar00rootroot00000000000000language: node_js node_js: - "4" - "6" - "7" - "8" after_script: - coveralls < coverage/lcov.info fast-deep-equal-1.0.0/LICENSE000066400000000000000000000020621312130732100154630ustar00rootroot00000000000000MIT License Copyright (c) 2017 Evgeny Poberezkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fast-deep-equal-1.0.0/README.md000066400000000000000000000027061312130732100157420ustar00rootroot00000000000000# fast-deep-equal The fastest deep equal [![Build Status](https://travis-ci.org/epoberezkin/fast-deep-equal.svg?branch=master)](https://travis-ci.org/epoberezkin/fast-deep-equal) [![npm version](https://badge.fury.io/js/fast-deep-equal.svg)](http://badge.fury.io/js/fast-deep-equal) [![Coverage Status](https://coveralls.io/repos/github/epoberezkin/fast-deep-equal/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/fast-deep-equal?branch=master) ## Install ```bash npm install fast-deep-equal ``` ## Features - ES5 compatible - works in node.js (0.10+) and browsers (IE9+) - checks equality of Date and RegExp objects by value. ## Usage ```javascript var equal = require('fast-deep-equal'); console.log(equal({foo: 'bar'}, {foo: 'bar'})); // true ``` ## Performance benchmark ``` fast-deep-equal x 82,915 ops/sec ±0.63% (89 runs sampled) nano-equal x 50,506 ops/sec ±2.23% (86 runs sampled) shallow-equal-fuzzy x 14,873 ops/sec ±3.19% (83 runs sampled) underscore.isEqual x 16,055 ops/sec ±2.29% (85 runs sampled) lodash.isEqual x 10,740 ops/sec ±1.04% (89 runs sampled) deep-equal x 12,276 ops/sec ±2.44% (84 runs sampled) deep-eql x 10,565 ops/sec ±0.89% (90 runs sampled) assert.deepStrictEqual x 965 ops/sec ±2.99% (81 runs sampled) The fastest is fast-deep-equal ``` To run benchmark (requires node.js 6+): ```bash npm install node benchmark ``` ## License [MIT](https://github.com/epoberezkin/fast-deep-equal/blob/master/LICENSE) fast-deep-equal-1.0.0/benchmark/000077500000000000000000000000001312130732100164105ustar00rootroot00000000000000fast-deep-equal-1.0.0/benchmark/.eslintrc.yml000066400000000000000000000001171312130732100210330ustar00rootroot00000000000000parserOptions: ecmaVersion: 2016 rules: no-invalid-this: 0 no-console: 0 fast-deep-equal-1.0.0/benchmark/index.js000066400000000000000000000030661312130732100200620ustar00rootroot00000000000000'use strict'; const assertDeepStrictEqual = require('assert').deepStrictEqual; const tests = require('../spec/tests'); const Benchmark = require('benchmark'); const suite = new Benchmark.Suite; const equalPackages = { 'fast-deep-equal': require('../index'), 'nano-equal': true, 'shallow-equal-fuzzy': true, 'underscore.isEqual': require('underscore').isEqual, 'lodash.isEqual': require('lodash').isEqual, 'deep-equal': true, 'deep-eql': true, 'assert.deepStrictEqual': (a, b) => { try { assertDeepStrictEqual(a, b); return true; } catch(e) { return false; } } }; for (const equalName in equalPackages) { let equalFunc = equalPackages[equalName]; if (equalFunc === true) equalFunc = require(equalName); for (const testSuite of tests) { for (const test of testSuite.tests) { try { if (equalFunc(test.value1, test.value2) !== test.equal) console.error('different result', equalName, testSuite.description, test.description); } catch(e) { console.error(equalName, testSuite.description, test.description, e); } } } suite.add(equalName, function() { for (const testSuite of tests) { for (const test of testSuite.tests) { if (test.description != 'pseudo array and equivalent array are not equal') equalFunc(test.value1, test.value2); } } }); } console.log(); suite .on('cycle', (event) => console.log(String(event.target))) .on('complete', function () { console.log('The fastest is ' + this.filter('fastest').map('name')); }) .run({async: true}); fast-deep-equal-1.0.0/index.js000066400000000000000000000021341312130732100161230ustar00rootroot00000000000000'use strict'; module.exports = function equal(a, b) { if (a === b) return true; var arrA = Array.isArray(a) , arrB = Array.isArray(b) , i; if (arrA && arrB) { if (a.length != b.length) return false; for (i = 0; i < a.length; i++) if (!equal(a[i], b[i])) return false; return true; } if (arrA != arrB) return false; if (a && b && typeof a === 'object' && typeof b === 'object') { var keys = Object.keys(a); if (keys.length !== Object.keys(b).length) return false; var dateA = a instanceof Date , dateB = b instanceof Date; if (dateA && dateB) return a.getTime() == b.getTime(); if (dateA != dateB) return false; var regexpA = a instanceof RegExp , regexpB = b instanceof RegExp; if (regexpA && regexpB) return a.toString() == b.toString(); if (regexpA != regexpB) return false; for (i = 0; i < keys.length; i++) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; for (i = 0; i < keys.length; i++) if(!equal(a[keys[i]], b[keys[i]])) return false; return true; } return false; }; fast-deep-equal-1.0.0/package.json000066400000000000000000000022421312130732100167440ustar00rootroot00000000000000{ "name": "fast-deep-equal", "version": "1.0.0", "description": "Fast deep equal", "main": "index.js", "scripts": { "eslint": "eslint *.js benchmark spec", "test-spec": "mocha spec/*.spec.js -R spec", "test-cov": "nyc npm run test-spec", "test": "npm run eslint && npm run test-cov" }, "repository": { "type": "git", "url": "git+https://github.com/epoberezkin/fast-deep-equal.git" }, "keywords": [ "fast", "equal", "deep-equal" ], "author": "Evgeny Poberezkin", "license": "MIT", "bugs": { "url": "https://github.com/epoberezkin/fast-deep-equal/issues" }, "homepage": "https://github.com/epoberezkin/fast-deep-equal#readme", "devDependencies": { "benchmark": "^2.1.4", "coveralls": "^2.13.1", "deep-eql": "^2.0.2", "deep-equal": "^1.0.1", "eslint": "^4.0.0", "lodash": "^4.17.4", "mocha": "^3.4.2", "nano-equal": "^1.0.1", "nyc": "^11.0.2", "pre-commit": "^1.2.2", "shallow-equal-fuzzy": "0.0.2", "underscore": "^1.8.3" }, "nyc": { "exclude": [ "**/spec/**", "node_modules" ], "reporter": [ "lcov", "text-summary" ] } } fast-deep-equal-1.0.0/spec/000077500000000000000000000000001312130732100154105ustar00rootroot00000000000000fast-deep-equal-1.0.0/spec/.eslintrc.yml000066400000000000000000000000761312130732100200370ustar00rootroot00000000000000rules: no-console: 0 globals: describe: false it: false fast-deep-equal-1.0.0/spec/index.spec.js000066400000000000000000000006521312130732100200110ustar00rootroot00000000000000'use strict'; var equal = require('../index'); var tests = require('./tests'); var assert = require('assert'); describe('equal', function() { tests.forEach(function (suite) { describe(suite.description, function() { suite.tests.forEach(function (test) { it(test.description, function() { assert.strictEqual(equal(test.value1, test.value2), test.equal); }); }); }); }); }); fast-deep-equal-1.0.0/spec/tests.js000066400000000000000000000166351312130732100171230ustar00rootroot00000000000000'use strict'; module.exports = [ { description: 'scalars', tests: [ { description: 'equal numbers', value1: 1, value2: 1, equal: true }, { description: 'not equal numbers', value1: 1, value2: 2, equal: false }, { description: 'number and array are not equal', value1: 1, value2: [], equal: false }, { description: '0 and null are not equal', value1: 0, value2: null, equal: false }, { description: 'equal strings', value1: 'a', value2: 'a', equal: true }, { description: 'not equal strings', value1: 'a', value2: 'b', equal: false }, { description: 'empty string and null are not equal', value1: '', value2: null, equal: false }, { description: 'null is equal to null', value1: null, value2: null, equal: true }, { description: 'equal booleans (true)', value1: true, value2: true, equal: true }, { description: 'equal booleans (false)', value1: false, value2: false, equal: true }, { description: 'not equal booleans', value1: true, value2: false, equal: false }, { description: '1 and true are not equal', value1: 1, value2: true, equal: false }, { description: '0 and false are not equal', value1: 0, value2: false, equal: false } ] }, { description: 'objects', tests: [ { description: 'empty objects are equal', value1: {}, value2: {}, equal: true }, { description: 'equal objects (same properties "order")', value1: {a: 1, b: '2'}, value2: {a: 1, b: '2'}, equal: true }, { description: 'equal objects (different properties "order")', value1: {a: 1, b: '2'}, value2: {b: '2', a: 1}, equal: true }, { description: 'not equal objects (extra property)', value1: {a: 1, b: '2'}, value2: {a: 1, b: '2', c: []}, equal: false }, { description: 'not equal objects (different properties)', value1: {a: 1, b: '2', c: 3}, value2: {a: 1, b: '2', d: 3}, equal: false }, { description: 'not equal objects (different properties)', value1: {a: 1, b: '2', c: 3}, value2: {a: 1, b: '2', d: 3}, equal: false }, { description: 'equal objects (same sub-properties)', value1: { a: [ { b: 'c' } ] }, value2: { a: [ { b: 'c' } ] }, equal: true }, { description: 'not equal objects (different sub-property value)', value1: { a: [ { b: 'c' } ] }, value2: { a: [ { b: 'd' } ] }, equal: false }, { description: 'not equal objects (different sub-property)', value1: { a: [ { b: 'c' } ] }, value2: { a: [ { c: 'c' } ] }, equal: false }, { description: 'empty array and empty object are not equal', value1: {}, value2: [], equal: false }, { description: 'object with extra undefined properties are not equal #1', value1: {}, value2: {foo: undefined}, equal: false }, { description: 'object with extra undefined properties are not equal #2', value1: {foo: undefined}, value2: {}, equal: false }, { description: 'object with extra undefined properties are not equal #3', value1: {foo: undefined}, value2: {bar: undefined}, equal: false } ] }, { description: 'arrays', tests: [ { description: 'two empty arrays are equal', value1: [], value2: [], equal: true }, { description: 'equal arrays', value1: [1, 2, 3], value2: [1, 2, 3], equal: true }, { description: 'not equal arrays (different item)', value1: [1, 2, 3], value2: [1, 2, 4], equal: false }, { description: 'not equal arrays (different length)', value1: [1, 2, 3], value2: [1, 2], equal: false }, { description: 'equal arrays of objects', value1: [{a: 'a'}, {b: 'b'}], value2: [{a: 'a'}, {b: 'b'}], equal: true }, { description: 'not equal arrays of objects', value1: [{a: 'a'}, {b: 'b'}], value2: [{a: 'a'}, {b: 'c'}], equal: false }, { description: 'pseudo array and equivalent array are not equal', value1: {'0': 0, '1': 1, length: 2}, value2: [0, 1], equal: false } ] }, { description: 'Date objects', tests: [ { description: 'equal date objects', value1: new Date('2017-06-16T21:36:48.362Z'), value2: new Date('2017-06-16T21:36:48.362Z'), equal: true }, { description: 'not equal date objects', value1: new Date('2017-06-16T21:36:48.362Z'), value2: new Date('2017-01-01T00:00:00.000Z'), equal: false }, { description: 'date and string are not equal', value1: new Date('2017-06-16T21:36:48.362Z'), value2: '2017-06-16T21:36:48.362Z', equal: false }, { description: 'date and object are not equal', value1: new Date('2017-06-16T21:36:48.362Z'), value2: {}, equal: false } ] }, { description: 'RegExp objects', tests: [ { description: 'equal RegExp objects', value1: /foo/, value2: /foo/, equal: true }, { description: 'not equal RegExp objects (different pattern)', value1: /foo/, value2: /bar/, equal: false }, { description: 'not equal RegExp objects (different flags)', value1: /foo/, value2: /foo/i, equal: false }, { description: 'RegExp and string are not equal', value1: /foo/, value2: 'foo', equal: false }, { description: 'RegExp and object are not equal', value1: /foo/, value2: {}, equal: false } ] }, { description: 'sample objects', tests: [ { description: 'big object', value1: { prop1: 'value1', prop2: 'value2', prop3: 'value3', prop4: { subProp1: 'sub value1', subProp2: { subSubProp1: 'sub sub value1', subSubProp2: [1, 2, {prop2: 1, prop: 2}, 4, 5] } }, prop5: 1000, prop6: new Date(2016, 2, 10) }, value2: { prop5: 1000, prop3: 'value3', prop1: 'value1', prop2: 'value2', prop6: new Date('2016/03/10'), prop4: { subProp2: { subSubProp1: 'sub sub value1', subSubProp2: [1, 2, {prop2: 1, prop: 2}, 4, 5] }, subProp1: 'sub value1' } }, equal: true } ] } ];