├── .npmrc ├── assert.js ├── .github └── workflows │ ├── node-pretest.yml │ ├── rebase.yml │ ├── require-allow-edits.yml │ ├── node-aught.yml │ ├── node-tens.yml │ └── node-assert.yml ├── .gitignore ├── example └── cmp.js ├── .nycrc ├── .eslintrc ├── LICENSE ├── test ├── _tape.js └── cmp.js ├── readme.markdown ├── package.json ├── index.js └── CHANGELOG.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | allow-same-version=true 3 | message=v%s 4 | -------------------------------------------------------------------------------- /assert.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('assert'); 4 | -------------------------------------------------------------------------------- /.github/workflows/node-pretest.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: pretest/posttest' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/pretest.yml@main 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | 3 | node_modules 4 | 5 | # Only apps should have lockfiles 6 | npm-shrinkwrap.json 7 | package-lock.json 8 | yarn.lock 9 | 10 | coverage 11 | .nyc_output 12 | 13 | .npmignore 14 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | uses: ljharb/actions/.github/workflows/rebase.yml@main 8 | secrets: 9 | token: ${{ secrets.GITHUB_TOKEN }} 10 | -------------------------------------------------------------------------------- /example/cmp.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var equal = require('../'); 4 | console.dir([ 5 | equal( 6 | { a: [2, 3], b: [4] }, 7 | { a: [2, 3], b: [4] } 8 | ), 9 | equal( 10 | { x: 5, y: [6] }, 11 | { x: 5, y: 6 } 12 | ) 13 | ]); 14 | -------------------------------------------------------------------------------- /.github/workflows/require-allow-edits.yml: -------------------------------------------------------------------------------- 1 | name: Require “Allow Edits” 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | name: "Require “Allow Edits”" 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: ljharb/require-allow-edits@main 13 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "extension": [ 3 | ".js", 4 | ".cjs", 5 | ".mjs" 6 | ], 7 | "all": true, 8 | "check-coverage": false, 9 | "reporter": ["text-summary", "text", "html", "json", "lcov"], 10 | "exclude": [ 11 | "coverage", 12 | "example", 13 | "test" 14 | ], 15 | "sourceMap": true, 16 | "instrument": true 17 | } 18 | -------------------------------------------------------------------------------- /.github/workflows/node-aught.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js < 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '< 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node < 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.github/workflows/node-tens.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js >= 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '>= 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node >= 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: 'echo tests completed' 19 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | 4 | "extends": "@ljharb", 5 | 6 | "rules": { 7 | "complexity": 0, 8 | "eqeqeq": [2, "always", { "null": "ignore" }], 9 | "func-style": [2, "declaration"], 10 | "id-length": 0, 11 | "indent": [2, 2], 12 | "max-params": [2, 6], 13 | "max-statements-per-line": [2, { "max": 2 }], 14 | "new-cap": [2, { "capIsNewExceptions": ["GetIntrinsic"] }], 15 | "no-magic-numbers": [2, { "ignore": [0, 1] }], 16 | }, 17 | 18 | "globals": { 19 | "Int8Array": false, 20 | "Uint8Array": false, 21 | }, 22 | 23 | "overrides": [ 24 | { 25 | "files": "example/**", 26 | "rules": { 27 | "no-console": 0, 28 | "no-magic-numbers": 0, 29 | } 30 | }, 31 | { 32 | "files": "test/**", 33 | "rules": { 34 | "max-lines-per-function": 0, 35 | "max-params": 0, 36 | "no-magic-numbers": 0, 37 | }, 38 | }, 39 | ], 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012, 2013, 2014 James Halliday , 2009 Thomas Robinson <280north.com> 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/_tape.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Test = require('tape/lib/test'); 4 | var is = require('object-is'); 5 | 6 | var deepEqual = require('../'); 7 | var assert = require('../assert'); 8 | 9 | var equal = process.env.ASSERT ? function assertDeepEqual(a, b, options) { 10 | try { 11 | if (options && options.strict) { 12 | assert.deepStrictEqual(a, b); 13 | } else { 14 | assert.deepEqual(a, b); 15 | } 16 | } catch (e) { 17 | return false; 18 | } 19 | return true; 20 | } : deepEqual; 21 | 22 | function equalReversed(t, a, b, isEqual, msg, isStrict, skipReversed) { 23 | var actual = isStrict 24 | ? equal(a, b, { strict: true }) 25 | : equal(a, b); 26 | var suffix = isEqual ? ' are equal' : ' are not equal'; 27 | t.equal(actual, !!isEqual, msg + suffix); 28 | if (typeof skipReversed === 'boolean' ? !skipReversed : !is(a, b)) { 29 | var actualReverse = isStrict 30 | ? equal(b, a, { strict: true }) 31 | : equal(b, a); 32 | t.equal(actualReverse, !!isEqual, msg + suffix + ' (reversed)'); 33 | } 34 | } 35 | function deepEqualTest(t, a, b, msg, isEqual, isStrictEqual, skipReversed) { 36 | equalReversed(t, a, b, isEqual, msg, false, skipReversed); 37 | equalReversed(t, a, b, isStrictEqual, 'strict: ' + msg, true, skipReversed); 38 | } 39 | 40 | Test.prototype.deepEqualTest = function (a, b, message, isEqual, isStrictEqual, skipReversed) { 41 | return deepEqualTest(this, a, b, message, !!isEqual, !!isStrictEqual, skipReversed); 42 | }; 43 | -------------------------------------------------------------------------------- /.github/workflows/node-assert.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js `assert`' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | matrix: 7 | runs-on: ubuntu-latest 8 | outputs: 9 | requireds: ${{ steps.set-matrix.outputs.requireds }} 10 | optionals: ${{ steps.set-matrix.outputs.optionals }} 11 | steps: 12 | - uses: ljharb/actions/node/matrix@main 13 | id: set-matrix 14 | with: 15 | type: 'majors' 16 | requireds: '^12.16 || >= 13.4' 17 | optionals: '>= 8 < 12.16 || ^13.0 < 13.4' 18 | 19 | assert-required: 20 | needs: [matrix] 21 | name: 'assert: required' 22 | runs-on: ubuntu-latest 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: ${{ fromJson(needs.matrix.outputs.requireds) }} 27 | 28 | steps: 29 | - uses: actions/checkout@v2 30 | - uses: ljharb/actions/node/install@main 31 | name: 'nvm install ${{ matrix.node-version }} && npm install' 32 | with: 33 | node-version: ${{ matrix.node-version }} 34 | - run: npm run tests-only 35 | env: 36 | ASSERT: true 37 | - uses: codecov/codecov-action@v2 38 | 39 | assert-optional: 40 | needs: [matrix] 41 | name: 'assert: optional' 42 | runs-on: ubuntu-latest 43 | continue-on-error: true 44 | 45 | strategy: 46 | fail-fast: false 47 | matrix: ${{ fromJson(needs.matrix.outputs.optionals) }} 48 | 49 | steps: 50 | - uses: actions/checkout@v2 51 | - uses: ljharb/actions/node/install@main 52 | name: 'nvm install ${{ matrix.node-version }} && npm install' 53 | with: 54 | node-version: ${{ matrix.node-version }} 55 | - run: npm run tests-only 56 | env: 57 | ASSERT: true 58 | - uses: codecov/codecov-action@v2 59 | 60 | assert: 61 | name: 'node: assert' 62 | needs: [assert-required, assert-optional] 63 | runs-on: ubuntu-latest 64 | steps: 65 | - run: 'echo tests completed' 66 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # deep-equal [![Version Badge][npm-version-svg]][package-url] 2 | 3 | Node's `assert.deepEqual() algorithm` as a standalone module, that also works in browser environments. 4 | 5 | It mirrors the robustness of node's own `assert.deepEqual` and is robust against later builtin modification. 6 | 7 | [![github actions][actions-image]][actions-url] 8 | [![coverage][codecov-image]][codecov-url] 9 | [![License][license-image]][license-url] 10 | [![Downloads][downloads-image]][downloads-url] 11 | 12 | [![npm badge][npm-badge-png]][package-url] 13 | 14 | # example 15 | 16 | ``` js 17 | var equal = require('deep-equal'); 18 | console.dir([ 19 | equal( 20 | { a : [ 2, 3 ], b : [ 4 ] }, 21 | { a : [ 2, 3 ], b : [ 4 ] } 22 | ), 23 | equal( 24 | { x : 5, y : [6] }, 25 | { x : 5, y : 6 } 26 | ) 27 | ]); 28 | ``` 29 | 30 | # methods 31 | 32 | ``` js 33 | var deepEqual = require('deep-equal') 34 | ``` 35 | 36 | ## deepEqual(a, b, opts) 37 | 38 | Compare objects `a` and `b`, returning whether they are equal according to a recursive equality algorithm. 39 | 40 | If `opts.strict` is `true`, use strict equality (`===`) to compare leaf nodes. 41 | The default is to use coercive equality (`==`) because that's how `assert.deepEqual()` works by default. 42 | 43 | # install 44 | 45 | With [npm](https://npmjs.org) do: 46 | 47 | ``` 48 | npm install deep-equal 49 | ``` 50 | 51 | # test 52 | 53 | With [npm](https://npmjs.org) do: 54 | 55 | ``` 56 | npm test 57 | ``` 58 | 59 | [package-url]: https://npmjs.org/package/deep-equal 60 | [npm-version-svg]: https://versionbadg.es/inspect-js/deep-equal.svg 61 | [deps-svg]: https://david-dm.org/inspect-js/node-deep-equal.svg 62 | [deps-url]: https://david-dm.org/inspect-js/node-deep-equal 63 | [dev-deps-svg]: https://david-dm.org/inspect-js/node-deep-equal/dev-status.svg 64 | [dev-deps-url]: https://david-dm.org/inspect-js/node-deep-equal#info=devDependencies 65 | [npm-badge-png]: https://nodei.co/npm/deep-equal.png?downloads=true&stars=true 66 | [license-image]: https://img.shields.io/npm/l/deep-equal.svg 67 | [license-url]: LICENSE 68 | [downloads-image]: https://img.shields.io/npm/dm/deep-equal.svg 69 | [downloads-url]: https://npm-stat.com/charts.html?package=deep-equal 70 | [codecov-image]: https://codecov.io/gh/inspect-js/node-deep-equal/branch/main/graphs/badge.svg 71 | [codecov-url]: https://app.codecov.io/gh/inspect-js/node-deep-equal/ 72 | [actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/inspect-js/node-deep-equal 73 | [actions-url]: https://github.com/inspect-js/node-deep-equal/actions 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deep-equal", 3 | "version": "2.2.3", 4 | "description": "node's assert.deepEqual algorithm", 5 | "main": "index.js", 6 | "exports": { 7 | ".": [ 8 | { 9 | "default": "./index.js" 10 | }, 11 | "./index.js" 12 | ], 13 | "./package": "./package.json", 14 | "./package.json": "./package.json" 15 | }, 16 | "directories": { 17 | "lib": ".", 18 | "example": "example", 19 | "test": "test" 20 | }, 21 | "scripts": { 22 | "prepack": "npmignore --auto --commentLines=autogenerated", 23 | "prepublish": "not-in-publish || npm run prepublishOnly", 24 | "prepublishOnly": "safe-publish-latest", 25 | "pretest": "npm run lint", 26 | "lint": "eslint --ext=js,mjs .", 27 | "tests-only": "nyc tape 'test/**/*.js'", 28 | "test": "npm run tests-only", 29 | "posttest": "aud --production", 30 | "version": "auto-changelog && git add CHANGELOG.md", 31 | "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" 32 | }, 33 | "dependencies": { 34 | "array-buffer-byte-length": "^1.0.0", 35 | "call-bind": "^1.0.5", 36 | "es-get-iterator": "^1.1.3", 37 | "get-intrinsic": "^1.2.2", 38 | "is-arguments": "^1.1.1", 39 | "is-array-buffer": "^3.0.2", 40 | "is-date-object": "^1.0.5", 41 | "is-regex": "^1.1.4", 42 | "is-shared-array-buffer": "^1.0.2", 43 | "isarray": "^2.0.5", 44 | "object-is": "^1.1.5", 45 | "object-keys": "^1.1.1", 46 | "object.assign": "^4.1.5", 47 | "regexp.prototype.flags": "^1.5.1", 48 | "side-channel": "^1.0.4", 49 | "which-boxed-primitive": "^1.0.2", 50 | "which-collection": "^1.0.1", 51 | "which-typed-array": "^1.1.13" 52 | }, 53 | "devDependencies": { 54 | "@ljharb/eslint-config": "^21.1.0", 55 | "aud": "^2.0.4", 56 | "auto-changelog": "^2.4.0", 57 | "available-typed-arrays": "^1.0.5", 58 | "eslint": "=8.8.0", 59 | "for-each": "^0.3.3", 60 | "has-proto": "^1.0.1", 61 | "has-symbols": "^1.0.3", 62 | "has-typed-arrays": "^1.0.1", 63 | "in-publish": "^2.0.1", 64 | "npmignore": "^0.3.1", 65 | "nyc": "^10.3.2", 66 | "object.getownpropertydescriptors": "^2.1.7", 67 | "safe-publish-latest": "^2.0.0", 68 | "semver": "^6.3.1", 69 | "tape": "^5.7.4" 70 | }, 71 | "repository": { 72 | "type": "git", 73 | "url": "http://github.com/inspect-js/node-deep-equal.git" 74 | }, 75 | "keywords": [ 76 | "equality", 77 | "equal", 78 | "compare" 79 | ], 80 | "author": { 81 | "name": "James Halliday", 82 | "email": "mail@substack.net", 83 | "url": "http://substack.net" 84 | }, 85 | "contributors": [ 86 | "James Halliday (https://substack.net)", 87 | "Jordan Harband " 88 | ], 89 | "funding": { 90 | "url": "https://github.com/sponsors/ljharb" 91 | }, 92 | "license": "MIT", 93 | "engines": { 94 | "node": ">= 0.4" 95 | }, 96 | "testling": { 97 | "files": "test/*.js", 98 | "browsers": { 99 | "ie": [ 100 | 6, 101 | 7, 102 | 8, 103 | 9 104 | ], 105 | "ff": [ 106 | 3.5, 107 | 10, 108 | 15 109 | ], 110 | "chrome": [ 111 | 10, 112 | 22 113 | ], 114 | "safari": [ 115 | 5.1 116 | ], 117 | "opera": [ 118 | 12 119 | ] 120 | } 121 | }, 122 | "auto-changelog": { 123 | "output": "CHANGELOG.md", 124 | "template": "keepachangelog", 125 | "unreleased": false, 126 | "commitLimit": false, 127 | "backfillLimit": false, 128 | "hideCredit": true 129 | }, 130 | "browser": { 131 | "assert.js": false 132 | }, 133 | "publishConfig": { 134 | "ignore": [ 135 | ".github/workflows" 136 | ] 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assign = require('object.assign'); 4 | var callBound = require('call-bind/callBound'); 5 | var flags = require('regexp.prototype.flags'); 6 | var GetIntrinsic = require('get-intrinsic'); 7 | var getIterator = require('es-get-iterator'); 8 | var getSideChannel = require('side-channel'); 9 | var is = require('object-is'); 10 | var isArguments = require('is-arguments'); 11 | var isArray = require('isarray'); 12 | var isArrayBuffer = require('is-array-buffer'); 13 | var isDate = require('is-date-object'); 14 | var isRegex = require('is-regex'); 15 | var isSharedArrayBuffer = require('is-shared-array-buffer'); 16 | var objectKeys = require('object-keys'); 17 | var whichBoxedPrimitive = require('which-boxed-primitive'); 18 | var whichCollection = require('which-collection'); 19 | var whichTypedArray = require('which-typed-array'); 20 | var byteLength = require('array-buffer-byte-length'); 21 | 22 | var sabByteLength = callBound('SharedArrayBuffer.prototype.byteLength', true); 23 | 24 | var $getTime = callBound('Date.prototype.getTime'); 25 | var gPO = Object.getPrototypeOf; 26 | var $objToString = callBound('Object.prototype.toString'); 27 | 28 | var $Set = GetIntrinsic('%Set%', true); 29 | var $mapHas = callBound('Map.prototype.has', true); 30 | var $mapGet = callBound('Map.prototype.get', true); 31 | var $mapSize = callBound('Map.prototype.size', true); 32 | var $setAdd = callBound('Set.prototype.add', true); 33 | var $setDelete = callBound('Set.prototype.delete', true); 34 | var $setHas = callBound('Set.prototype.has', true); 35 | var $setSize = callBound('Set.prototype.size', true); 36 | 37 | // taken from https://github.com/browserify/commonjs-assert/blob/bba838e9ba9e28edf3127ce6974624208502f6bc/internal/util/comparisons.js#L401-L414 38 | function setHasEqualElement(set, val1, opts, channel) { 39 | var i = getIterator(set); 40 | var result; 41 | while ((result = i.next()) && !result.done) { 42 | if (internalDeepEqual(val1, result.value, opts, channel)) { // eslint-disable-line no-use-before-define 43 | // Remove the matching element to make sure we do not check that again. 44 | $setDelete(set, result.value); 45 | return true; 46 | } 47 | } 48 | 49 | return false; 50 | } 51 | 52 | // taken from https://github.com/browserify/commonjs-assert/blob/bba838e9ba9e28edf3127ce6974624208502f6bc/internal/util/comparisons.js#L416-L439 53 | function findLooseMatchingPrimitives(prim) { 54 | if (typeof prim === 'undefined') { 55 | return null; 56 | } 57 | if (typeof prim === 'object') { // Only pass in null as object! 58 | return void 0; 59 | } 60 | if (typeof prim === 'symbol') { 61 | return false; 62 | } 63 | if (typeof prim === 'string' || typeof prim === 'number') { 64 | // Loose equal entries exist only if the string is possible to convert to a regular number and not NaN. 65 | return +prim === +prim; // eslint-disable-line no-implicit-coercion 66 | } 67 | return true; 68 | } 69 | 70 | // taken from https://github.com/browserify/commonjs-assert/blob/bba838e9ba9e28edf3127ce6974624208502f6bc/internal/util/comparisons.js#L449-L460 71 | function mapMightHaveLoosePrim(a, b, prim, item, opts, channel) { 72 | var altValue = findLooseMatchingPrimitives(prim); 73 | if (altValue != null) { 74 | return altValue; 75 | } 76 | var curB = $mapGet(b, altValue); 77 | var looseOpts = assign({}, opts, { strict: false }); 78 | if ( 79 | (typeof curB === 'undefined' && !$mapHas(b, altValue)) 80 | // eslint-disable-next-line no-use-before-define 81 | || !internalDeepEqual(item, curB, looseOpts, channel) 82 | ) { 83 | return false; 84 | } 85 | // eslint-disable-next-line no-use-before-define 86 | return !$mapHas(a, altValue) && internalDeepEqual(item, curB, looseOpts, channel); 87 | } 88 | 89 | // taken from https://github.com/browserify/commonjs-assert/blob/bba838e9ba9e28edf3127ce6974624208502f6bc/internal/util/comparisons.js#L441-L447 90 | function setMightHaveLoosePrim(a, b, prim) { 91 | var altValue = findLooseMatchingPrimitives(prim); 92 | if (altValue != null) { 93 | return altValue; 94 | } 95 | 96 | return $setHas(b, altValue) && !$setHas(a, altValue); 97 | } 98 | 99 | // taken from https://github.com/browserify/commonjs-assert/blob/bba838e9ba9e28edf3127ce6974624208502f6bc/internal/util/comparisons.js#L518-L533 100 | function mapHasEqualEntry(set, map, key1, item1, opts, channel) { 101 | var i = getIterator(set); 102 | var result; 103 | var key2; 104 | while ((result = i.next()) && !result.done) { 105 | key2 = result.value; 106 | if ( 107 | // eslint-disable-next-line no-use-before-define 108 | internalDeepEqual(key1, key2, opts, channel) 109 | // eslint-disable-next-line no-use-before-define 110 | && internalDeepEqual(item1, $mapGet(map, key2), opts, channel) 111 | ) { 112 | $setDelete(set, key2); 113 | return true; 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | function internalDeepEqual(actual, expected, options, channel) { 121 | var opts = options || {}; 122 | 123 | // 7.1. All identical values are equivalent, as determined by ===. 124 | if (opts.strict ? is(actual, expected) : actual === expected) { 125 | return true; 126 | } 127 | 128 | var actualBoxed = whichBoxedPrimitive(actual); 129 | var expectedBoxed = whichBoxedPrimitive(expected); 130 | if (actualBoxed !== expectedBoxed) { 131 | return false; 132 | } 133 | 134 | // 7.3. Other pairs that do not both pass typeof value == 'object', equivalence is determined by ==. 135 | if (!actual || !expected || (typeof actual !== 'object' && typeof expected !== 'object')) { 136 | return opts.strict ? is(actual, expected) : actual == expected; // eslint-disable-line eqeqeq 137 | } 138 | 139 | /* 140 | * 7.4. For all other Object pairs, including Array objects, equivalence is 141 | * determined by having the same number of owned properties (as verified 142 | * with Object.prototype.hasOwnProperty.call), the same set of keys 143 | * (although not necessarily the same order), equivalent values for every 144 | * corresponding key, and an identical 'prototype' property. Note: this 145 | * accounts for both named and indexed properties on Arrays. 146 | */ 147 | // see https://github.com/nodejs/node/commit/d3aafd02efd3a403d646a3044adcf14e63a88d32 for memos/channel inspiration 148 | 149 | var hasActual = channel.has(actual); 150 | var hasExpected = channel.has(expected); 151 | var sentinel; 152 | if (hasActual && hasExpected) { 153 | if (channel.get(actual) === channel.get(expected)) { 154 | return true; 155 | } 156 | } else { 157 | sentinel = {}; 158 | } 159 | if (!hasActual) { channel.set(actual, sentinel); } 160 | if (!hasExpected) { channel.set(expected, sentinel); } 161 | 162 | // eslint-disable-next-line no-use-before-define 163 | return objEquiv(actual, expected, opts, channel); 164 | } 165 | 166 | function isBuffer(x) { 167 | if (!x || typeof x !== 'object' || typeof x.length !== 'number') { 168 | return false; 169 | } 170 | if (typeof x.copy !== 'function' || typeof x.slice !== 'function') { 171 | return false; 172 | } 173 | if (x.length > 0 && typeof x[0] !== 'number') { 174 | return false; 175 | } 176 | 177 | return !!(x.constructor && x.constructor.isBuffer && x.constructor.isBuffer(x)); 178 | } 179 | 180 | function setEquiv(a, b, opts, channel) { 181 | if ($setSize(a) !== $setSize(b)) { 182 | return false; 183 | } 184 | var iA = getIterator(a); 185 | var iB = getIterator(b); 186 | var resultA; 187 | var resultB; 188 | var set; 189 | while ((resultA = iA.next()) && !resultA.done) { 190 | if (resultA.value && typeof resultA.value === 'object') { 191 | if (!set) { set = new $Set(); } 192 | $setAdd(set, resultA.value); 193 | } else if (!$setHas(b, resultA.value)) { 194 | if (opts.strict) { return false; } 195 | if (!setMightHaveLoosePrim(a, b, resultA.value)) { 196 | return false; 197 | } 198 | if (!set) { set = new $Set(); } 199 | $setAdd(set, resultA.value); 200 | } 201 | } 202 | if (set) { 203 | while ((resultB = iB.next()) && !resultB.done) { 204 | // We have to check if a primitive value is already matching and only if it's not, go hunting for it. 205 | if (resultB.value && typeof resultB.value === 'object') { 206 | if (!setHasEqualElement(set, resultB.value, opts.strict, channel)) { 207 | return false; 208 | } 209 | } else if ( 210 | !opts.strict 211 | && !$setHas(a, resultB.value) 212 | && !setHasEqualElement(set, resultB.value, opts.strict, channel) 213 | ) { 214 | return false; 215 | } 216 | } 217 | return $setSize(set) === 0; 218 | } 219 | return true; 220 | } 221 | 222 | function mapEquiv(a, b, opts, channel) { 223 | if ($mapSize(a) !== $mapSize(b)) { 224 | return false; 225 | } 226 | var iA = getIterator(a); 227 | var iB = getIterator(b); 228 | var resultA; 229 | var resultB; 230 | var set; 231 | var key; 232 | var item1; 233 | var item2; 234 | while ((resultA = iA.next()) && !resultA.done) { 235 | key = resultA.value[0]; 236 | item1 = resultA.value[1]; 237 | if (key && typeof key === 'object') { 238 | if (!set) { set = new $Set(); } 239 | $setAdd(set, key); 240 | } else { 241 | item2 = $mapGet(b, key); 242 | if ((typeof item2 === 'undefined' && !$mapHas(b, key)) || !internalDeepEqual(item1, item2, opts, channel)) { 243 | if (opts.strict) { 244 | return false; 245 | } 246 | if (!mapMightHaveLoosePrim(a, b, key, item1, opts, channel)) { 247 | return false; 248 | } 249 | if (!set) { set = new $Set(); } 250 | $setAdd(set, key); 251 | } 252 | } 253 | } 254 | 255 | if (set) { 256 | while ((resultB = iB.next()) && !resultB.done) { 257 | key = resultB.value[0]; 258 | item2 = resultB.value[1]; 259 | if (key && typeof key === 'object') { 260 | if (!mapHasEqualEntry(set, a, key, item2, opts, channel)) { 261 | return false; 262 | } 263 | } else if ( 264 | !opts.strict 265 | && (!a.has(key) || !internalDeepEqual($mapGet(a, key), item2, opts, channel)) 266 | && !mapHasEqualEntry(set, a, key, item2, assign({}, opts, { strict: false }), channel) 267 | ) { 268 | return false; 269 | } 270 | } 271 | return $setSize(set) === 0; 272 | } 273 | return true; 274 | } 275 | 276 | function objEquiv(a, b, opts, channel) { 277 | /* eslint max-statements: [2, 100], max-lines-per-function: [2, 120], max-depth: [2, 5], max-lines: [2, 400] */ 278 | var i, key; 279 | 280 | if (typeof a !== typeof b) { return false; } 281 | if (a == null || b == null) { return false; } 282 | 283 | if ($objToString(a) !== $objToString(b)) { return false; } 284 | 285 | if (isArguments(a) !== isArguments(b)) { return false; } 286 | 287 | var aIsArray = isArray(a); 288 | var bIsArray = isArray(b); 289 | if (aIsArray !== bIsArray) { return false; } 290 | 291 | // TODO: replace when a cross-realm brand check is available 292 | var aIsError = a instanceof Error; 293 | var bIsError = b instanceof Error; 294 | if (aIsError !== bIsError) { return false; } 295 | if (aIsError || bIsError) { 296 | if (a.name !== b.name || a.message !== b.message) { return false; } 297 | } 298 | 299 | var aIsRegex = isRegex(a); 300 | var bIsRegex = isRegex(b); 301 | if (aIsRegex !== bIsRegex) { return false; } 302 | if ((aIsRegex || bIsRegex) && (a.source !== b.source || flags(a) !== flags(b))) { 303 | return false; 304 | } 305 | 306 | var aIsDate = isDate(a); 307 | var bIsDate = isDate(b); 308 | if (aIsDate !== bIsDate) { return false; } 309 | if (aIsDate || bIsDate) { // && would work too, because both are true or both false here 310 | if ($getTime(a) !== $getTime(b)) { return false; } 311 | } 312 | if (opts.strict && gPO && gPO(a) !== gPO(b)) { return false; } 313 | 314 | var aWhich = whichTypedArray(a); 315 | var bWhich = whichTypedArray(b); 316 | if (aWhich !== bWhich) { 317 | return false; 318 | } 319 | if (aWhich || bWhich) { // && would work too, because both are true or both false here 320 | if (a.length !== b.length) { return false; } 321 | for (i = 0; i < a.length; i++) { 322 | if (a[i] !== b[i]) { return false; } 323 | } 324 | return true; 325 | } 326 | 327 | var aIsBuffer = isBuffer(a); 328 | var bIsBuffer = isBuffer(b); 329 | if (aIsBuffer !== bIsBuffer) { return false; } 330 | if (aIsBuffer || bIsBuffer) { // && would work too, because both are true or both false here 331 | if (a.length !== b.length) { return false; } 332 | for (i = 0; i < a.length; i++) { 333 | if (a[i] !== b[i]) { return false; } 334 | } 335 | return true; 336 | } 337 | 338 | var aIsArrayBuffer = isArrayBuffer(a); 339 | var bIsArrayBuffer = isArrayBuffer(b); 340 | if (aIsArrayBuffer !== bIsArrayBuffer) { return false; } 341 | if (aIsArrayBuffer || bIsArrayBuffer) { // && would work too, because both are true or both false here 342 | if (byteLength(a) !== byteLength(b)) { return false; } 343 | return typeof Uint8Array === 'function' && internalDeepEqual(new Uint8Array(a), new Uint8Array(b), opts, channel); 344 | } 345 | 346 | var aIsSAB = isSharedArrayBuffer(a); 347 | var bIsSAB = isSharedArrayBuffer(b); 348 | if (aIsSAB !== bIsSAB) { return false; } 349 | if (aIsSAB || bIsSAB) { // && would work too, because both are true or both false here 350 | if (sabByteLength(a) !== sabByteLength(b)) { return false; } 351 | return typeof Uint8Array === 'function' && internalDeepEqual(new Uint8Array(a), new Uint8Array(b), opts, channel); 352 | } 353 | 354 | if (typeof a !== typeof b) { return false; } 355 | 356 | var ka = objectKeys(a); 357 | var kb = objectKeys(b); 358 | // having the same number of owned properties (keys incorporates hasOwnProperty) 359 | if (ka.length !== kb.length) { return false; } 360 | 361 | // the same set of keys (although not necessarily the same order), 362 | ka.sort(); 363 | kb.sort(); 364 | // ~~~cheap key test 365 | for (i = ka.length - 1; i >= 0; i--) { 366 | if (ka[i] != kb[i]) { return false; } // eslint-disable-line eqeqeq 367 | } 368 | 369 | // equivalent values for every corresponding key, and ~~~possibly expensive deep test 370 | for (i = ka.length - 1; i >= 0; i--) { 371 | key = ka[i]; 372 | if (!internalDeepEqual(a[key], b[key], opts, channel)) { return false; } 373 | } 374 | 375 | var aCollection = whichCollection(a); 376 | var bCollection = whichCollection(b); 377 | if (aCollection !== bCollection) { 378 | return false; 379 | } 380 | if (aCollection === 'Set' || bCollection === 'Set') { // aCollection === bCollection 381 | return setEquiv(a, b, opts, channel); 382 | } 383 | if (aCollection === 'Map') { // aCollection === bCollection 384 | return mapEquiv(a, b, opts, channel); 385 | } 386 | 387 | return true; 388 | } 389 | 390 | module.exports = function deepEqual(a, b, opts) { 391 | return internalDeepEqual(a, b, opts, getSideChannel()); 392 | }; 393 | -------------------------------------------------------------------------------- /test/cmp.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var test = require('tape'); 4 | require('./_tape'); 5 | var assign = require('object.assign'); 6 | var gOPDs = require('object.getownpropertydescriptors'); 7 | var hasSymbols = require('has-symbols')(); 8 | var hasTypedArrays = require('has-typed-arrays')(); 9 | var semver = require('semver'); 10 | var keys = require('object-keys'); 11 | var availableTypedArrays = require('available-typed-arrays')(); 12 | var forEach = require('for-each'); 13 | var hasProto = require('has-proto')(); 14 | 15 | var safeBuffer = typeof Buffer === 'function' ? Buffer.from && Buffer.from.length > 1 ? Buffer.from : Buffer : null; 16 | var buffersAreTypedArrays = typeof Buffer === 'function' && new Buffer(0) instanceof Uint8Array; 17 | 18 | var isNode = typeof process === 'object' && typeof process.version === 'string'; 19 | 20 | function tag(obj, value) { 21 | if (hasSymbols && Symbol.toStringTag && Object.defineProperty) { 22 | Object.defineProperty(obj, Symbol.toStringTag, { 23 | value: value 24 | }); 25 | } 26 | return obj; 27 | } 28 | 29 | test('equal', function (t) { 30 | t.deepEqualTest( 31 | { a: [2, 3], b: [4] }, 32 | { a: [2, 3], b: [4] }, 33 | 'two equal objects', 34 | true, 35 | true, 36 | false 37 | ); 38 | 39 | var obj1 = { a: [2, 3], b: [4] }; 40 | var obj2 = { b: [4], a: [2, 3] }; 41 | t.notDeepEqual(keys(obj1), keys(obj2), 'keys are in a different order'); 42 | t.deepEqual(keys(obj1), keys(obj2).reverse(), 'keys are in opposite order'); 43 | t.deepEqualTest( 44 | obj1, 45 | obj2, 46 | 'two equal objects, in different order', 47 | true, 48 | true 49 | ); 50 | 51 | t.deepEqualTest( 52 | { a: 2, b: '4' }, 53 | { a: 2, b: 4 }, 54 | 'two loosely equal, strictly inequal objects', 55 | true, 56 | false 57 | ); 58 | 59 | t.deepEqualTest( 60 | { a: 2, b: 4 }, 61 | { a: 2, B: 4 }, 62 | 'two inequal objects', 63 | false, 64 | false 65 | ); 66 | 67 | t.deepEqualTest( 68 | '-000', 69 | false, 70 | '`false` and `"-000"`', 71 | true, 72 | false 73 | ); 74 | 75 | t.end(); 76 | }); 77 | 78 | test('Maps', { skip: typeof Map !== 'function' }, function (t) { 79 | t.deepEqualTest( 80 | new Map([['a', 1], ['b', 2]]), 81 | new Map([['b', 2], ['a', 1]]), 82 | 'two equal Maps', 83 | true, 84 | true 85 | ); 86 | 87 | t.deepEqualTest( 88 | new Map([['a', [1, 2]]]), 89 | new Map([['a', [2, 1]]]), 90 | 'two Maps with inequal values on the same key', 91 | false, 92 | false 93 | ); 94 | 95 | t.deepEqualTest( 96 | new Map([['a', 1]]), 97 | new Map([['b', 1]]), 98 | 'two inequal Maps', 99 | false, 100 | false 101 | ); 102 | 103 | t.deepEqualTest( 104 | new Map([[{}, 3], [{}, 2], [{}, 1]]), 105 | new Map([[{}, 1], [{}, 2], [{}, 3]]), 106 | 'two equal Maps in different orders with object keys', 107 | true, 108 | true 109 | ); 110 | 111 | t.deepEqualTest( 112 | new Map([[undefined, undefined]]), 113 | new Map([[undefined, null]]), 114 | 'undefined keys, nullish values, loosely equal, strictly inequal', 115 | true, 116 | false 117 | ); 118 | 119 | t.deepEqualTest( 120 | new Map([[{}, null], [true, 2], [{}, 1], [undefined, {}]]), 121 | new Map([[{}, 1], [true, 2], [{}, null], [undefined, {}]]), 122 | 'two equal Maps in different orders with primitive keys', 123 | true, 124 | true 125 | ); 126 | 127 | t.deepEqualTest( 128 | new Map([[false, 3], [{}, 2], [{}, 1]]), 129 | new Map([[{}, 1], [{}, 2], [false, 3]]), 130 | 'two equal Maps in different orders with a mix of keys', 131 | true, 132 | true 133 | ); 134 | 135 | t.deepEqualTest( 136 | new Map([[null, undefined]]), 137 | new Map([[null, null]]), 138 | 'null keys, nullish values, loosely equal, strictly inequal', 139 | true, 140 | false 141 | ); 142 | 143 | t.deepEqualTest( 144 | new Map([[undefined, 3]]), 145 | new Map([[null, 3]]), 146 | 'nullish keys, loosely equal, strictly inequal', 147 | true, 148 | false 149 | ); 150 | 151 | t.deepEqualTest( 152 | new Map([[{}, null], [true, 2], [{}, 1], [undefined, {}]]), 153 | new Map([[{}, 1], [true, 2], [{}, null], [undefined, {}]]), 154 | 'two equal Maps in different orders with primitive keys', 155 | true, 156 | true 157 | ); 158 | 159 | t.deepEqualTest( 160 | new Map([[false, 3], [{}, 2], [{}, 1]]), 161 | new Map([[{}, 1], [{}, 2], [false, 3]]), 162 | 'two equal Maps in different orders with a mix of keys', 163 | true, 164 | true 165 | ); 166 | 167 | t.deepEqualTest( 168 | new Map(), 169 | new Map([[{}, 1]]), 170 | 'two inequal Maps', 171 | false, 172 | false 173 | ); 174 | 175 | t.deepEqualTest( 176 | new Map([[{}, null], [false, 3]]), 177 | new Map([[{}, null], [true, 2]]), 178 | 'two inequal maps, same size, primitive key, start with object key', 179 | false, 180 | false 181 | ); 182 | 183 | t.deepEqualTest( 184 | new Map([[false, 3], [{}, null]]), 185 | new Map([[true, 2], [{}, null]]), 186 | 'two inequal maps, same size, primitive key, start with primitive key', 187 | false, 188 | false 189 | ); 190 | 191 | t.deepEqualTest( 192 | new Map([[undefined, null], ['+000', 2]]), 193 | new Map([[null, undefined], [false, '2']]), 194 | 'primitive comparisons', 195 | true, 196 | false 197 | ); 198 | 199 | t.end(); 200 | }); 201 | 202 | test('WeakMaps', { skip: typeof WeakMap !== 'function' }, function (t) { 203 | t.deepEqualTest( 204 | new WeakMap([[Object, null], [Function, true]]), 205 | new WeakMap([[Function, true], [Object, null]]), 206 | 'two equal WeakMaps', 207 | true, 208 | true 209 | ); 210 | 211 | t.deepEqualTest( 212 | new WeakMap([[Object, null]]), 213 | new WeakMap([[Object, true]]), 214 | 'two WeakMaps with inequal values on the same key', 215 | true, 216 | true 217 | ); 218 | 219 | t.deepEqualTest( 220 | new WeakMap([[Object, null], [Function, true]]), 221 | new WeakMap([[Object, null]]), 222 | 'two inequal WeakMaps', 223 | true, 224 | true 225 | ); 226 | 227 | t.end(); 228 | }); 229 | 230 | test('Sets', { skip: typeof Set !== 'function' }, function (t) { 231 | t.deepEqualTest( 232 | new Set(['a', 1, 'b', 2]), 233 | new Set(['b', 2, 'a', 1]), 234 | 'two equal Sets', 235 | true, 236 | true 237 | ); 238 | 239 | t.deepEqualTest( 240 | new Set(['a', 1]), 241 | new Set(['b', 1]), 242 | 'two inequal Sets', 243 | false, 244 | false 245 | ); 246 | 247 | t.deepEqualTest( 248 | new Set([{}, 1, {}, {}, 2]), 249 | new Set([{}, 1, {}, 2, {}]), 250 | 'two equal Sets in different orders', 251 | true, 252 | true 253 | ); 254 | 255 | t.deepEqualTest( 256 | new Set(), 257 | new Set([1]), 258 | 'two inequally sized Sets', 259 | false, 260 | false 261 | ); 262 | 263 | t.deepEqualTest( 264 | new Set([{ a: 1 }, 2]), 265 | new Set(['2', { a: '1' }]), 266 | 'two loosely equal, strictly inequal Sets', 267 | true, 268 | false 269 | ); 270 | 271 | t.deepEqualTest( 272 | new Set([{ a: 1 }, 2]), 273 | new Set(['2', { a: 2 }]), 274 | 'two inequal Sets', 275 | false, 276 | false 277 | ); 278 | 279 | t.deepEqualTest( 280 | new Set([null, '', 1, 5, 2, false]), 281 | new Set([undefined, 0, '5', true, '2', '-000']), 282 | 'more primitive comparisons', 283 | true, 284 | false 285 | ); 286 | 287 | t.end(); 288 | }); 289 | 290 | test('Set and Map', { skip: !Object.defineProperty || typeof Set !== 'function' || typeof Map !== 'function' }, function (t) { 291 | t.deepEqualTest( 292 | new Set(), 293 | new Map(), 294 | 'Map and Set', 295 | false, 296 | false 297 | ); 298 | 299 | var maplikeSet = new Set(); 300 | Object.defineProperty(maplikeSet, 'constructor', { enumerable: false, value: Map }); 301 | maplikeSet.__proto__ = Map.prototype; // eslint-disable-line no-proto 302 | t.deepEqualTest( 303 | maplikeSet, 304 | new Map(), 305 | 'Map-like Set, and Map', 306 | false, 307 | false 308 | ); 309 | 310 | t.end(); 311 | }); 312 | 313 | test('WeakSets', { skip: typeof WeakSet !== 'function' }, function (t) { 314 | t.deepEqualTest( 315 | new WeakSet([Object, Function]), 316 | new WeakSet([Function, Object]), 317 | 'two equal WeakSets', 318 | true, 319 | true 320 | ); 321 | 322 | t.deepEqualTest( 323 | new WeakSet([Object, Function]), 324 | new WeakSet([Object]), 325 | 'two inequal WeakSets', 326 | true, 327 | true 328 | ); 329 | 330 | t.end(); 331 | }); 332 | 333 | test('not equal', function (t) { 334 | t.deepEqualTest( 335 | { x: 5, y: [6] }, 336 | { x: 5, y: 6 }, 337 | 'two inequal objects are', 338 | false, 339 | false 340 | ); 341 | 342 | t.end(); 343 | }); 344 | 345 | test('nested nulls', function (t) { 346 | t.deepEqualTest( 347 | [null, null, null], 348 | [null, null, null], 349 | 'same-length arrays of nulls', 350 | true, 351 | true, 352 | true 353 | ); 354 | t.end(); 355 | }); 356 | 357 | test('objects with strings vs numbers', function (t) { 358 | t.deepEqualTest( 359 | [{ a: 3 }, { b: 4 }], 360 | [{ a: '3' }, { b: '4' }], 361 | 'objects with equivalent string/number values', 362 | true, 363 | false 364 | ); 365 | t.end(); 366 | }); 367 | 368 | test('non-objects', function (t) { 369 | t.deepEqualTest(3, 3, 'same numbers', true, true, true); 370 | t.deepEqualTest('beep', 'beep', 'same strings', true, true, true); 371 | t.deepEqualTest('3', 3, 'numeric string and number', true, false); 372 | t.deepEqualTest('3', [3], 'numeric string and array containing number', false, false); 373 | t.deepEqualTest(3, [3], 'number and array containing number', false, false); 374 | 375 | t.end(); 376 | }); 377 | 378 | test('infinities', function (t) { 379 | t.deepEqualTest(Infinity, Infinity, '∞ and ∞', true, true, true); 380 | t.deepEqualTest(-Infinity, -Infinity, '-∞ and -∞', true, true, true); 381 | t.deepEqualTest(Infinity, -Infinity, '∞ and -∞', false, false); 382 | 383 | t.end(); 384 | }); 385 | 386 | test('arguments class', function (t) { 387 | function getArgs() { 388 | return arguments; 389 | } 390 | 391 | t.deepEqualTest( 392 | getArgs(1, 2, 3), 393 | getArgs(1, 2, 3), 394 | 'equivalent arguments objects are equal', 395 | true, 396 | true, 397 | true 398 | ); 399 | 400 | t.deepEqualTest( 401 | getArgs(1, 2, 3), 402 | [1, 2, 3], 403 | 'array and arguments with same contents', 404 | false, 405 | false 406 | ); 407 | 408 | var args = getArgs(); 409 | var notArgs = tag({ length: 0 }, 'Arguments'); 410 | t.deepEqualTest( 411 | args, 412 | notArgs, 413 | 'args and similar arraylike object', 414 | false, 415 | false 416 | ); 417 | 418 | t.end(); 419 | }); 420 | 421 | test('Dates', function (t) { 422 | var d0 = new Date(1387585278000); 423 | var d1 = new Date('Fri Dec 20 2013 16:21:18 GMT-0800 (PST)'); 424 | 425 | t.deepEqualTest(d0, d1, 'two Dates with the same timestamp', true, true); 426 | 427 | d1.a = true; 428 | 429 | t.deepEqualTest(d0, d1, 'two Dates with the same timestamp but different own properties', false, false); 430 | 431 | t.test('overriding `getTime`', { skip: !Object.defineProperty }, function (st) { 432 | var a = new Date('2000'); 433 | var b = new Date('2000'); 434 | Object.defineProperty(a, 'getTime', { value: function () { return 5; } }); 435 | st.deepEqualTest(a, b, 'two Dates with the same timestamp but one has overridden `getTime`', true, true); 436 | st.end(); 437 | }); 438 | 439 | t.test('fake Date', { skip: !hasProto }, function (st) { 440 | var a = new Date(2000); 441 | var b = tag(Object.create( 442 | a.__proto__, // eslint-disable-line no-proto 443 | gOPDs(a) 444 | ), 'Date'); 445 | 446 | st.deepEqualTest( 447 | a, 448 | b, 449 | 'Date, and fake Date', 450 | false, 451 | false 452 | ); 453 | 454 | st.end(); 455 | }); 456 | 457 | var a = new Date('2000'); 458 | var b = new Date('2000'); 459 | b.foo = true; 460 | t.deepEqualTest( 461 | a, 462 | b, 463 | 'two identical Dates, one with an extra property', 464 | false, 465 | false 466 | ); 467 | 468 | t.deepEqualTest( 469 | new Date('2000'), 470 | new Date('2001'), 471 | 'two inequal Dates', 472 | false, 473 | false 474 | ); 475 | 476 | t.end(); 477 | }); 478 | 479 | test('buffers', { skip: typeof Buffer !== 'function' }, function (t) { 480 | /* eslint no-buffer-constructor: 1, new-cap: 1 */ 481 | t.deepEqualTest( 482 | safeBuffer('xyz'), 483 | safeBuffer('xyz'), 484 | 'buffers with same contents are equal', 485 | true, 486 | true 487 | ); 488 | 489 | t.deepEqualTest( 490 | safeBuffer('xyz'), 491 | safeBuffer('xyy'), 492 | 'buffers with same length and different contents are inequal', 493 | false, 494 | false 495 | ); 496 | 497 | t.deepEqualTest( 498 | safeBuffer('xyz'), 499 | safeBuffer('xy'), 500 | 'buffers with different length are inequal', 501 | false, 502 | false 503 | ); 504 | 505 | t.deepEqualTest( 506 | safeBuffer('abc'), 507 | safeBuffer('xyz'), 508 | 'buffers with different contents', 509 | false, 510 | false 511 | ); 512 | 513 | var emptyBuffer = safeBuffer(''); 514 | 515 | t.deepEqualTest( 516 | emptyBuffer, 517 | [], 518 | 'empty buffer and empty array', 519 | false, 520 | false 521 | ); 522 | 523 | t.test('bufferlikes', { skip: !Object.defineProperty || !hasTypedArrays }, function (st) { 524 | var fakeBuffer = { 525 | 0: 'a', 526 | length: 1, 527 | __proto__: emptyBuffer.__proto__, // eslint-disable-line no-proto 528 | copy: emptyBuffer.copy, 529 | slice: emptyBuffer.slice 530 | }; 531 | Object.defineProperty(fakeBuffer, '0', { enumerable: false }); 532 | Object.defineProperty(fakeBuffer, 'length', { enumerable: false }); 533 | Object.defineProperty(fakeBuffer, 'copy', { enumerable: false }); 534 | Object.defineProperty(fakeBuffer, 'slice', { enumerable: false }); 535 | 536 | st.deepEqualTest( 537 | safeBuffer('a'), 538 | fakeBuffer, 539 | 'real buffer, and mildly fake buffer', 540 | false, 541 | false 542 | ); 543 | 544 | st.test('bufferlike', { skip: buffersAreTypedArrays ? !hasSymbols || !Symbol.toStringTag : false }, function (s2t) { 545 | var bufferlike = buffersAreTypedArrays ? new Uint8Array() : {}; 546 | Object.defineProperty(bufferlike, 'length', { 547 | enumerable: false, 548 | value: bufferlike.length || 0 549 | }); 550 | Object.defineProperty(bufferlike, 'copy', { 551 | enumerable: false, 552 | value: emptyBuffer.copy 553 | }); 554 | bufferlike.__proto__ = emptyBuffer.__proto__; // eslint-disable-line no-proto 555 | 556 | s2t.deepEqualTest( 557 | emptyBuffer, 558 | bufferlike, 559 | 'empty buffer and empty bufferlike', 560 | true, 561 | true 562 | ); 563 | s2t.end(); 564 | }); 565 | 566 | st.end(); 567 | }); 568 | 569 | t.end(); 570 | }); 571 | 572 | test('Arrays', function (t) { 573 | var a = []; 574 | var b = []; 575 | b.foo = true; 576 | 577 | t.deepEqualTest( 578 | a, 579 | b, 580 | 'two identical arrays, one with an extra property', 581 | false, 582 | false 583 | ); 584 | 585 | t.end(); 586 | }); 587 | 588 | test('booleans', function (t) { 589 | t.deepEqualTest( 590 | true, 591 | true, 592 | 'trues', 593 | true, 594 | true, 595 | false 596 | ); 597 | 598 | t.deepEqualTest( 599 | false, 600 | false, 601 | 'falses', 602 | true, 603 | true, 604 | false 605 | ); 606 | 607 | t.deepEqualTest( 608 | true, 609 | false, 610 | 'true and false', 611 | false, 612 | false 613 | ); 614 | 615 | t.end(); 616 | }); 617 | 618 | test('booleans and arrays', function (t) { 619 | t.deepEqualTest( 620 | true, 621 | [], 622 | 'true and an empty array', 623 | false, 624 | false 625 | ); 626 | t.deepEqualTest( 627 | false, 628 | [], 629 | 'false and an empty array', 630 | false, 631 | false 632 | ); 633 | t.end(); 634 | }); 635 | 636 | test('arrays initiated', function (t) { 637 | var a0 = [ 638 | undefined, 639 | null, 640 | -1, 641 | 0, 642 | 1, 643 | false, 644 | true, 645 | undefined, 646 | '', 647 | 'abc', 648 | null, 649 | undefined 650 | ]; 651 | var a1 = [ 652 | undefined, 653 | null, 654 | -1, 655 | 0, 656 | 1, 657 | false, 658 | true, 659 | undefined, 660 | '', 661 | 'abc', 662 | null, 663 | undefined 664 | ]; 665 | 666 | t.deepEqualTest( 667 | a0, 668 | a1, 669 | 'arrays with equal contents are equal', 670 | true, 671 | true, 672 | true 673 | ); 674 | t.end(); 675 | }); 676 | 677 | test('arrays assigned', function (t) { 678 | var a0 = [ 679 | undefined, 680 | null, 681 | -1, 682 | 0, 683 | 1, 684 | false, 685 | true, 686 | undefined, 687 | '', 688 | 'abc', 689 | null, 690 | undefined 691 | ]; 692 | var a1 = []; 693 | 694 | a1[0] = undefined; 695 | a1[1] = null; 696 | a1[2] = -1; 697 | a1[3] = 0; 698 | a1[4] = 1; 699 | a1[5] = false; 700 | a1[6] = true; 701 | a1[7] = undefined; 702 | a1[8] = ''; 703 | a1[9] = 'abc'; 704 | a1[10] = null; 705 | a1[11] = undefined; 706 | a1.length = 12; 707 | 708 | t.deepEqualTest(a0, a1, 'a literal array and an assigned array', true, true); 709 | t.end(); 710 | }); 711 | 712 | test('arrays push', function (t) { 713 | var a0 = [ 714 | undefined, 715 | null, 716 | -1, 717 | 0, 718 | 1, 719 | false, 720 | true, 721 | undefined, 722 | '', 723 | 'abc', 724 | null, 725 | undefined 726 | ], 727 | a1 = []; 728 | 729 | a1.push(undefined); 730 | a1.push(null); 731 | a1.push(-1); 732 | a1.push(0); 733 | a1.push(1); 734 | a1.push(false); 735 | a1.push(true); 736 | a1.push(undefined); 737 | a1.push(''); 738 | a1.push('abc'); 739 | a1.push(null); 740 | a1.push(undefined); 741 | a1.length = 12; 742 | 743 | t.deepEqualTest(a0, a1, 'a literal array and a pushed array', true, true); 744 | t.end(); 745 | }); 746 | 747 | test('null == undefined', function (t) { 748 | t.deepEqualTest(null, undefined, 'null and undefined', true, false); 749 | t.deepEqualTest([null], [undefined], '[null] and [undefined]', true, false); 750 | 751 | t.end(); 752 | }); 753 | 754 | // node 14 changed `deepEqual` to make two NaNs loosely equal. TODO, semver-major: change deep-equal in the same way. 755 | var isNode14 = isNode && process.env.ASSERT && semver.satisfies(process.version, '>= 14'); 756 | test('NaNs', function (t) { 757 | t.deepEqualTest( 758 | NaN, 759 | NaN, 760 | 'two NaNs', 761 | isNode14, 762 | true 763 | ); 764 | 765 | t.deepEqualTest( 766 | { a: NaN }, 767 | { a: NaN }, 768 | 'two equiv objects with a NaN value', 769 | isNode14, 770 | true 771 | ); 772 | 773 | t.deepEqualTest(NaN, 1, 'NaN and 1', false, false); 774 | 775 | t.end(); 776 | }); 777 | 778 | test('zeroes', function (t) { 779 | t.deepEqualTest(0, -0, '0 and -0', true, false); 780 | 781 | t.deepEqualTest({ a: 0 }, { a: -0 }, 'two objects with a same-keyed 0/-0 value', true, false); 782 | 783 | t.end(); 784 | }); 785 | 786 | test('Object.create', { skip: !Object.create }, function (t) { 787 | var a = { a: 'A' }; 788 | var b = Object.create(a); 789 | b.b = 'B'; 790 | var c = Object.create(a); 791 | c.b = 'C'; 792 | 793 | t.deepEqualTest( 794 | b, 795 | c, 796 | 'two objects with the same [[Prototype]] but a different own property', 797 | false, 798 | false 799 | ); 800 | 801 | t.end(); 802 | }); 803 | 804 | test('Object.create(null)', { skip: !Object.create }, function (t) { 805 | t.deepEqualTest( 806 | Object.create(null), 807 | Object.create(null), 808 | 'two empty null objects', 809 | true, 810 | true, 811 | true 812 | ); 813 | 814 | t.deepEqualTest( 815 | Object.create(null, { a: { value: 'b' } }), 816 | Object.create(null, { a: { value: 'b' } }), 817 | 'two null objects with the same property pair', 818 | true, 819 | true, 820 | true 821 | ); 822 | 823 | t.end(); 824 | }); 825 | 826 | test('regexes vs dates', function (t) { 827 | var d = new Date(1387585278000); 828 | var r = /abc/; 829 | 830 | t.deepEqualTest(d, r, 'Date and RegExp', false, false); 831 | 832 | t.end(); 833 | }); 834 | 835 | test('regexen', function (t) { 836 | t.deepEqualTest(/abc/, /xyz/, 'two different regexes', false, false); 837 | t.deepEqualTest(/abc/, /abc/, 'two abc regexes', true, true, false); 838 | t.deepEqualTest(/xyz/, /xyz/, 'two xyz regexes', true, true, false); 839 | 840 | t.test('fake RegExp', { skip: !hasProto }, function (st) { 841 | var a = /abc/g; 842 | var b = tag(Object.create( 843 | a.__proto__, // eslint-disable-line no-proto 844 | gOPDs(a) 845 | ), 'RegExp'); 846 | 847 | st.deepEqualTest(a, b, 'regex and fake regex', false, false); 848 | 849 | st.end(); 850 | }); 851 | 852 | var a = /abc/gi; 853 | var b = /abc/gi; 854 | b.foo = true; 855 | t.deepEqualTest( 856 | a, 857 | b, 858 | 'two identical regexes, one with an extra property', 859 | false, 860 | false 861 | ); 862 | 863 | var c = /abc/g; 864 | var d = /abc/i; 865 | t.deepEqualTest( 866 | c, 867 | d, 868 | 'two regexes with the same source but different flags', 869 | false, 870 | false 871 | ); 872 | 873 | t.end(); 874 | }); 875 | 876 | test('object literals', function (t) { 877 | t.deepEqualTest( 878 | { prototype: 2 }, 879 | { prototype: '2' }, 880 | 'two loosely equal, strictly inequal prototype properties', 881 | true, 882 | false 883 | ); 884 | 885 | t.end(); 886 | }); 887 | 888 | test('arrays and objects', function (t) { 889 | t.deepEqualTest([], {}, 'empty array and empty object', false, false); 890 | t.deepEqualTest([], { length: 0 }, 'empty array and empty arraylike object', false, false); 891 | t.deepEqualTest([1], { 0: 1 }, 'array and similar object', false, false); 892 | 893 | t.end(); 894 | }); 895 | 896 | test('functions', function (t) { 897 | function f() {} 898 | 899 | t.deepEqualTest(f, f, 'a function and itself', true, true, true); 900 | t.deepEqualTest([f], [f], 'a function and itself in an array', true, true, true); 901 | 902 | t.deepEqualTest(function () {}, function () {}, 'two distinct functions', false, false, true); 903 | t.deepEqualTest([function () {}], [function () {}], 'two distinct functions in an array', false, false, true); 904 | 905 | t.deepEqualTest(f, {}, 'function and object', false, false, true); 906 | t.deepEqualTest([f], [{}], 'function and object in an array', false, false, true); 907 | 908 | t.end(); 909 | }); 910 | 911 | test('Errors', function (t) { 912 | t.deepEqualTest(new Error('xyz'), new Error('xyz'), 'two errors of the same type with the same message', true, true, false); 913 | t.deepEqualTest(new Error('xyz'), new TypeError('xyz'), 'two errors of different types with the same message', false, false); 914 | t.deepEqualTest(new Error('xyz'), new Error('zyx'), 'two errors of the same type with a different message', false, false); 915 | 916 | t.test('errorlike', { skip: !Object.defineProperty }, function (st) { 917 | var err = new Error('foo'); 918 | // TODO: add `__proto__` when brand check is available 919 | var errorlike = tag({ message: err.message, stack: err.stack, name: err.name, constructor: err.constructor }, 'Error'); 920 | Object.defineProperty(errorlike, 'message', { enumerable: false }); 921 | Object.defineProperty(errorlike, 'stack', { enumerable: false }); 922 | Object.defineProperty(errorlike, 'name', { enumerable: false }); 923 | Object.defineProperty(errorlike, 'constructor', { enumerable: false }); 924 | st.notOk(errorlike instanceof Error); 925 | st.ok(err instanceof Error); 926 | st.deepEqualTest( 927 | err, 928 | errorlike, 929 | 'error, and errorlike object', 930 | false, 931 | false 932 | ); 933 | 934 | st.end(); 935 | }); 936 | 937 | t.deepEqualTest( 938 | new Error('a'), 939 | assign(new Error('a'), { code: 10 }), 940 | 'two otherwise equal errors with different own properties', 941 | false, 942 | false 943 | ); 944 | 945 | t.test('fake error', { skip: !process.env.ASSERT || !hasProto }, function (st) { 946 | var a = tag({ 947 | __proto__: null 948 | }, 'Error'); 949 | var b = new RangeError('abc'); 950 | b.__proto__ = null; // eslint-disable-line no-proto 951 | 952 | st.deepEqualTest( 953 | a, 954 | b, 955 | 'null object faking as an Error, RangeError with null proto', 956 | false, 957 | false 958 | ); 959 | st.end(); 960 | }); 961 | 962 | t.end(); 963 | }); 964 | 965 | test('object and null', function (t) { 966 | t.deepEqualTest( 967 | {}, 968 | null, 969 | 'null and an object', 970 | false, 971 | false 972 | ); 973 | 974 | t.end(); 975 | }); 976 | 977 | test('errors', function (t) { 978 | 979 | t.end(); 980 | }); 981 | 982 | test('error = Object', function (t) { 983 | t.deepEqualTest( 984 | new Error('a'), 985 | { message: 'a' }, 986 | false, 987 | false 988 | ); 989 | 990 | t.end(); 991 | }); 992 | 993 | test('[[Prototypes]]', function (t) { 994 | function C() {} 995 | var instance = new C(); 996 | delete instance.constructor; 997 | 998 | t.deepEqualTest({}, instance, 'two identical objects with different [[Prototypes]]', true, false); 999 | 1000 | t.test('Dates with different prototypes', { skip: !hasProto }, function (st) { 1001 | var d1 = new Date(0); 1002 | var d2 = new Date(0); 1003 | 1004 | st.deepEqualTest(d1, d2, 'two dates with the same timestamp', true, true); 1005 | 1006 | var newProto = { 1007 | __proto__: Date.prototype 1008 | }; 1009 | d2.__proto__ = newProto; // eslint-disable-line no-proto 1010 | st.ok(d2 instanceof Date, 'd2 is still a Date instance after tweaking [[Prototype]]'); 1011 | 1012 | st.deepEqualTest(d1, d2, 'two dates with the same timestamp and different [[Prototype]]', true, false); 1013 | 1014 | st.end(); 1015 | }); 1016 | 1017 | t.end(); 1018 | }); 1019 | 1020 | test('toStringTag', { skip: !hasSymbols || !Symbol.toStringTag }, function (t) { 1021 | var o1 = {}; 1022 | t.equal(Object.prototype.toString.call(o1), '[object Object]', 'o1: Symbol.toStringTag works'); 1023 | 1024 | var o2 = {}; 1025 | t.equal(Object.prototype.toString.call(o2), '[object Object]', 'o2: original Symbol.toStringTag works'); 1026 | 1027 | t.deepEqualTest(o1, o2, 'two normal empty objects', true, true); 1028 | 1029 | o2[Symbol.toStringTag] = 'jifasnif'; 1030 | t.equal(Object.prototype.toString.call(o2), '[object jifasnif]', 'o2: modified Symbol.toStringTag works'); 1031 | 1032 | t.deepEqualTest(o1, o2, 'two normal empty objects with different toStringTags', false, false); 1033 | 1034 | t.end(); 1035 | }); 1036 | 1037 | test('boxed primitives', function (t) { 1038 | t.deepEqualTest(Object(false), false, 'boxed and primitive `false`', false, false); 1039 | t.deepEqualTest(Object(true), true, 'boxed and primitive `true`', false, false); 1040 | t.deepEqualTest(Object(3), 3, 'boxed and primitive `3`', false, false); 1041 | t.deepEqualTest(Object(NaN), NaN, 'boxed and primitive `NaN`', false, false); 1042 | t.deepEqualTest(Object(''), '', 'boxed and primitive `""`', false, false); 1043 | t.deepEqualTest(Object('str'), 'str', 'boxed and primitive `"str"`', false, false); 1044 | 1045 | t.test('symbol', { skip: !hasSymbols }, function (st) { 1046 | var s = Symbol(''); 1047 | st.deepEqualTest(Object(s), s, 'boxed and primitive `Symbol()`', false, false); 1048 | st.end(); 1049 | }); 1050 | 1051 | t.test('bigint', { skip: typeof BigInt !== 'function' }, function (st) { 1052 | var hhgtg = BigInt(42); 1053 | st.deepEqualTest(Object(hhgtg), hhgtg, 'boxed and primitive `BigInt(42)`', false, false); 1054 | st.end(); 1055 | }); 1056 | 1057 | t.test('`valueOf` is called for boxed primitives', function (st) { 1058 | var a = Object(5); 1059 | a.valueOf = function () { throw new Error('failed'); }; 1060 | var b = Object(5); 1061 | b.valueOf = function () { throw new Error('failed'); }; 1062 | 1063 | st.deepEqualTest(a, b, 'two boxed numbers with a thrower valueOf', false, false); 1064 | 1065 | st.end(); 1066 | }); 1067 | 1068 | t.end(); 1069 | }); 1070 | 1071 | test('getters', { skip: !Object.defineProperty }, function (t) { 1072 | var a = {}; 1073 | Object.defineProperty(a, 'a', { enumerable: true, get: function () { return 5; } }); 1074 | var b = {}; 1075 | Object.defineProperty(b, 'a', { enumerable: true, get: function () { return 6; } }); 1076 | 1077 | t.deepEqualTest(a, b, 'two objects with the same getter but producing different values', false, false); 1078 | 1079 | t.end(); 1080 | }); 1081 | 1082 | var isBrokenNode = isNode && process.env.ASSERT && semver.satisfies(process.version, '<= 13.3.0'); 1083 | test('fake arrays: extra keys will be tested', { skip: !hasProto || isBrokenNode }, function (t) { 1084 | var a = tag({ 1085 | __proto__: Array.prototype, 1086 | 0: 1, 1087 | 1: 1, 1088 | 2: 'broken', 1089 | length: 2 1090 | }, 'Array'); 1091 | if (Object.defineProperty) { 1092 | Object.defineProperty(a, 'length', { 1093 | enumerable: false 1094 | }); 1095 | } 1096 | 1097 | t.deepEqualTest(a, [1, 1], 'fake and real array with same contents and [[Prototype]]', false, false); 1098 | 1099 | var b = tag(/abc/, 'Array'); 1100 | b.__proto__ = Array.prototype; // eslint-disable-line no-proto 1101 | b.length = 3; 1102 | if (Object.defineProperty) { 1103 | Object.defineProperty(b, 'length', { 1104 | enumerable: false 1105 | }); 1106 | } 1107 | t.deepEqualTest(b, ['a', 'b', 'c'], 'regex faking as array, and array', false, false); 1108 | 1109 | t.end(); 1110 | }); 1111 | 1112 | test('circular references', function (t) { 1113 | var b = {}; 1114 | b.b = b; 1115 | 1116 | var c = {}; 1117 | c.b = c; 1118 | 1119 | t.deepEqualTest( 1120 | b, 1121 | c, 1122 | 'two self-referencing objects', 1123 | true, 1124 | true 1125 | ); 1126 | 1127 | var d = {}; 1128 | d.a = 1; 1129 | d.b = d; 1130 | 1131 | var e = {}; 1132 | e.a = 1; 1133 | e.b = e.a; 1134 | 1135 | t.deepEqualTest( 1136 | d, 1137 | e, 1138 | 'two deeply self-referencing objects', 1139 | false, 1140 | false 1141 | ); 1142 | 1143 | t.end(); 1144 | }); 1145 | 1146 | // io.js v2 is the only version where `console.log(b)` below is catchable 1147 | var isNodeWhereBufferBreaks = isNode && semver.satisfies(process.version, '< 3'); 1148 | var isNode06 = isNode && semver.satisfies(process.version, '<= 0.6'); // segfaults in node 0.6, it seems 1149 | 1150 | test('TypedArrays', { skip: !hasTypedArrays }, function (t) { 1151 | t.test('Buffer faked as Uint8Array', { skip: typeof Buffer !== 'function' || !Object.create || !hasProto || isNode06 }, function (st) { 1152 | var a = safeBuffer('test'); 1153 | var b = tag(Object.create( 1154 | a.__proto__, // eslint-disable-line no-proto 1155 | assign(gOPDs(a), { 1156 | length: { 1157 | enumerable: false, 1158 | value: 4 1159 | } 1160 | }) 1161 | ), 'Uint8Array'); 1162 | 1163 | st.deepEqualTest( 1164 | a, 1165 | b, 1166 | 'Buffer and Uint8Array', 1167 | isNodeWhereBufferBreaks, 1168 | isNodeWhereBufferBreaks 1169 | ); 1170 | 1171 | st.end(); 1172 | }); 1173 | 1174 | forEach(availableTypedArrays, function (name) { 1175 | t.test(name + 's', function (st) { 1176 | var TA = global[name]; 1177 | var isBigInt = name.slice(0, 3) === 'Big'; 1178 | var Z = isBigInt ? BigInt : Number; 1179 | 1180 | st.deepEqualTest( 1181 | new TA([Z(1), Z(2), Z(3)]), 1182 | new TA([Z(1), Z(2), Z(3)]), 1183 | 'two ' + name + 's with the same contents', 1184 | true, 1185 | true 1186 | ); 1187 | 1188 | st.deepEqualTest( 1189 | new TA([Z(1), Z(2), Z(3)]), 1190 | new TA([Z(1), Z(2), Z(4)]), 1191 | 'two ' + name + 's with different contents', 1192 | false, 1193 | false 1194 | ); 1195 | 1196 | st.end(); 1197 | }); 1198 | }); 1199 | 1200 | t.test('one TypedArray faking as another', { skip: !hasProto }, function (st) { 1201 | var a = new Uint8Array(10); 1202 | var b = tag(new Int8Array(10), 'Uint8Array'); 1203 | b.__proto__ = Uint8Array.prototype; // eslint-disable-line no-proto 1204 | 1205 | st.deepEqualTest( 1206 | a, 1207 | b, 1208 | 'Uint8Array, and Int8Array pretending to be a Uint8Array', 1209 | false, 1210 | false 1211 | ); 1212 | 1213 | st.end(); 1214 | }); 1215 | 1216 | t.test('ArrayBuffers', { skip: typeof ArrayBuffer !== 'function' }, function (st) { 1217 | var buffer1 = new ArrayBuffer(8); // initial value of 0's 1218 | var buffer2 = new ArrayBuffer(8); // initial value of 0's 1219 | 1220 | var view1 = new Int8Array(buffer1); 1221 | var view2 = new Int8Array(buffer2); 1222 | 1223 | st.deepEqualTest( 1224 | view1, 1225 | view2, 1226 | 'Int8Arrays of similar ArrayBuffers', 1227 | true, 1228 | true 1229 | ); 1230 | 1231 | st.deepEqualTest( 1232 | buffer1, 1233 | buffer2, 1234 | 'similar ArrayBuffers', 1235 | true, 1236 | true 1237 | ); 1238 | 1239 | for (var i = 0; i < view1.byteLength; i += 1) { 1240 | view1[i] = 9; // change all values to 9's 1241 | } 1242 | 1243 | st.deepEqualTest( 1244 | view1, 1245 | view2, 1246 | 'Int8Arrays of different ArrayBuffers', 1247 | false, 1248 | false 1249 | ); 1250 | 1251 | st.deepEqualTest( 1252 | buffer1, 1253 | buffer2, 1254 | 'different ArrayBuffers', 1255 | false, 1256 | false 1257 | ); 1258 | 1259 | // node < 0.11 has a nonconfigurable own byteLength property 1260 | t.test('lies about byteLength', { skip: !('byteLength' in ArrayBuffer.prototype) }, function (s2t) { 1261 | var empty4 = new ArrayBuffer(4); 1262 | var empty6 = new ArrayBuffer(6); 1263 | Object.defineProperty(empty6, 'byteLength', { value: 4 }); 1264 | 1265 | s2t.deepEqualTest( 1266 | empty4, 1267 | empty6, 1268 | 'different-length ArrayBuffers, one lying', 1269 | false, 1270 | false 1271 | ); 1272 | s2t.end(); 1273 | }); 1274 | 1275 | st.end(); 1276 | }); 1277 | 1278 | t.test('SharedArrayBuffers', { skip: typeof SharedArrayBuffer !== 'function' }, function (st) { 1279 | var buffer1 = new SharedArrayBuffer(8); // initial value of 0's 1280 | var buffer2 = new SharedArrayBuffer(8); // initial value of 0's 1281 | 1282 | var view1 = new Int8Array(buffer1); 1283 | var view2 = new Int8Array(buffer2); 1284 | 1285 | st.deepEqualTest( 1286 | view1, 1287 | view2, 1288 | 'Int8Arrays of similar SharedArrayBuffers', 1289 | true, 1290 | true 1291 | ); 1292 | 1293 | st.deepEqualTest( 1294 | buffer1, 1295 | buffer2, 1296 | 'similar SharedArrayBuffers', 1297 | true, 1298 | true 1299 | ); 1300 | 1301 | for (var i = 0; i < view1.byteLength; i += 1) { 1302 | view1[i] = 9; // change all values to 9's 1303 | } 1304 | 1305 | st.deepEqualTest( 1306 | view1, 1307 | view2, 1308 | 'Int8Arrays of different SharedArrayBuffers', 1309 | false, 1310 | false 1311 | ); 1312 | 1313 | st.deepEqualTest( 1314 | buffer1, 1315 | buffer2, 1316 | 'different SharedArrayBuffers', 1317 | false, 1318 | false 1319 | ); 1320 | 1321 | t.test('lies about byteLength', { skip: !('byteLength' in SharedArrayBuffer.prototype) }, function (s2t) { 1322 | var empty4 = new SharedArrayBuffer(4); 1323 | var empty6 = new SharedArrayBuffer(6); 1324 | Object.defineProperty(empty6, 'byteLength', { value: 4 }); 1325 | 1326 | s2t.deepEqualTest( 1327 | empty4, 1328 | empty6, 1329 | 'different-length SharedArrayBuffers, one lying', 1330 | false, 1331 | false 1332 | ); 1333 | s2t.end(); 1334 | }); 1335 | 1336 | st.end(); 1337 | }); 1338 | 1339 | t.end(); 1340 | }); 1341 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [v2.2.3](https://github.com/inspect-js/node-deep-equal/compare/v2.2.2...v2.2.3) - 2023-11-08 9 | 10 | ### Fixed 11 | 12 | - [readme] remove performance comment and highlight robustness instead [`#76`](https://github.com/inspect-js/node-deep-equal/issues/76) [`#106`](https://github.com/inspect-js/node-deep-equal/issues/106) 13 | 14 | ### Commits 15 | 16 | - Merge tag 'v1.1.2' [`c90525f`](https://github.com/inspect-js/node-deep-equal/commit/c90525fe8380c8f6680d534eff4f189c33fb1601) 17 | - [Tests] port tests from main; only diff should be true/falses [`e02cadb`](https://github.com/inspect-js/node-deep-equal/commit/e02cadb650ef9d75684c015a35d2c59e029d5174) 18 | - [Dev Deps] update `@ljharb/eslint-config`, `auto-changelog`, `aud`, `eslint`, `set-publish-latest`, `tape` [`11bd45b`](https://github.com/inspect-js/node-deep-equal/commit/11bd45b63943466c13a5ae97276796396a8f2619) 19 | - [Tests] update `.github` from default branch [`58885d3`](https://github.com/inspect-js/node-deep-equal/commit/58885d3280fd25909ca5a17c7cec1e54bdd25233) 20 | - [readme] update readme from default branch [`b0bca9a`](https://github.com/inspect-js/node-deep-equal/commit/b0bca9a1158a9596ec51a0404a6a8272b70ee204) 21 | - [Tests] add `nyc` for coverage [`e25bc37`](https://github.com/inspect-js/node-deep-equal/commit/e25bc3716c7ec0390b06bd7b6fac0c9ab0968ab4) 22 | - [readme] update badge URLs, fix line breaking [`1d58c6e`](https://github.com/inspect-js/node-deep-equal/commit/1d58c6ecbab5275e17735d352ac7fa4a1af40aca) 23 | - [Tests] use `Buffer.from` when available [`f0d4a42`](https://github.com/inspect-js/node-deep-equal/commit/f0d4a42fb87854e17d78cb2d6e9ec0156ea3d2f3) 24 | - [Tests] use `has-proto` [`0263fb9`](https://github.com/inspect-js/node-deep-equal/commit/0263fb9170a4e6a400c3b628cfba902ebaf59df5) 25 | - [Deps] update `is-arguments`, `is-date-object`, `is-regex`, `object-is`, `regexp.prototype.flags` [`80c15ca`](https://github.com/inspect-js/node-deep-equal/commit/80c15cae82164c888de8635287c3b44ab84b3fd4) 26 | - [meta] add missing `engines.node` [`e1d08a8`](https://github.com/inspect-js/node-deep-equal/commit/e1d08a818fdb69e4f39b7aa23dc88092d3339c43) 27 | - [meta] use `npmignore` to autogenerate an npmignore file [`e0770e5`](https://github.com/inspect-js/node-deep-equal/commit/e0770e594ec683ded32fd1b14e876f087fc04f4a) 28 | - [Deps] update `is-date-object`, `is-regex`, `object-is`, `regexp.prototype.flags` [`e4fb8c6`](https://github.com/inspect-js/node-deep-equal/commit/e4fb8c6459aa13d3a110b45e5612c31890a5d94e) 29 | - [Tests] handle ported test failures in iojs v2 [`3798ff4`](https://github.com/inspect-js/node-deep-equal/commit/3798ff490286ee9ba70cf50c339914be355eea18) 30 | - [Deps] update `call-bind`, `regexp.prototype.flags`, `which-typed-array` [`540e3a1`](https://github.com/inspect-js/node-deep-equal/commit/540e3a119dcd94b30253ad380fde69d5531cf0ac) 31 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape` [`0f8ca75`](https://github.com/inspect-js/node-deep-equal/commit/0f8ca7575e44c66fdf1dc2b6ad4e69e1b549369f) 32 | - [Tests] handle some additional test differences in node <= 0.10 [`197a220`](https://github.com/inspect-js/node-deep-equal/commit/197a2203f0a95828c62ff2b3c980ddf16736913c) 33 | - [Dev Deps] update `object.getownpropertydescriptors`, `tape` [`21851a6`](https://github.com/inspect-js/node-deep-equal/commit/21851a62cda0b832800de3070d9fbb7216e43284) 34 | - [Dev Deps] update `semver`, `tape` [`dd440b2`](https://github.com/inspect-js/node-deep-equal/commit/dd440b2267ac8fa496b907369d3e0b73f9439e87) 35 | - [meta] add missing `engines.node` [`e158993`](https://github.com/inspect-js/node-deep-equal/commit/e158993fcf913aca8a1ffdc037abfeeb3a5cb4e5) 36 | - [meta] update `.gitignore` from default branch [`6ee186b`](https://github.com/inspect-js/node-deep-equal/commit/6ee186bd39199a1c05421e200b1e8e31a83cf363) 37 | - [Deps] update `get-intrinsic` [`6da4b86`](https://github.com/inspect-js/node-deep-equal/commit/6da4b86e4d7ad3c01736006ca129b8e3c3f2c82c) 38 | - [Dev Deps] update `tape` [`6ada1ab`](https://github.com/inspect-js/node-deep-equal/commit/6ada1ab7f9a176b10f0117a8e10b785965c0e830) 39 | - [Dev Deps] update `tape` [`270d34b`](https://github.com/inspect-js/node-deep-equal/commit/270d34b48401ee40792bf18d06614044246776dd) 40 | - [meta] fix URLs [`a269c18`](https://github.com/inspect-js/node-deep-equal/commit/a269c183bccb78dfdd2c88a149fe5373f13af4c0) 41 | - [readme] update default branch name [`030a63f`](https://github.com/inspect-js/node-deep-equal/commit/030a63f40afa3d468ffb10437cbf5acaa677fea2) 42 | - [Deps] update `which-typed-array` [`2f0c327`](https://github.com/inspect-js/node-deep-equal/commit/2f0c327eaaed7b50649c367f88944b6dd7e9f18c) 43 | - [Tests] only use `Buffer.from` when it has a length of > 1 [`f7e5776`](https://github.com/inspect-js/node-deep-equal/commit/f7e577622d943da78c2c9cd1e070eb786cf7a68b) 44 | 45 | ## [v2.2.2](https://github.com/inspect-js/node-deep-equal/compare/v2.2.1...v2.2.2) - 2023-07-10 46 | 47 | ### Commits 48 | 49 | - [Fix] avoid an infinite loop in node 0.8 with Typed Arrays [`f247282`](https://github.com/inspect-js/node-deep-equal/commit/f247282e66060087c51221f77b9170fa0e2e461b) 50 | - [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`fa25583`](https://github.com/inspect-js/node-deep-equal/commit/fa255839c1afed228c41ca76177a8c239ec9305a) 51 | - [Deps] update `get-intrinsic` [`3638470`](https://github.com/inspect-js/node-deep-equal/commit/3638470e71ed6185e06a0f0694e77cbf4c2b791c) 52 | 53 | ## [v2.2.1](https://github.com/inspect-js/node-deep-equal/compare/v2.2.0...v2.2.1) - 2023-04-27 54 | 55 | ### Commits 56 | 57 | - [Tests] add passing tests covering object key ordering [`51c9ff6`](https://github.com/inspect-js/node-deep-equal/commit/51c9ff6b4c5d4371e0f444ce1160e416bf88e21f) 58 | - [Refactor] use `array-buffer-byte-length` [`f47822c`](https://github.com/inspect-js/node-deep-equal/commit/f47822cf0c188caa71dfbb107b081324fcb6b99d) 59 | - [Deps] update `is-array-buffer`, `regexp.prototype.flags` [`160d851`](https://github.com/inspect-js/node-deep-equal/commit/160d8513335d63256f9826835b35d1a462c76771) 60 | - [Deps] update `es-get-iterator`, `get-intrinsic` [`2e08e95`](https://github.com/inspect-js/node-deep-equal/commit/2e08e956a43c839246d2280cfaaa3f3200937bbd) 61 | - [Dev Deps] update `object.getownpropertydescriptors` [`63e9ab7`](https://github.com/inspect-js/node-deep-equal/commit/63e9ab7450212bf7e393c1bf725293389cb4626a) 62 | - [Dev Deps] update `tape` [`c8db964`](https://github.com/inspect-js/node-deep-equal/commit/c8db964f605834388b0df20c5fce49cfbaa541bc) 63 | 64 | ## [v2.2.0](https://github.com/inspect-js/node-deep-equal/compare/v2.1.0...v2.2.0) - 2023-01-05 65 | 66 | ### Commits 67 | 68 | - [New] add support for `SharedArrayBuffer` [`0ef51c7`](https://github.com/inspect-js/node-deep-equal/commit/0ef51c79b7dcd6ae5890b2dce4304be7c8ebe314) 69 | - [Refactor] use `is-array-buffer` package [`0360ee1`](https://github.com/inspect-js/node-deep-equal/commit/0360ee1f1bb6e5804c15a9a4aa75ff84120a33e1) 70 | - [Fix] `whichTypedArray` can return false in both cases [`df3e3c4`](https://github.com/inspect-js/node-deep-equal/commit/df3e3c4e30552b7a7892b62dc45fccd31eac9bfe) 71 | - [Dev Deps] update `aud`, `object.getownpropertydescriptors` [`6d62ea4`](https://github.com/inspect-js/node-deep-equal/commit/6d62ea4f2b82d4f861fd3e0c2d67916939b1edbc) 72 | - [Dev Deps] update `@ljharb/eslint-config` [`15aab59`](https://github.com/inspect-js/node-deep-equal/commit/15aab59d647628e05b77d1897036d73884f7a107) 73 | - [Deps] update `which-typed-array` [`8dfce27`](https://github.com/inspect-js/node-deep-equal/commit/8dfce27f333721c697b90569b26e4bded0d61d88) 74 | - [eslint] remove `.eslintignore` [`af46773`](https://github.com/inspect-js/node-deep-equal/commit/af46773b281dc67d7743280505a22248f0f0748d) 75 | 76 | ## [v2.1.0](https://github.com/inspect-js/node-deep-equal/compare/v2.0.5...v2.1.0) - 2022-11-02 77 | 78 | ### Fixed 79 | 80 | - [New] add support for `ArrayBuffer` [`#94`](https://github.com/inspect-js/node-deep-equal/issues/94) 81 | 82 | ### Commits 83 | 84 | - [actions] reuse common workflows [`12de287`](https://github.com/inspect-js/node-deep-equal/commit/12de2873def84c621421b1e3d4a96babf2ceb30a) 85 | - [actions] use `node/install` instead of `node/run`; use `codecov` action [`ec248b9`](https://github.com/inspect-js/node-deep-equal/commit/ec248b96f4f91eb4c5971dfec74d6d91f04b39cd) 86 | - [Tests] run assert tests on a dynamic matrix [`695aebd`](https://github.com/inspect-js/node-deep-equal/commit/695aebd50945621984bfa7e60b5c99f79dbacf1a) 87 | - [readme] add badges [`492e159`](https://github.com/inspect-js/node-deep-equal/commit/492e1591585233184151b5526cf5413e61a2aa89) 88 | - [Test] ArrayBuffers in node < 0.12 have a nonconfigurable own `byteLength` property [`40f4b87`](https://github.com/inspect-js/node-deep-equal/commit/40f4b8719658f6262399b24791d4ccb5960ca8ea) 89 | - [meta] use `npmignore` to autogenerate an npmignore file [`2627269`](https://github.com/inspect-js/node-deep-equal/commit/26272693147d68ec3ae2216b1f3ac5d30b79b3da) 90 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape` [`7a05bb7`](https://github.com/inspect-js/node-deep-equal/commit/7a05bb7482817616243fc89956abf48710d77fea) 91 | - [Deps] update `call-bind`, `es-get-iterator`, `get-intrinsic`, `is-arguments`, `is-regex`, `regexp.prototype.flags`, `side-channel`, `which-boxed-primitive`, `which-typed-array` [`c0844e6`](https://github.com/inspect-js/node-deep-equal/commit/c0844e629ba3dc5193fd41a75ebcedaba976c1af) 92 | - [actions] update codecov uploader [`b1b0552`](https://github.com/inspect-js/node-deep-equal/commit/b1b0552fe3dc23029a2717f84642e53548902e68) 93 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `auto-changelog`, `has-symbols`, `object.getownpropertydescriptors`, `tape` [`9a1ccf5`](https://github.com/inspect-js/node-deep-equal/commit/9a1ccf5285317962fe37baa211c2b20081be71ef) 94 | - [meta] do not publish github action workflow files [`2d63384`](https://github.com/inspect-js/node-deep-equal/commit/2d63384d6676b593c2a74b45747ac81cea3da76e) 95 | - [actions] update rebase action to use reusable workflow [`69d21f5`](https://github.com/inspect-js/node-deep-equal/commit/69d21f55af0bcff1c41447a6ac396ae556fda226) 96 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbols`, `object.getownpropertydescriptors`, `tape` [`297aae8`](https://github.com/inspect-js/node-deep-equal/commit/297aae88f619b1e058418be32e37fc29770b4f21) 97 | - [Tests] add tests for regexes with the same source but different flags [`29c8a0d`](https://github.com/inspect-js/node-deep-equal/commit/29c8a0da09567b3bbe6614c1e235d5a87d7bdaf2) 98 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`9e64ec9`](https://github.com/inspect-js/node-deep-equal/commit/9e64ec93a8c5cbe87315d30dd62a8fe6dcf842b4) 99 | - [Deps] update `is-arguments`, `is-date-object`, `is-regex`, `which-typed-array` [`edfb752`](https://github.com/inspect-js/node-deep-equal/commit/edfb752810699790c06bb424174f38b449a4b8fb) 100 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `auto-changelog`, `tape` [`7b5f7a3`](https://github.com/inspect-js/node-deep-equal/commit/7b5f7a348b2bb78ca1c00003d0dd3444d5a372a6) 101 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `has-typed-arrays`, `tape` [`e328a23`](https://github.com/inspect-js/node-deep-equal/commit/e328a237ba9c262d8c2d178a65d5e1f744cbbd6b) 102 | - [Deps] update `get-intrinsic`, `regexp.prototype.flags`, `which-typed-array` [`29123a7`](https://github.com/inspect-js/node-deep-equal/commit/29123a71857c27cce497ac991fa9be0e5921adce) 103 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud` [`b7039ef`](https://github.com/inspect-js/node-deep-equal/commit/b7039effc1b751cb579095f9738ee019d8458a41) 104 | - [Dev Deps] update `aud`, `tape` [`9d0b2e0`](https://github.com/inspect-js/node-deep-equal/commit/9d0b2e07df24dfd1d4d9bf32cdca07e6e1377f23) 105 | - [actions] update workflows [`a5f5a7e`](https://github.com/inspect-js/node-deep-equal/commit/a5f5a7ed570e35cefad08ed32652cb8647d0166c) 106 | - [Deps] update `get-intrinsic`, `object.assign` [`02025e2`](https://github.com/inspect-js/node-deep-equal/commit/02025e21dfbce6a4d52421c4892ba743dd7a7540) 107 | - [Test] node < 4 lacks `ArrayBuffer.prototype.fill` [`bb65b07`](https://github.com/inspect-js/node-deep-equal/commit/bb65b07d39eeea03ca066a92892a06a607641ed7) 108 | - [Deps] update `is-date-object`, `is-regex` [`a463ed2`](https://github.com/inspect-js/node-deep-equal/commit/a463ed26ba7ca4b818db4929e4e946ddc0590bce) 109 | - [Deps] update `get-intrinsic`, `object-is` [`2a33cce`](https://github.com/inspect-js/node-deep-equal/commit/2a33cced17827df191676ecdd9b9bc4f0d814aa6) 110 | - [actions] update workflows [`d905278`](https://github.com/inspect-js/node-deep-equal/commit/d90527855a35bcaeef70d3e21370580d7d182c8d) 111 | - [meta] use `prepublishOnly` script for npm 7+ [`7b66184`](https://github.com/inspect-js/node-deep-equal/commit/7b661846aedb0ad5768f1118e93c662d214c85f8) 112 | - [Dev Deps] update `object.getownpropertydescriptors` [`d970dbc`](https://github.com/inspect-js/node-deep-equal/commit/d970dbcf4a95c58d5bbd6ea507455bbfa1e7ec02) 113 | 114 | ## [v2.0.5](https://github.com/inspect-js/node-deep-equal/compare/v2.0.4...v2.0.5) - 2020-12-01 115 | 116 | ### Commits 117 | 118 | - [Tests] migrate tests to Github Actions [`4051a18`](https://github.com/inspect-js/node-deep-equal/commit/4051a1811612fd1b107743a092402361f597f89a) 119 | - [meta] add Automatic Rebase and Require Allow Edits workflows [`6682b15`](https://github.com/inspect-js/node-deep-equal/commit/6682b15417630d6c57c854d088dfcd6023b3e185) 120 | - [Deps] use `call-bind` and `get-intrinsic` instead of `es-abstract`; update `es-get-iterator`, `object-is`, `object.assign` [`a1d6d93`](https://github.com/inspect-js/node-deep-equal/commit/a1d6d931ebc80db8a6dba1bd453165356458f9e1) 121 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `object.getownpropertydescriptors` [`b142f4b`](https://github.com/inspect-js/node-deep-equal/commit/b142f4b9458c320b944dc06f57b9339530cf404e) 122 | 123 | ## [v2.0.4](https://github.com/inspect-js/node-deep-equal/compare/v2.0.3...v2.0.4) - 2020-10-01 124 | 125 | ### Fixed 126 | 127 | - [meta] fix incorrect `./package.json` exports entry [`#89`](https://github.com/inspect-js/node-deep-equal/issues/89) 128 | 129 | ### Commits 130 | 131 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `auto-changelog` [`d6bfee3`](https://github.com/inspect-js/node-deep-equal/commit/d6bfee329e2a430a12e6a4aba7006c5d7c36020e) 132 | - [Tests] account for node 14+ making two NaNs loosely deep equal [`9367954`](https://github.com/inspect-js/node-deep-equal/commit/93679546d97dbd92d615b0f758d733ea1fb4eb4b) 133 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`86a159b`](https://github.com/inspect-js/node-deep-equal/commit/86a159b72c3e3620285498113251220d3c5d05f0) 134 | - [Deps] update `es-abstract`, `object-is`, `object.assign` [`e87979d`](https://github.com/inspect-js/node-deep-equal/commit/e87979d311faa537622a6c9faee6e91cf9a08bcd) 135 | - [Deps] update `es-abstract`, `is-regex` [`d0cacca`](https://github.com/inspect-js/node-deep-equal/commit/d0cacca140b963d8abbe10f6bf640f22ef11f7b0) 136 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape` [`375a9e1`](https://github.com/inspect-js/node-deep-equal/commit/375a9e1e4911b3210e328365432c8cf946d0a7e2) 137 | - [Dev Deps] update `eslint`, `auto-changelog` [`e562d4f`](https://github.com/inspect-js/node-deep-equal/commit/e562d4fadebf09b1fca02d6f43e1c933c6ef8242) 138 | - [Deps] update `side-channel` [`f092342`](https://github.com/inspect-js/node-deep-equal/commit/f092342373d4a33b3f679042f357fd800185caad) 139 | 140 | ## [v2.0.3](https://github.com/inspect-js/node-deep-equal/compare/v2.0.2...v2.0.3) - 2020-04-23 141 | 142 | ### Commits 143 | 144 | - [Deps] update `object-is`, `which-typed-array` [`c232374`](https://github.com/inspect-js/node-deep-equal/commit/c2323741001f7cb2414f4fa26301f1b9705e6b46) 145 | - [Dev Deps] update `auto-changelog`; add `aud` [`c80a91d`](https://github.com/inspect-js/node-deep-equal/commit/c80a91d8b9815300fc9e24f08094cac8942d9da7) 146 | - [Dev Deps] update `auto-changelog` [`295d195`](https://github.com/inspect-js/node-deep-equal/commit/295d19529365a87ed663eecf26f19effe5b06f3c) 147 | - [Dev Deps] update `aud` [`1134cc2`](https://github.com/inspect-js/node-deep-equal/commit/1134cc26fd112e3679a6973f4d418c4495e3358d) 148 | - [Deps] Fix classification of `object.assign` [`32695dd`](https://github.com/inspect-js/node-deep-equal/commit/32695dd88c3eb86c87e162830e0e1c55447a4b9f) 149 | 150 | ## [v2.0.2](https://github.com/inspect-js/node-deep-equal/compare/v2.0.1...v2.0.2) - 2020-04-01 151 | 152 | ### Commits 153 | 154 | - [Fix] properly pass `strict` option through internals [`4e2919d`](https://github.com/inspect-js/node-deep-equal/commit/4e2919d7c403413a9cf094b2f3be095653670e97) 155 | - [Tests] add more coverage [`a3d8677`](https://github.com/inspect-js/node-deep-equal/commit/a3d86774fa39e1a00b3371a32fbe42c7b38743ff) 156 | - [Tests] add coverage reporting [`3174e33`](https://github.com/inspect-js/node-deep-equal/commit/3174e33f952a4bdd57c43e3b40dea705d3d61e68) 157 | - [Refactor] add strict pragma; remove unused try/catch [`c1d173e`](https://github.com/inspect-js/node-deep-equal/commit/c1d173ebadfcc4a2574f28b17727239dcd2737be) 158 | - [Fix] the `prototype` property is not special on non-functions [`1c3cc25`](https://github.com/inspect-js/node-deep-equal/commit/1c3cc2526766e52cc32b9c1859b7073d5dbb70aa) 159 | - [Deps] update `es-abstract`, `es-get-iterator`, `is-date-object`, `is-regex`, `object-is`, `regexp.prototype.flags`, `side-channel` [`7787bdc`](https://github.com/inspect-js/node-deep-equal/commit/7787bdc1268620ef12d17777fce3682abc4e364e) 160 | - [Deps] update `es-abstract`, `es-get-iterator`, `which-collection` [`87624cf`](https://github.com/inspect-js/node-deep-equal/commit/87624cf96f2ca00bf5200aa860c4574dba96f4aa) 161 | - [Fix] robustly distinguish Typed Arrays [`7ccb2b0`](https://github.com/inspect-js/node-deep-equal/commit/7ccb2b0f88136516cd58cad74d9c0a20daad824c) 162 | - [Dev Deps] update `@ljharb/eslint-config`, `tape` [`c1814a1`](https://github.com/inspect-js/node-deep-equal/commit/c1814a1256e373ac6e7953b354f9f56ff5b7fe89) 163 | - [Dev Deps] update `@ljharb/eslint-config`, `object.getownpropertydescriptors`, `tape` [`7a0d819`](https://github.com/inspect-js/node-deep-equal/commit/7a0d819e5b3807eab873d7961eb34e30ff615943) 164 | - [Dev Deps] update `auto-changelog`, `tape` [`f248756`](https://github.com/inspect-js/node-deep-equal/commit/f2487567b092d90005a7d09b084f7ffb9ba71257) 165 | - [Tests] fix `tag` helper, from bb50ea2e6d7906cd58683fdc7d327660e71612f4 [`469f008`](https://github.com/inspect-js/node-deep-equal/commit/469f0089d16d8678ee4c5f57016d40f072b3f7be) 166 | - [Dev Deps] update `eslint`, `tape` [`6537dce`](https://github.com/inspect-js/node-deep-equal/commit/6537dcef16c792546c3a40ea5b53ab43861cf719) 167 | - [Fix] make `isBuffer` check slightly more robust [`c21e14d`](https://github.com/inspect-js/node-deep-equal/commit/c21e14d7afe7d53391fa95fd8c59f85affc02ac6) 168 | - [meta] disable greenkeeper updates for semver [`724f051`](https://github.com/inspect-js/node-deep-equal/commit/724f051213e159d5a021d0649e6a2cafd4c13458) 169 | - [Deps] update `es-abstract` [`942ad86`](https://github.com/inspect-js/node-deep-equal/commit/942ad8699442dd83207bb04ae079997b3433ca60) 170 | - [Deps] update `es-abstract` [`8724052`](https://github.com/inspect-js/node-deep-equal/commit/8724052e10d2e897626af6f46e0bce9d35523b04) 171 | 172 | ## [v2.0.1](https://github.com/inspect-js/node-deep-equal/compare/v2.0.0...v2.0.1) - 2019-12-08 173 | 174 | ### Fixed 175 | 176 | - [Fix] `Map` and `Set` comparison: keys are loosely compared also [`#75`](https://github.com/inspect-js/node-deep-equal/issues/75) 177 | 178 | ### Commits 179 | 180 | - [Fix] check extra properties on regexps [`1eac46b`](https://github.com/inspect-js/node-deep-equal/commit/1eac46b69c7b499cecb7e3b555b6e260de2043fd) 181 | - [Tests] update test skipping logic [`8adf08d`](https://github.com/inspect-js/node-deep-equal/commit/8adf08dcb91146590f2c57b614de6a853054f297) 182 | 183 | ## [v2.0.0](https://github.com/inspect-js/node-deep-equal/compare/v1.1.2...v2.0.0) - 2019-12-03 184 | 185 | ### Fixed 186 | 187 | - [Fix] handle circular references [`#19`](https://github.com/inspect-js/node-deep-equal/issues/19) 188 | - [Breaking] compare `Map`, `Set`, `WeakMap`, `WeakSet` matching node assert [`#54`](https://github.com/inspect-js/node-deep-equal/issues/54) [`#46`](https://github.com/inspect-js/node-deep-equal/issues/46) 189 | - [Breaking] compare `Map`, `Set`, `WeakMap`, `WeakSet` matching node assert [`#54`](https://github.com/inspect-js/node-deep-equal/issues/54) [`#46`](https://github.com/inspect-js/node-deep-equal/issues/46) 190 | - [Breaking] comparing arrays and objects should always fail, per node‘s assert.deepEqual [`#12`](https://github.com/inspect-js/node-deep-equal/issues/12) 191 | 192 | ### Commits 193 | 194 | - [Tests] add passing tests from node core [`91a6472`](https://github.com/inspect-js/node-deep-equal/commit/91a6472719331eca1b13472db798e7f3188af9f7) 195 | - [Tests] convert remaining tests to use the custom assertion [`2bb7269`](https://github.com/inspect-js/node-deep-equal/commit/2bb7269013574a9a4e84ec5e34a04258f3ecd94a) 196 | - [Tests] add tests for getters, fake arrays, overriding getTime on Dates [`1b66d90`](https://github.com/inspect-js/node-deep-equal/commit/1b66d90232a5a576d0334f0c109f8c79da487c9f) 197 | - [Breaking] non-Date objects with different [[Prototypes]] are not equal [`5f2f2e5`](https://github.com/inspect-js/node-deep-equal/commit/5f2f2e55a3cfea251ca502a7846489a9133b4347) 198 | - [Breaking] boxed primitives are not silently unboxed [`e207bc3`](https://github.com/inspect-js/node-deep-equal/commit/e207bc352f338a5c57b2ef2ce59d78b821fb2b58) 199 | - [Tests] run tests with assert, as well [`ccaf3ea`](https://github.com/inspect-js/node-deep-equal/commit/ccaf3eabb081d255f9fafcf2cc2631eafaa9b2a7) 200 | - [Breaking] boxed primitives are unwrapped for comparisons [`a159a3a`](https://github.com/inspect-js/node-deep-equal/commit/a159a3a0660a2da9a8ff6392aba4b2de81bc8391) 201 | - [Refactor] use `side-channel` for memoizing circular refs [`983780a`](https://github.com/inspect-js/node-deep-equal/commit/983780aec338b8d909c3f6a5b1e0f4d7fe1d78b5) 202 | - [Tests] Failing tests for Map equality [`4856185`](https://github.com/inspect-js/node-deep-equal/commit/4856185d989914e2f440fe3fd3bac4d977365fe2) 203 | - [Tests] add `toStringTag` helper [`bb50ea2`](https://github.com/inspect-js/node-deep-equal/commit/bb50ea2e6d7906cd58683fdc7d327660e71612f4) 204 | - [Fix] robustly unbox boxed primitives, using `unbox-primitive` [`c455998`](https://github.com/inspect-js/node-deep-equal/commit/c45599893f02f349604a7b39b39f45036ea2e499) 205 | - [Breaking] two objects with different `Symbol.toStringTag`s are not equal [`45431b6`](https://github.com/inspect-js/node-deep-equal/commit/45431b67b5e7e9cb91d5ff8706dc55348d59184e) 206 | - [Tests] add more Error tests [`c0ae38c`](https://github.com/inspect-js/node-deep-equal/commit/c0ae38c43872621da83aba608cd62b951de7c4c6) 207 | - [Breaking] ensure `Error` objects compare properly [`ffb2522`](https://github.com/inspect-js/node-deep-equal/commit/ffb2522eb94afe46a8ccc23faebdcee23ea6f170) 208 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`737031e`](https://github.com/inspect-js/node-deep-equal/commit/737031e9ac09812ec7181040e857d8b73b573970) 209 | - [readme] update URLs, readme [`9d300da`](https://github.com/inspect-js/node-deep-equal/commit/9d300da78ce21dcca7259bb557765cfac0db3e16) 210 | - [Tests] use `Buffer.from` when available [`43fa5da`](https://github.com/inspect-js/node-deep-equal/commit/43fa5dafe17b1287f56c2566c487a9c05946fe4f) 211 | - [Breaking] add `exports` to `package.json` [`ecd15ae`](https://github.com/inspect-js/node-deep-equal/commit/ecd15aedeeddc8f386ed8b54296648ee4a73af9b) 212 | - [Tests] require ASSERT tests to pass [`7ac77cf`](https://github.com/inspect-js/node-deep-equal/commit/7ac77cf21081b30eeadb5ac5201b30ad0d4dcbe4) 213 | - [Robustness] use `callBound` from `es-abstract` [`4dc3477`](https://github.com/inspect-js/node-deep-equal/commit/4dc347792be1f7131b3095ba98590a599cce7e20) 214 | - [patch] [[Prototype]]s are only compared in strict mode [`43b1eef`](https://github.com/inspect-js/node-deep-equal/commit/43b1eef2eb7bc3045fb160bf5d755bce44cbfd52) 215 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `has-symbols` [`89228df`](https://github.com/inspect-js/node-deep-equal/commit/89228df447b174008e163f1c83c8f0f559e30fa0) 216 | - [Tests] up to `node` `v12.9` [`595c81a`](https://github.com/inspect-js/node-deep-equal/commit/595c81a2e2c1baab216b2dac640ed020f49033bf) 217 | - [Fix] pass options when comparing Collection keys/values [`9859584`](https://github.com/inspect-js/node-deep-equal/commit/9859584ae2f4f46ec602e18bac9610c71ff00e2f) 218 | - [Breaking] `false` and `[]` are no longer equal, even non-strictly [`5c3accc`](https://github.com/inspect-js/node-deep-equal/commit/5c3acccf541ba0b77342c2a441b32a43acebc73e) 219 | - [Tests] only use `Buffer.from` when it has a length of > 1 [`3645129`](https://github.com/inspect-js/node-deep-equal/commit/3645129d7692c5195ae4b94ba83d2fe84d9538d7) 220 | - [Breaking] remove `lib/is-arguments` and `lib/keys` entrypoints [`783d47e`](https://github.com/inspect-js/node-deep-equal/commit/783d47e3092b7a62aaecbf6836b18a0dfca96662) 221 | - [Dev Deps] update `eslint` [`7cc1dd9`](https://github.com/inspect-js/node-deep-equal/commit/7cc1dd986fc30946ca06ba6496ef856cfb911cf3) 222 | - Merge tag 'v1.1.1' [`f9d3c6d`](https://github.com/inspect-js/node-deep-equal/commit/f9d3c6d1e4a895c448ba7d8766f8616d0e235c9a) 223 | - Merge tag 'v1.1.0' [`0aeca99`](https://github.com/inspect-js/node-deep-equal/commit/0aeca9988dba6fe3318f46c47c933e6926175278) 224 | 225 | ## [v1.1.2](https://github.com/inspect-js/node-deep-equal/compare/v1.1.1...v1.1.2) - 2023-11-08 226 | 227 | ### Commits 228 | 229 | - [Tests] port tests from main; only diff should be true/falses [`e02cadb`](https://github.com/inspect-js/node-deep-equal/commit/e02cadb650ef9d75684c015a35d2c59e029d5174) 230 | - [Dev Deps] update `@ljharb/eslint-config`, `auto-changelog`, `aud`, `eslint`, `set-publish-latest`, `tape` [`11bd45b`](https://github.com/inspect-js/node-deep-equal/commit/11bd45b63943466c13a5ae97276796396a8f2619) 231 | - [Tests] update `.github` from default branch [`58885d3`](https://github.com/inspect-js/node-deep-equal/commit/58885d3280fd25909ca5a17c7cec1e54bdd25233) 232 | - [readme] update readme from default branch [`b0bca9a`](https://github.com/inspect-js/node-deep-equal/commit/b0bca9a1158a9596ec51a0404a6a8272b70ee204) 233 | - [Tests] add `nyc` for coverage [`e25bc37`](https://github.com/inspect-js/node-deep-equal/commit/e25bc3716c7ec0390b06bd7b6fac0c9ab0968ab4) 234 | - [Tests] use `Buffer.from` when available [`f0d4a42`](https://github.com/inspect-js/node-deep-equal/commit/f0d4a42fb87854e17d78cb2d6e9ec0156ea3d2f3) 235 | - [Deps] update `is-arguments`, `is-date-object`, `is-regex`, `object-is`, `regexp.prototype.flags` [`80c15ca`](https://github.com/inspect-js/node-deep-equal/commit/80c15cae82164c888de8635287c3b44ab84b3fd4) 236 | - [meta] use `npmignore` to autogenerate an npmignore file [`e0770e5`](https://github.com/inspect-js/node-deep-equal/commit/e0770e594ec683ded32fd1b14e876f087fc04f4a) 237 | - [Deps] update `is-date-object`, `is-regex`, `object-is`, `regexp.prototype.flags` [`e4fb8c6`](https://github.com/inspect-js/node-deep-equal/commit/e4fb8c6459aa13d3a110b45e5612c31890a5d94e) 238 | - [Tests] handle ported test failures in iojs v2 [`3798ff4`](https://github.com/inspect-js/node-deep-equal/commit/3798ff490286ee9ba70cf50c339914be355eea18) 239 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape` [`0f8ca75`](https://github.com/inspect-js/node-deep-equal/commit/0f8ca7575e44c66fdf1dc2b6ad4e69e1b549369f) 240 | - [Tests] handle some additional test differences in node <= 0.10 [`197a220`](https://github.com/inspect-js/node-deep-equal/commit/197a2203f0a95828c62ff2b3c980ddf16736913c) 241 | - [meta] add missing `engines.node` [`e158993`](https://github.com/inspect-js/node-deep-equal/commit/e158993fcf913aca8a1ffdc037abfeeb3a5cb4e5) 242 | - [meta] update `.gitignore` from default branch [`6ee186b`](https://github.com/inspect-js/node-deep-equal/commit/6ee186bd39199a1c05421e200b1e8e31a83cf363) 243 | - [Dev Deps] update `tape` [`270d34b`](https://github.com/inspect-js/node-deep-equal/commit/270d34b48401ee40792bf18d06614044246776dd) 244 | - [meta] fix URLs [`a269c18`](https://github.com/inspect-js/node-deep-equal/commit/a269c183bccb78dfdd2c88a149fe5373f13af4c0) 245 | - [Tests] only use `Buffer.from` when it has a length of > 1 [`f7e5776`](https://github.com/inspect-js/node-deep-equal/commit/f7e577622d943da78c2c9cd1e070eb786cf7a68b) 246 | 247 | ## [v1.1.1](https://github.com/inspect-js/node-deep-equal/compare/v1.1.0...v1.1.1) - 2019-11-12 248 | 249 | ### Commits 250 | 251 | - [Tests] use shared travis-ci configs [`678cb2a`](https://github.com/inspect-js/node-deep-equal/commit/678cb2a34ef920eab563af69bdf402b9273c3e2c) 252 | - [meta] add `auto-changelog` [`569bcce`](https://github.com/inspect-js/node-deep-equal/commit/569bcce030784f7506367055122c54c6cac00ebc) 253 | - [Dev Deps] update `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest` [`9dedd40`](https://github.com/inspect-js/node-deep-equal/commit/9dedd409cb74c538153287db546a14f2fa583e6f) 254 | - [Tests] add `npx aud` in `posttest` [`0b76639`](https://github.com/inspect-js/node-deep-equal/commit/0b766394504f74d002ad85e7b8244ce89bb27130) 255 | - [meta] add `funding` field [`3e519e3`](https://github.com/inspect-js/node-deep-equal/commit/3e519e36998ea82120cfe9a509dc0090a87d7063) 256 | 257 | ## [v1.1.0](https://github.com/inspect-js/node-deep-equal/compare/v1.0.1...v1.1.0) - 2019-08-27 258 | 259 | ### Commits 260 | 261 | - [Tests] up to `node` `v12.7`, `v11.15`, `v10.16`, `v9.11`, `v8.16`, `v7.10`, `v6.17`, `4.9`; use `nvm install-latest-npm` [`ba11166`](https://github.com/inspect-js/node-deep-equal/commit/ba111664928f3a9279528dd05330b974950003b4) 262 | - [Tests] make a `tape` helper, to easily compare loose/strict, and (a,b)/(b,a) arg order [`0c25e94`](https://github.com/inspect-js/node-deep-equal/commit/0c25e9438b2d4a96e75c3c2e6fbb353ae450ed1f) 263 | - [Tests] add `npm run lint` [`8590816`](https://github.com/inspect-js/node-deep-equal/commit/8590816be6bc57a07fbc160985f5f04f11c7fa97) 264 | - test: Fails simple array tests on IE < 9 #10 [`bc37498`](https://github.com/inspect-js/node-deep-equal/commit/bc374988ee763a881ef39d8f6949838ec4df4e64) 265 | - [Tests] clean up/flesh out test cases [`3fffed9`](https://github.com/inspect-js/node-deep-equal/commit/3fffed9a7e095bbf922561fa0b18681422861af8) 266 | - [Fix] (array,arguments) now behaves the same as (arguments,array) [`a9528ff`](https://github.com/inspect-js/node-deep-equal/commit/a9528ff71561c303e722eb5ae0a3b9b2ecae4a3b) 267 | - [Refactor] move Date and RegExp tests into `objEquiv` [`5b3bf31`](https://github.com/inspect-js/node-deep-equal/commit/5b3bf315b603f00bab49e78c05c075cdc0dfd506) 268 | - [Fix] properly compare RegExp objects [`b8c179c`](https://github.com/inspect-js/node-deep-equal/commit/b8c179c5aa91c8a2f71f053e2d9e2d477780250e) 269 | - [Refactor] Use `object-keys` and `is-arguments` instead of a homegrown shim. [`3b503fb`](https://github.com/inspect-js/node-deep-equal/commit/3b503fb262c431df72a6c91cbb384be557315645) 270 | - [Fix] use `object-is` to support `NaN` and `-0` properly [`28fde4a`](https://github.com/inspect-js/node-deep-equal/commit/28fde4a411073e3131d3637248f8c25aac9329f2) 271 | - [meta] fix license text so GitHub can detect it [`7000403`](https://github.com/inspect-js/node-deep-equal/commit/700040347119ce46b3e917e800d87628af1384f9) 272 | - [Tests] add array/object tests [`558eecf`](https://github.com/inspect-js/node-deep-equal/commit/558eecf9daa815468f0bc4c9799041507b7ffa15) 273 | - [Fix] ensure Buffer + non-Buffer comparison order does not matter [`de4e75c`](https://github.com/inspect-js/node-deep-equal/commit/de4e75ce7f0621cdc09ae8cbdc82de9e4c17578e) 274 | - [Refactor] `objEquiv`: bail early if typeofs are different [`410e2d6`](https://github.com/inspect-js/node-deep-equal/commit/410e2d63730763e7e92c9b45b916f97058ab31f7) 275 | - [Tests] add tests for `Object.create(null)` [`ed266e8`](https://github.com/inspect-js/node-deep-equal/commit/ed266e8571d1efdbb4ece0a01f849cbc57461076) 276 | - [Refactor] there is no need to do further compareation when two types are not equal [`6a5efc1`](https://github.com/inspect-js/node-deep-equal/commit/6a5efc130e96398de55cf517969746c52735f34b) 277 | - Only apps should have lockfiles [`f60442f`](https://github.com/inspect-js/node-deep-equal/commit/f60442fa6fd10004366d80481ada7df668bd6adb) 278 | - [Tests] clean up redundant test [`cbbef21`](https://github.com/inspect-js/node-deep-equal/commit/cbbef21045e3b2e1ee30f6d0a83381d489df296e) 279 | - [Fix] use `is-date-object` to properly detect cross-realm Dates [`0c5b21a`](https://github.com/inspect-js/node-deep-equal/commit/0c5b21ad245d1427caefe20b2bace752cbe5e493) 280 | - [meta] Add copyright statements [`56a7746`](https://github.com/inspect-js/node-deep-equal/commit/56a774674f55bb3e0627aaec4dda90e4a06df7d6) 281 | - [Dev Deps] update `tape` [`3e9c1b9`](https://github.com/inspect-js/node-deep-equal/commit/3e9c1b903703e32bbed45fddcae815eb25822fd4) 282 | 283 | ## [v1.0.1](https://github.com/inspect-js/node-deep-equal/compare/v1.0.0...v1.0.1) - 2015-08-29 284 | 285 | ### Fixed 286 | 287 | - Null should == undefined [`#23`](https://github.com/inspect-js/node-deep-equal/issues/23) 288 | 289 | ### Commits 290 | 291 | - Update travis.yml to modern node [`5055802`](https://github.com/inspect-js/node-deep-equal/commit/5055802274a85a3e1493fa1b7378499554c6a4dc) 292 | 293 | ## [v1.0.0](https://github.com/inspect-js/node-deep-equal/compare/v0.2.2...v1.0.0) - 2015-02-07 294 | 295 | ## [v0.2.2](https://github.com/inspect-js/node-deep-equal/compare/v0.2.1...v0.2.2) - 2015-02-07 296 | 297 | ### Commits 298 | 299 | - latest tape [`1d18617`](https://github.com/inspect-js/node-deep-equal/commit/1d18617608316a034c8ee6727838c9b82614f0f9) 300 | - add type check to support browsers [`3acb0d7`](https://github.com/inspect-js/node-deep-equal/commit/3acb0d7fb8915fb7f1ca97701b5761793738bad3) 301 | 302 | ## [v0.2.1](https://github.com/inspect-js/node-deep-equal/compare/v0.2.0...v0.2.1) - 2014-01-29 303 | 304 | ### Commits 305 | 306 | - license file [`b3431d4`](https://github.com/inspect-js/node-deep-equal/commit/b3431d48e0f7c406a08d0e077f2dd9580d4561ae) 307 | 308 | ## [v0.2.0](https://github.com/inspect-js/node-deep-equal/compare/v0.1.2...v0.2.0) - 2014-01-29 309 | 310 | ### Commits 311 | 312 | - buffer check without Buffer [`5271f39`](https://github.com/inspect-js/node-deep-equal/commit/5271f39f3ce61fecb71fa6ca28cb4a8a8b963bbd) 313 | - failing test for buffer comparison [`cc8990b`](https://github.com/inspect-js/node-deep-equal/commit/cc8990b9d84a2267d84253e21c9f7db238e961e9) 314 | 315 | ## [v0.1.2](https://github.com/inspect-js/node-deep-equal/compare/v0.1.1...v0.1.2) - 2013-12-20 316 | 317 | ### Commits 318 | 319 | - test the arguments shim and properly factor out the arguments handling [`cf88b9c`](https://github.com/inspect-js/node-deep-equal/commit/cf88b9c2e87d6050ba1a46a82be216d0244ee428) 320 | - more coverage for the keys shim [`7a41f0e`](https://github.com/inspect-js/node-deep-equal/commit/7a41f0ec813616b0e1272c2bf463028a84d51c99) 321 | - test coverage for the non-object case [`abd3358`](https://github.com/inspect-js/node-deep-equal/commit/abd33586af0006e8492bbcdb1eb27a306359b03c) 322 | - fix the argument comparisons to properly call equal() [`0114a10`](https://github.com/inspect-js/node-deep-equal/commit/0114a10398e386ab0e073966e8525cd2ce125de4) 323 | - more code coverage for date comparisons [`41ac40e`](https://github.com/inspect-js/node-deep-equal/commit/41ac40e844b10833a75a39ea92e73bcdb1ae3cd9) 324 | - use the latest version of tape [`f8341cb`](https://github.com/inspect-js/node-deep-equal/commit/f8341cbff475ee7ee1ec651662cb5bd621c75838) 325 | - use https: for the badges [`514b332`](https://github.com/inspect-js/node-deep-equal/commit/514b332e9c2390c89c5beac8cf866c2f9a4afa9e) 326 | - 100% coverage [`e55aac7`](https://github.com/inspect-js/node-deep-equal/commit/e55aac78a6e013d6f5a10febc7009476a8f10ca5) 327 | 328 | ## [v0.1.1](https://github.com/inspect-js/node-deep-equal/compare/v0.1.0...v0.1.1) - 2013-12-20 329 | 330 | ### Commits 331 | 332 | - Fixed arguments support for IE8- [`174d41a`](https://github.com/inspect-js/node-deep-equal/commit/174d41a5559820458648d237ebedfe78e44f7430) 333 | 334 | ## [v0.1.0](https://github.com/inspect-js/node-deep-equal/compare/v0.0.0...v0.1.0) - 2013-10-14 335 | 336 | ### Commits 337 | 338 | - upgrade the markdown [`30e1f8f`](https://github.com/inspect-js/node-deep-equal/commit/30e1f8fe5b1fb7d5d68b156bf69bb04a7bb807a3) 339 | - opts.strict instead of a boolean arg [`58cbdb2`](https://github.com/inspect-js/node-deep-equal/commit/58cbdb2a97e623a68310833218af5ada6c97c2ce) 340 | - using testling-ci [`064af17`](https://github.com/inspect-js/node-deep-equal/commit/064af170f895fc67ec4bbf654e7de27721cf40c0) 341 | - Add optional strict parameter [`f3413b1`](https://github.com/inspect-js/node-deep-equal/commit/f3413b1d95e261f735939fbcaee65e598fe92852) 342 | - strict equality test [`281189b`](https://github.com/inspect-js/node-deep-equal/commit/281189b6962c9c57105474d01a8127da3318f555) 343 | - document opts.strict [`69fae5a`](https://github.com/inspect-js/node-deep-equal/commit/69fae5ab4b9278e28d09864c62dcfe9b4f00c1d8) 344 | - using tape [`4384db8`](https://github.com/inspect-js/node-deep-equal/commit/4384db8a9cc7af1cf79e1976d1b36e66934b2b4c) 345 | - using travis [`e508692`](https://github.com/inspect-js/node-deep-equal/commit/e5086928e1edf120d227d5e7f5e6ac4d755248a1) 346 | - deepEquals comparing nulls seems to break in ie6-8 [`b2cfeb9`](https://github.com/inspect-js/node-deep-equal/commit/b2cfeb95da6982f8bc2e676231820a3a47385db3) 347 | - performance note in the readme [`da9bfc9`](https://github.com/inspect-js/node-deep-equal/commit/da9bfc9aadfb9045bbf8157e9403de7184b404fd) 348 | - more firefoxes [`3d60ec5`](https://github.com/inspect-js/node-deep-equal/commit/3d60ec58d6fe269c13c5be04b749f01972aa5b1c) 349 | 350 | ## v0.0.0 - 2012-02-10 351 | 352 | ### Commits 353 | 354 | - implementation with an example [`2dd56f9`](https://github.com/inspect-js/node-deep-equal/commit/2dd56f9e6d42e841c74289c2e2d489047d077622) 355 | - readme [`4a44f99`](https://github.com/inspect-js/node-deep-equal/commit/4a44f99bea3277e32d9842d9d49ac21f316ac74d) 356 | - and a test [`357ccd3`](https://github.com/inspect-js/node-deep-equal/commit/357ccd37d23ba7814c8fe284d36d6e86a39b7526) 357 | - actually just MIT [`3d348c8`](https://github.com/inspect-js/node-deep-equal/commit/3d348c88fc92ce1d69a3fedbb2aa8cb6ea1480f7) 358 | --------------------------------------------------------------------------------