[Pkg-javascript-commits] [node-deep-eql] 01/06: New upstream version 3.0.1
Sruthi Chandran
srud-guest at moszumanska.debian.org
Wed Oct 25 18:14:06 UTC 2017
This is an automated email from the git hooks/post-receive script.
srud-guest pushed a commit to branch master
in repository node-deep-eql.
commit e71693284a9c30e3b56f2bfa2fd99cc89e4e66bb
Author: Sruthi Chandran <srud at disroot.org>
Date: Wed Oct 25 21:58:54 2017 +0530
New upstream version 3.0.1
---
.gitignore | 21 ++
.travis.yml | 27 ++
README.md | 11 +-
bench/.eslintrc | 18 ++
bench/index.js | 125 ++++++++
component.json | 19 ++
index.js | 136 +++++----
karma.conf.js | 96 +++++++
package.json | 10 +-
test/.eslintrc | 19 ++
test/index.js | 538 +++++++++++++++++++++++++++++++++++
test/new-ecmascript-types.js | 660 +++++++++++++++++++++++++++++++++++++++++++
12 files changed, 1616 insertions(+), 64 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a7fb08c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+build
+components
+
+node_modules
+npm-debug.log
+
+coverage/
+
+deep-eql.js
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a13f091
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,27 @@
+sudo: false
+language: node_js
+addons:
+ sauce_connect: true
+cache:
+ directories:
+ - node_modules
+node_js:
+ - 4 # to be removed 2018-04-01
+ - 6 # to be removed 2019-04-01
+ - lts/* # safety net; don't remove
+ - node # safety net; don't remove
+before_install:
+- npm i -g npm
+script:
+- npm t
+after_success:
+- npm run upload-coverage
+- travis-after-all && npm run semantic-release
+env:
+ global:
+ - SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
+ - LOGS_DIR=/tmp/chai-build/logs
+ - secure: fOmukdZc9lwl/tfer01TAoPCcpafNbr1ZvUnjKmiP/r1cC2RWpF1JlYITtioLlvadzCTwi88SBzQLIi1/qCSao7vSsup5oC05brgUOR9uD7VE9IfIpyV5bthT/sX3IKNeIFKlow4H1f8RLlweqtor5AyHlG5cXOJybQMyAAfkWo=
+ - secure: XC9Uz7J9Yflf7NuSFAkWq2yb3UksnKe83l3npLhYWN/uNk74ukh1z3o+OcJ4ujNsMx+/AcKjlJPmu8ghrjxCo6ocWBNz2+TR2UOZjukS96BOAOvOTgJqEv6nGW7HNVhpDYZEPbhM2d67UnoAX3aZFDZdug2EHD2GFJYYD7LZpnM=
+ - secure: LsutIKfCxltpyJSW0h+L8EDQYC+Rh7w48ZBbbJq+jS19ejQTPfojvvw5NcucpNh0P+x27PikRGKNOAAUuPqZSA9l9OFPoPVxgUI8r8E7Kl6D0pi6hCz5bX+dG0VaI078GpaflsyOVjiiW844sR7IXpP1w3GP2fI1DBXOBUbsWNQ=
+ - secure: EqyK5QPQZ7eHu7RbRjj/1MJywBbsn7EiJXHm9jjDnsuLkMEhrBdV5bYsIEDIROIsOSl8OBw208rrIUNO73aSvfQgkCJMN3Mtjfqh/Yn1We90k0Gy9KZMsiheD/3qjsOQxQPludlU58EDlEItTVLb2Clfs7Qfv7M5p3xl54OCaN8=
diff --git a/README.md b/README.md
index 15d5e52..96ecef1 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,11 @@
alt="devDependencies:?"
src="https://img.shields.io/david/chaijs/deep-eql.svg?style=flat-square"
/>
+ </a><a href="https://github.com/nodejs/LTS#lts-schedule1">
+ <img
+ alt="Supported Node Version: 4+"
+ src="https://img.shields.io/badge/node-4+-43853d.svg?style=flat-square"
+ />
</a>
<br/>
<a href="https://saucelabs.com/u/chaijs-deep-eql">
@@ -79,6 +84,7 @@ As an example, take the following:
{ a: 1 } !== { a: 1 } // These are two different objects, they hold different references and so are not strictly equal - even though they hold the same values inside
{ a: 1 } != { a: 1 } // They have the same type, meaning loose equality performs the same check as strict equality - they are still not equal.
+var deepEql = require("deep-eql");
deepEql({ a: 1 }, { a: 1 }) === true // deepEql can determine that they share the same keys and those keys share the same values, therefore they are deeply equal!
```
@@ -96,7 +102,7 @@ The primary export of `deep-eql` is function that can be given two objects to co
### Rules
-- Strict equality for non-traversable nodes according to [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
+- Strict equality for non-traversable nodes according to [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is):
- `eql(NaN, NaN).should.be.true;`
- `eql(-0, +0).should.be.false;`
- All own and inherited enumerable properties are considered:
@@ -105,3 +111,6 @@ The primary export of `deep-eql` is function that can be given two objects to co
- Arguments are not Arrays:
- `eql([], arguments).should.be.false;`
- `eql([], Array.prototype.slice.call(arguments)).should.be.true;`
+- Error objects are compared by reference (see https://github.com/chaijs/chai/issues/608):
+ - `eql(new Error('msg'), new Error('msg')).should.be.false;`
+ - `var err = new Error('msg'); eql(err, err).should.be.true;`
diff --git a/bench/.eslintrc b/bench/.eslintrc
new file mode 100644
index 0000000..df40e10
--- /dev/null
+++ b/bench/.eslintrc
@@ -0,0 +1,18 @@
+{
+ "extends": [ "strict/test" ],
+ "env": {
+ "node": true,
+ "browser": true,
+ "es6": true
+ },
+ "rules": {
+ "no-eval": 0,
+ "no-new-wrappers": 0,
+ "no-array-constructor": 0,
+ "no-new-object": 0,
+ "no-empty-function": 0,
+ "no-undefined": 0,
+ "no-console": 0,
+ "id-length": 0
+ }
+}
diff --git a/bench/index.js b/bench/index.js
new file mode 100644
index 0000000..ac23ea7
--- /dev/null
+++ b/bench/index.js
@@ -0,0 +1,125 @@
+'use strict';
+var deepEql = require('../');
+var lodashDeepEql = require('lodash.isequal');
+var assertDeepeql = require('assert').deepEql;
+var kewlrDeepeql = require('kewlr').chai;
+var inspect = require('util').inspect;
+var Benchmark = require('benchmark');
+var benches = [];
+var mapObjRefA = {};
+var mapObjRefB = {};
+function getArguments() {
+ return arguments;
+}
+var fixtures = {
+ 'equal references ': [ mapObjRefA, mapObjRefA ],
+ 'string literal ': [ 'abc', 'abc' ],
+ 'array literal ': [ [ 1, 2, 3 ], [ 1, 2, 3 ] ],
+ 'boolean literal ': [ true, true ],
+ 'object literal ': [ { a: 1 }, { a: 1 } ],
+ 'object from null ': [ Object.create(null), Object.create(null) ],
+ 'regex literal ': [ /^abc$/, /^abc$/ ],
+ 'number literal ': [ 1, 1 ],
+ 'null ': [ null, null ],
+ 'undefined ': [ undefined, undefined ],
+ 'buffer ': [ new Buffer('hello world'), new Buffer('hello world') ],
+ 'date ': [ new Date(123), new Date(123) ],
+ 'map ': [ new Map().set('a', 1), new Map().set('a', 1) ],
+ 'map (complex) ': [
+ new Map().set(mapObjRefA, new Map().set(mapObjRefB, 1)),
+ new Map().set(mapObjRefA, new Map().set(mapObjRefB, 1)),
+ ],
+ 'regex constructor ': [ new RegExp('abc'), new RegExp('abc') ],
+ 'set ': [ new Set().add(1), new Set().add(1) ],
+ 'string constructor ': [ new String(), new String() ],
+ 'arguments ': [ getArguments(1, 2, 3), getArguments(1, 2, 3) ],
+
+ /* Failing benchmarks */
+ 'string literal (differing) ': [ 'abc', 'cba', false ],
+ 'array literal (differing) ': [ [ 1, 2, 3 ], [ 4, 5, 6 ], false ],
+ 'boolean literal (differing)': [ true, false, false ],
+ 'object literal (differing) ': [ { a: 1 }, { a: 2 }, false ],
+ 'regex literal (differing) ': [ /^abc$/, /^def$/, false ],
+ 'number literal (differing) ': [ 1, 2, false ],
+ 'null & undefined ': [ null, undefined, false ],
+ 'buffer (differing) ': [ new Buffer(123), new Buffer(456), false ],
+ 'date (differing) ': [ new Date(123), new Date(456), false ],
+ 'error ': [ new Error(''), new Error(''), false ],
+ 'map (differing) ': [ new Map().set('a', 1), new Map().set('a', 2), false ],
+ 'regex ctor (differing) ': [ new RegExp('abc'), new RegExp('def'), false ],
+ 'set (differing) ': [ new Set().add(1), new Set().add(2), false ],
+ 'string ctor (differing) ': [ new String('abc'), new String('def'), false ],
+ 'weakmap ': [ new WeakMap(), new WeakMap(), false ],
+ 'weakset ': [ new WeakSet(), new WeakSet(), false ],
+ 'arguments (differing) ': [ getArguments(1, 2, 3), getArguments(4, 5, 6), false ],
+ 'function ': [ function () {}, function () {}, false ],
+ 'promise ': [ Promise.resolve(), Promise.resolve(), false ],
+};
+try {
+ fixtures['arrow function (differing) '] = [
+ eval('() => {}'),
+ eval('() => {}'),
+ false,
+ ];
+} catch (error) {
+ console.error('cannot benchmark arrow functions');
+}
+try {
+ fixtures['generator func (differing) '] = [
+ eval('(function* () {})'),
+ eval('(function* () {})'),
+ false,
+ ];
+} catch (error) {
+ console.error('cannot benchmark generator functions');
+}
+
+function prepareBenchMark(test, name, assert) {
+ assert = assert || deepEql;
+ var leftHand = test[0];
+ var rightHand = test[1];
+ var expectedResult = 2 in test ? test[2] : true;
+ var invocationString = 'deepEql(' + inspect(leftHand) + ', ' + inspect(rightHand) + ') === ' + expectedResult;
+ benches.push(new Benchmark(name, {
+ fn: function () {
+ if (assert(leftHand, rightHand) !== expectedResult) {
+ throw new Error('failing test: ' + invocationString);
+ }
+ },
+ onCycle: function (event) {
+ process.stdout.clearLine();
+ process.stdout.cursorTo(0);
+ process.stdout.write(event.target.toString());
+ },
+ }));
+}
+
+var filter = process.argv.slice(2).filter(function (arg) {
+ return arg[0] !== '-';
+})[0] || '';
+var lodash = process.argv.indexOf('--lodash') !== -1;
+var nodeassert = process.argv.indexOf('--nodeassert') !== -1;
+var kewlr = process.argv.indexOf('--kewlr') !== -1;
+Object.keys(fixtures).filter(function (key) {
+ return key.indexOf(filter) !== -1;
+}).forEach(function (testName) {
+ prepareBenchMark(fixtures[testName], testName + ' ');
+ if (lodash) {
+ prepareBenchMark(fixtures[testName], testName + ' (lodash)', lodashDeepEql);
+ }
+ if (nodeassert) {
+ prepareBenchMark(fixtures[testName], testName + ' (node)', assertDeepeql);
+ }
+ if (kewlr) {
+ prepareBenchMark(fixtures[testName], testName + ' (kewlr)', kewlrDeepeql);
+ }
+});
+Benchmark.invoke(benches, {
+ name: 'run',
+ onCycle: function onCycle() {
+ console.log('');
+ },
+ onComplete: function onComplete() {
+ console.log('~Fin~');
+ },
+});
diff --git a/component.json b/component.json
new file mode 100644
index 0000000..f97f1a1
--- /dev/null
+++ b/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "deep-eql"
+ , "repo": "chaijs/deep-eql"
+ , "version": "0.1.3"
+ , "description": "Improved deep equality testing for Node.js and the browser."
+ , "license": "MIT"
+ , "keywords": [
+ ]
+ , "main": "lib/eql.js"
+ , "scripts": [
+ "lib/eql.js"
+ ]
+ , "dependencies": {
+ "chaijs/type-detect": "0.1.1"
+ }
+ , "development": {
+ "chaijs/simple-assert": "1.0.0"
+ }
+}
diff --git a/index.js b/index.js
index 552f0d2..b1b5295 100644
--- a/index.js
+++ b/index.js
@@ -1,55 +1,31 @@
'use strict';
-/* globals Symbol: true, Uint8Array: true, WeakMap: true */
+/* globals Symbol: false, Uint8Array: false, WeakMap: false */
/*!
* deep-eql
* Copyright(c) 2013 Jake Luer <jake at alogicalparadox.com>
* MIT Licensed
*/
-/*!
- * Module dependencies
- */
-
var type = require('type-detect');
function FakeMap() {
- this.clear();
+ this._key = 'chai/deep-eql__' + Math.random() + Date.now();
}
+
FakeMap.prototype = {
- clear: function clearMap() {
- this.keys = [];
- this.values = [];
- return this;
- },
- set: function setMap(key, value) {
- var index = this.keys.indexOf(key);
- if (index >= 0) {
- this.values[index] = value;
- } else {
- this.keys.push(key);
- this.values.push(value);
- }
- return this;
- },
get: function getMap(key) {
- return this.values[this.keys.indexOf(key)];
+ return key[this._key];
},
- delete: function deleteMap(key) {
- var index = this.keys.indexOf(key);
- if (index >= 0) {
- this.values = this.values.slice(0, index).concat(this.values.slice(index + 1));
- this.keys = this.keys.slice(0, index).concat(this.keys.slice(index + 1));
+ set: function setMap(key, value) {
+ if (Object.isExtensible(key)) {
+ Object.defineProperty(key, this._key, {
+ value: value,
+ configurable: true,
+ });
}
- return this;
},
};
-var MemoizeMap = null;
-if (typeof WeakMap === 'function') {
- MemoizeMap = WeakMap;
-} else {
- MemoizeMap = FakeMap;
-}
-
+var MemoizeMap = typeof WeakMap === 'function' ? WeakMap : FakeMap;
/*!
* Check to see if the MemoizeMap has recorded a result of the two operands
*
@@ -59,7 +35,8 @@ if (typeof WeakMap === 'function') {
* @returns {Boolean|null} result
*/
function memoizeCompare(leftHandOperand, rightHandOperand, memoizeMap) {
- if (!memoizeMap) {
+ // Technically, WeakMap keys can *only* be objects, not primitives.
+ if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
return null;
}
var leftHandMap = memoizeMap.get(leftHandOperand);
@@ -81,7 +58,8 @@ function memoizeCompare(leftHandOperand, rightHandOperand, memoizeMap) {
* @param {Boolean} result
*/
function memoizeSet(leftHandOperand, rightHandOperand, memoizeMap, result) {
- if (!memoizeMap || typeof leftHandOperand !== 'object' || typeof rightHandOperand !== 'object') {
+ // Technically, WeakMap keys can *only* be objects, not primitives.
+ if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
return;
}
var leftHandMap = memoizeMap.get(leftHandOperand);
@@ -114,6 +92,27 @@ module.exports.MemoizeMap = MemoizeMap;
* @return {Boolean} equal match
*/
function deepEqual(leftHandOperand, rightHandOperand, options) {
+ // If we have a comparator, we can't assume anything; so bail to its check first.
+ if (options && options.comparator) {
+ return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);
+ }
+
+ var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);
+ if (simpleResult !== null) {
+ return simpleResult;
+ }
+
+ // Deeper comparisons are pushed through to a larger function
+ return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);
+}
+
+/**
+ * Many comparisons can be canceled out early via simple equality or primitive checks.
+ * @param {Mixed} leftHandOperand
+ * @param {Mixed} rightHandOperand
+ * @return {Boolean|null} equal match
+ */
+function simpleEqual(leftHandOperand, rightHandOperand) {
// Equal references (except for Numbers) can be returned early
if (leftHandOperand === rightHandOperand) {
// Handle +-0 cases
@@ -128,17 +127,13 @@ function deepEqual(leftHandOperand, rightHandOperand, options) {
return true;
}
- // Primitives/null/undefined can be checked for referential equality; returning early
- if (
- typeof leftHandOperand !== 'object' ||
- leftHandOperand === null ||
- leftHandOperand === undefined // eslint-disable-line no-undefined
- ) {
- return leftHandOperand === rightHandOperand;
+ // Anything that is not an 'object', i.e. symbols, functions, booleans, numbers,
+ // strings, and undefined, can be compared by reference.
+ if (isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {
+ // Easy out b/c it would have passed the first equality check
+ return false;
}
-
- // Deeper comparisons are pushed through to a larger function
- return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);
+ return null;
}
/*!
@@ -158,32 +153,44 @@ function extensiveDeepEqual(leftHandOperand, rightHandOperand, options) {
options.memoize = options.memoize === false ? false : options.memoize || new MemoizeMap();
var comparator = options && options.comparator;
- var memoizeResult = memoizeCompare(leftHandOperand, rightHandOperand, options.memoize);
- if (memoizeResult !== null) {
- return memoizeResult;
+ // Check if a memoized result exists.
+ var memoizeResultLeft = memoizeCompare(leftHandOperand, rightHandOperand, options.memoize);
+ if (memoizeResultLeft !== null) {
+ return memoizeResultLeft;
+ }
+ var memoizeResultRight = memoizeCompare(rightHandOperand, leftHandOperand, options.memoize);
+ if (memoizeResultRight !== null) {
+ return memoizeResultRight;
}
- var comparatorResult = comparator && comparator(leftHandOperand, rightHandOperand);
- if (comparatorResult === false || comparatorResult === true) {
- memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult);
- memoizeSet(rightHandOperand, leftHandOperand, options.memoize, comparatorResult);
- return comparatorResult;
+ // If a comparator is present, use it.
+ if (comparator) {
+ var comparatorResult = comparator(leftHandOperand, rightHandOperand);
+ // Comparators may return null, in which case we want to go back to default behavior.
+ if (comparatorResult === false || comparatorResult === true) {
+ memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult);
+ return comparatorResult;
+ }
+ // To allow comparators to override *any* behavior, we ran them first. Since it didn't decide
+ // what to do, we need to make sure to return the basic tests first before we move on.
+ var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);
+ if (simpleResult !== null) {
+ // Don't memoize this, it takes longer to set/retrieve than to just compare.
+ return simpleResult;
+ }
}
var leftHandType = type(leftHandOperand);
if (leftHandType !== type(rightHandOperand)) {
memoizeSet(leftHandOperand, rightHandOperand, options.memoize, false);
- memoizeSet(rightHandOperand, leftHandOperand, options.memoize, false);
return false;
}
// Temporarily set the operands in the memoize object to prevent blowing the stack
memoizeSet(leftHandOperand, rightHandOperand, options.memoize, true);
- memoizeSet(rightHandOperand, leftHandOperand, options.memoize, true);
var result = extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options);
memoizeSet(leftHandOperand, rightHandOperand, options.memoize, result);
- memoizeSet(rightHandOperand, leftHandOperand, options.memoize, result);
return result;
}
@@ -433,3 +440,16 @@ function objectEqual(leftHandOperand, rightHandOperand, options) {
return false;
}
+
+/*!
+ * Returns true if the argument is a primitive.
+ *
+ * This intentionally returns true for all objects that can be compared by reference,
+ * including functions and symbols.
+ *
+ * @param {Mixed} value
+ * @return {Boolean} result
+ */
+function isPrimitive(value) {
+ return value === null || typeof value !== 'object';
+}
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 0000000..e7a9848
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,96 @@
+'use strict';
+var packageJson = require('./package.json');
+var defaultTimeout = 120000;
+var browserifyIstanbul = require('browserify-istanbul');
+module.exports = function configureKarma(config) {
+ var localBrowsers = [
+ 'PhantomJS',
+ ];
+ var sauceLabsBrowsers = {
+ SauceChromeLatest: {
+ base: 'SauceLabs',
+ browserName: 'Chrome',
+ },
+ SauceFirefoxLatest: {
+ base: 'SauceLabs',
+ browserName: 'Firefox',
+ },
+ SauceSafariLatest: {
+ base: 'SauceLabs',
+ browserName: 'Safari',
+ platform: 'OS X 10.11',
+ },
+ SauceInternetExplorerLatest: {
+ base: 'SauceLabs',
+ browserName: 'Internet Explorer',
+ },
+ SauceInternetExplorerOldestSupported: {
+ base: 'SauceLabs',
+ browserName: 'Internet Explorer',
+ version: 9,
+ },
+ SauceEdgeLatest: {
+ base: 'SauceLabs',
+ browserName: 'MicrosoftEdge',
+ },
+ SauceAndroidLatest: {
+ base: 'SauceLabs',
+ browserName: 'Android',
+ },
+ };
+ config.set({
+ basePath: '',
+ browsers: localBrowsers,
+ logLevel: process.env.npm_config_debug ? config.LOG_DEBUG : config.LOG_INFO,
+ frameworks: [ 'browserify', 'mocha' ],
+ files: [ 'test/*.js' ],
+ exclude: [],
+ preprocessors: {
+ 'test/*.js': [ 'browserify' ],
+ },
+ browserify: {
+ debug: true,
+ bare: true,
+ transform: [
+ browserifyIstanbul({ ignore: [ '**/node_modules/**', '**/test/**' ] }),
+ ],
+ },
+ reporters: [ 'progress', 'coverage' ],
+ coverageReporter: {
+ type: 'lcov',
+ dir: 'coverage',
+ },
+ port: 9876,
+ colors: true,
+ concurrency: 3,
+ autoWatch: false,
+ captureTimeout: defaultTimeout,
+ browserDisconnectTimeout: defaultTimeout,
+ browserNoActivityTimeout: defaultTimeout,
+ singleRun: true,
+ });
+
+ if (process.env.SAUCE_ACCESS_KEY && process.env.SAUCE_USERNAME) {
+ var branch = process.env.TRAVIS_BRANCH || 'local';
+ var build = 'localbuild';
+ if (process.env.TRAVIS_JOB_NUMBER) {
+ build = 'travis@' + process.env.TRAVIS_JOB_NUMBER;
+ }
+ config.reporters.push('saucelabs');
+ config.set({
+ customLaunchers: sauceLabsBrowsers,
+ browsers: localBrowsers.concat(Object.keys(sauceLabsBrowsers)),
+ sauceLabs: {
+ testName: packageJson.name,
+ tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER || new Date().getTime(),
+ recordVideo: true,
+ startConnect: ('TRAVIS' in process.env) === false,
+ tags: [
+ 'typeDetect_' + packageJson.version,
+ process.env.SAUCE_USERNAME + '@' + branch,
+ build,
+ ],
+ },
+ });
+ }
+};
diff --git a/package.json b/package.json
index 1e3f832..d6a5b46 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
},
"scripts": {
"bench": "node bench",
- "build": "browserify $npm_pakcage_main --standalone deepEqual -o deep-eql.js",
+ "build": "browserify $npm_package_main --standalone deepEqual -o deep-eql.js",
"lint": "eslint --ignore-path .gitignore .",
"prepublish": "npm run build",
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
@@ -48,11 +48,12 @@
"rules": {
"complexity": 0,
"spaced-comment": 0,
+ "no-underscore-dangle": 0,
"no-use-before-define": 0
}
},
"dependencies": {
- "type-detect": "^3.0.0"
+ "type-detect": "^4.0.0"
},
"devDependencies": {
"benchmark": "^2.1.0",
@@ -84,6 +85,5 @@
},
"engines": {
"node": ">=0.12"
- },
- "version": "2.0.0"
-}
\ No newline at end of file
+ }
+}
diff --git a/test/.eslintrc b/test/.eslintrc
new file mode 100644
index 0000000..edffc56
--- /dev/null
+++ b/test/.eslintrc
@@ -0,0 +1,19 @@
+{
+ "extends": [ "strict/test" ],
+ "env": {
+ "node": true,
+ "browser": true,
+ "es6": true,
+ "mocha": true
+ },
+ "rules": {
+ "no-new-wrappers": 0,
+ "no-array-constructor": 0,
+ "no-new-object": 0,
+ "no-empty-function": 0,
+ "no-undefined": 0,
+ "complexity": 0,
+ "max-statements": 0,
+ "id-match": 0
+ }
+}
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..5714d0b
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,538 @@
+'use strict';
+var assert = require('simple-assert');
+var eql = require('..');
+var MemoizeMap = require('..').MemoizeMap;
+function describeIf(condition) {
+ return condition ? describe : describe.skip;
+}
+describe('Generic', function () {
+
+ describe('strings', function () {
+
+ it('returns true for same values', function () {
+ assert(eql('x', 'x'), 'eql("x", "x")');
+ });
+
+ it('returns true for different instances with same values', function () {
+ assert(eql(new String('x'), new String('x')), 'eql(new String("x"), new String("x"))');
+ });
+
+ it('returns false for literal vs instance with same value', function () {
+ assert(eql('x', new String('x')) === false, 'eql("x", new String("x")) === false');
+ assert(eql(new String('x'), 'x') === false, 'eql(new String("x"), "x") === false');
+ });
+
+ it('returns false for different instances with different values', function () {
+ assert(eql(new String('x'), new String('y')) === false,
+ 'eql(new String("x"), new String("y")) === false');
+ });
+
+ it('returns false for different values', function () {
+ assert(eql('x', 'y') === false, 'eql("x", "y") === false');
+ });
+
+ });
+
+ describe('booleans', function () {
+
+ it('returns true for same values', function () {
+ assert(eql(true, true), 'eql(true, true)');
+ });
+
+ it('returns true for instances with same value', function () {
+ assert(eql(new Boolean(true), new Boolean(true)), 'eql(new Boolean(true), new Boolean(true))');
+ });
+
+ it('returns false for literal vs instance with same value', function () {
+ assert(eql(true, new Boolean(true)) === false, 'eql(true, new Boolean(true)) === false');
+ });
+
+ it('returns false for literal vs instance with different values', function () {
+ assert(eql(false, new Boolean(true)) === false, 'eql(false, new Boolean(true)) === false');
+ assert(eql(new Boolean(false), true) === false, 'eql(new Boolean(false), true) === false');
+ });
+
+ it('returns false for instances with different values', function () {
+ assert(eql(new Boolean(false), new Boolean(true)) === false,
+ 'eql(new Boolean(false), new Boolean(true)) === false');
+ assert(eql(new Boolean(true), new Boolean(false)) === false,
+ 'eql(new Boolean(true), new Boolean(false)) === false');
+ });
+
+ it('returns false for different values', function () {
+ assert(eql(true, false) === false, 'eql(true, false) === false');
+ assert(eql(true, Boolean(false)) === false, 'eql(true, Boolean(false)) === false');
+ });
+
+ });
+
+ describe('null', function () {
+
+ it('returns true for two nulls', function () {
+ assert(eql(null, null), 'eql(null, null)');
+ });
+
+ it('returns false for null, undefined', function () {
+ assert(eql(null, undefined) === false, 'eql(null, undefined) === false');
+ });
+
+ it('doesn\'t crash on weakmap key error (#33)', function () {
+ assert(eql({}, null) === false, 'eql({}, null) === false');
+ });
+
+ });
+
+ describe('undefined', function () {
+
+ it('returns true for two undefineds', function () {
+ assert(eql(undefined, undefined), 'eql(undefined, undefined)');
+ });
+
+ it('returns false for undefined, null', function () {
+ assert(eql(undefined, null) === false, 'eql(undefined, null) === false');
+ });
+
+ });
+
+ describe('numbers', function () {
+
+ it('returns true for same values', function () {
+ assert(eql(-0, -0), 'eql(-0, -0)');
+ assert(eql(+0, +0), 'eql(+0, +0)');
+ assert(eql(0, 0), 'eql(0, 0)');
+ assert(eql(1, 1), 'eql(1, 1)');
+ assert(eql(Infinity, Infinity), 'eql(Infinity, Infinity)');
+ assert(eql(-Infinity, -Infinity), 'eql(-Infinity, -Infinity)');
+ });
+
+ it('returns false for literal vs instance with same value', function () {
+ assert(eql(1, new Number(1)) === false, 'eql(1, new Number(1)) === false');
+ });
+
+ it('returns true NaN vs NaN', function () {
+ assert(eql(NaN, NaN), 'eql(NaN, NaN)');
+ });
+
+ it('returns true for NaN instances', function () {
+ assert(eql(new Number(NaN), new Number(NaN)), 'eql(new Number(NaN), new Number(NaN))');
+ });
+
+ it('returns false on numbers with different signs', function () {
+ assert(eql(-1, 1) === false, 'eql(-1, 1) === false');
+ assert(eql(-0, +0) === false, 'eql(-0, +0) === false');
+ assert(eql(-Infinity, Infinity) === false, 'eql(-Infinity, +Infinity) === false');
+ });
+
+ it('returns false on instances with different signs', function () {
+ assert(eql(new Number(-1), new Number(1)) === false, 'eql(new Number(-1), new Number(1)) === false');
+ assert(eql(new Number(-0), new Number(+0)) === false, 'eql(new Number(-0), new Number(+0)) === false');
+ assert(eql(new Number(-Infinity), new Number(Infinity)) === false,
+ 'eql(new Number(-Infinity), new Number(+Infinity)) === false');
+ });
+
+ });
+
+ describe('dates', function () {
+
+ it('returns true given two dates with the same time', function () {
+ var dateA = new Date();
+ assert(eql(dateA, new Date(dateA.getTime())), 'eql(dateA, new Date(dateA.getTime()))');
+ });
+
+ it('returns true given two invalid dates', function () {
+ assert(eql(new Date(NaN), new Date(NaN)), 'eql(new Date(NaN), new Date(NaN))');
+ });
+
+ it('returns false given two dates with the different times', function () {
+ var dateA = new Date();
+ assert(eql(dateA, new Date(dateA.getTime() + 1)) === false,
+ 'eql(dateA, new Date(dateA.getTime() + 1)) === false');
+ });
+
+ });
+
+ describe('regexp', function () {
+
+ it('returns true given two regexes with the same source', function () {
+ assert(eql(/\s/, /\s/), 'eql(/\\s/, /\\s/)');
+ assert(eql(/\s/, new RegExp('\\s')), 'eql(/\\s/, new RegExp("\\s"))');
+ });
+
+ it('returns false given two regexes with different source', function () {
+ assert(eql(/^$/, /^/) === false, 'eql(/^$/, /^/) === false');
+ assert(eql(/^$/, new RegExp('^')) === false, 'eql(/^$/, new RegExp("^"))');
+ });
+
+ it('returns false given two regexes with different flags', function () {
+ assert(eql(/^/m, /^/i) === false, 'eql(/^/m, /^/i) === false');
+ });
+
+ });
+
+ describe('empty types', function () {
+
+ it('returns true on two empty objects', function () {
+ assert(eql({}, {}), 'eql({}, {})');
+ });
+
+ it('returns true on two empty arrays', function () {
+ assert(eql([], []), 'eql([], [])');
+ });
+
+ it('returns false on different types', function () {
+ assert(eql([], {}) === false, 'eql([], {}) === false');
+ });
+
+ });
+
+ describe('class instances', function () {
+
+ it('returns true given two empty class instances', function () {
+ function BaseA() {}
+ assert(eql(new BaseA(), new BaseA()), 'eql(new BaseA(), new BaseA())');
+ });
+
+ it('returns true given two class instances with same properties', function () {
+ function BaseA(prop) {
+ this.prop = prop;
+ }
+ assert(eql(new BaseA(1), new BaseA(1)), 'eql(new BaseA(1), new BaseA(1))');
+ });
+
+ it('returns true given two class instances with deeply equal bases', function () {
+ function BaseA() {}
+ function BaseB() {}
+ BaseA.prototype.foo = { a: 1 };
+ BaseB.prototype.foo = { a: 1 };
+ assert(eql(new BaseA(), new BaseB()) === true,
+ 'eql(new <base with .prototype.foo = { a: 1 }>, new <base with .prototype.foo = { a: 1 }>) === true');
+ });
+
+ it('returns false given two class instances with different properties', function () {
+ function BaseA(prop) {
+ this.prop = prop;
+ }
+ assert(eql(new BaseA(1), new BaseA(2)) === false, 'eql(new BaseA(1), new BaseA(2)) === false');
+ });
+
+ it('returns false given two class instances with deeply unequal bases', function () {
+ function BaseA() {}
+ function BaseB() {}
+ BaseA.prototype.foo = { a: 1 };
+ BaseB.prototype.foo = { a: 2 };
+ assert(eql(new BaseA(), new BaseB()) === false,
+ 'eql(new <base with .prototype.foo = { a: 1 }>, new <base with .prototype.foo = { a: 2 }>) === false');
+ });
+
+ });
+
+ describe('arguments', function () {
+ function getArguments() {
+ return arguments;
+ }
+
+ it('returns true given two arguments', function () {
+ var argumentsA = getArguments();
+ var argumentsB = getArguments();
+ assert(eql(argumentsA, argumentsB), 'eql(argumentsA, argumentsB)');
+ });
+
+ it('returns true given two arguments with same properties', function () {
+ var argumentsA = getArguments(1, 2);
+ var argumentsB = getArguments(1, 2);
+ assert(eql(argumentsA, argumentsB), 'eql(argumentsA, argumentsB)');
+ });
+
+ it('returns false given two arguments with different properties', function () {
+ var argumentsA = getArguments(1, 2);
+ var argumentsB = getArguments(3, 4);
+ assert(eql(argumentsA, argumentsB) === false, 'eql(argumentsA, argumentsB) === false');
+ });
+
+ it('returns false given an array', function () {
+ assert(eql([], arguments) === false, 'eql([], arguments) === false');
+ });
+
+ it('returns false given an object', function () {
+ assert(eql({}, arguments) === false, 'eql({}, arguments) === false');
+ });
+
+ });
+
+ describe('arrays', function () {
+
+ it('returns true with arrays containing same literals', function () {
+ assert(eql([ 1, 2, 3 ], [ 1, 2, 3 ]), 'eql([ 1, 2, 3 ], [ 1, 2, 3 ])');
+ assert(eql([ 'a', 'b', 'c' ], [ 'a', 'b', 'c' ]), 'eql([ "a", "b", "c" ], [ "a", "b", "c" ])');
+ });
+
+ it('returns true given literal or constructor', function () {
+ assert(eql([ 1, 2, 3 ], new Array(1, 2, 3)), 'eql([ 1, 2, 3 ], new Array(1, 2, 3))');
+ });
+
+ it('returns false with arrays containing literals in different order', function () {
+ assert(eql([ 3, 2, 1 ], [ 1, 2, 3 ]) === false, 'eql([ 3, 2, 1 ], [ 1, 2, 3 ]) === false');
+ });
+
+ it('returns false for arrays of different length', function () {
+ assert(eql(new Array(1), new Array(100)) === false, 'eql(new Array(1), new Array(100)) === false');
+ });
+
+ });
+
+ describe('objects', function () {
+
+ it('returns true with objects containing same literals', function () {
+ assert(eql({ foo: 1, bar: 2 }, { foo: 1, bar: 2 }), 'eql({ foo: 1, bar: 2 }, { foo: 1, bar: 2 })');
+ assert(eql({ foo: 'baz' }, { foo: 'baz' }), 'eql({ foo: "baz" }, { foo: "baz" })');
+ });
+
+ it('returns true for deeply nested objects', function () {
+ assert(eql({ foo: { bar: 'foo' } }, { foo: { bar: 'foo' } }),
+ 'eql({ foo: { bar: "foo" }}, { foo: { bar: "foo" }})');
+ });
+
+ it('returns true with objects with same circular reference', function () {
+ var objectA = { foo: 1 };
+ var objectB = { foo: 1 };
+ var objectC = { a: objectA, b: objectB };
+ objectA.bar = objectC;
+ objectB.bar = objectC;
+ assert(eql(objectA, objectB) === true,
+ 'eql({ foo: 1, bar: objectC }, { foo: 1, bar: objectC }) === true');
+ });
+
+ it('returns true with objects with deeply equal prototypes', function () {
+ var objectA = Object.create({ foo: { a: 1 } });
+ var objectB = Object.create({ foo: { a: 1 } });
+ assert(eql(objectA, objectB) === true,
+ 'eql(Object.create({ foo: { a: 1 } }), Object.create({ foo: { a: 1 } })) === true');
+ });
+
+ it('returns false with objects containing different literals', function () {
+ assert(eql({ foo: 1, bar: 1 }, { foo: 1, bar: 2 }) === false,
+ 'eql({ foo: 1, bar: 2 }, { foo: 1, bar: 2 }) === false');
+ assert(eql({ foo: 'bar' }, { foo: 'baz' }) === false, 'eql({ foo: "bar" }, { foo: "baz" }) === false');
+ assert(eql({ foo: { bar: 'foo' } }, { foo: { bar: 'baz' } }) === false,
+ 'eql({ foo: { bar: "foo" }}, { foo: { bar: "baz" }}) === false');
+ });
+
+ it('returns false with objects containing different keys', function () {
+ assert(eql({ foo: 1, bar: 1 }, { foo: 1, baz: 2 }) === false,
+ 'eql({ foo: 1, bar: 2 }, { foo: 1, baz: 2 }) === false');
+ assert(eql({ foo: 'bar' }, { bar: 'baz' }) === false, 'eql({ foo: "bar" }, { foo: "baz" }) === false');
+ });
+
+ it('returns true with circular objects', function () {
+ var objectA = { foo: 1 };
+ var objectB = { foo: 1 };
+ objectA.bar = objectB;
+ objectB.bar = objectA;
+ assert(eql(objectA, objectB) === true,
+ 'eql({ foo: 1, bar: -> }, { foo: 1, bar: <- }) === true');
+ });
+
+ it('returns true with non-extensible objects', function () {
+ var objectA = Object.preventExtensions({ foo: 1 });
+ var objectB = Object.preventExtensions({ foo: 1 });
+ assert(eql(objectA, objectB) === true,
+ 'eql(Object.preventExtensions({ foo: 1 }), Object.preventExtensions({ foo: 1 })) === true');
+ });
+
+ it('returns true with sealed objects', function () {
+ var objectA = Object.seal({ foo: 1 });
+ var objectB = Object.seal({ foo: 1 });
+ assert(eql(objectA, objectB) === true,
+ 'eql(Object.seal({ foo: 1 }), Object.seal({ foo: 1 })) === true');
+ });
+
+ it('returns true with frozen objects', function () {
+ var objectA = Object.freeze({ foo: 1 });
+ var objectB = Object.freeze({ foo: 1 });
+ assert(eql(objectA, objectB) === true,
+ 'eql(Object.freeze({ foo: 1 }), Object.freeze({ foo: 1 })) === true');
+ });
+
+ it('returns false with objects with deeply unequal prototypes', function () {
+ var objectA = Object.create({ foo: { a: 1 } });
+ var objectB = Object.create({ foo: { a: 2 } });
+ assert(eql(objectA, objectB) === false,
+ 'eql(Object.create({ foo: { a: 1 } }), Object.create({ foo: { a: 2 } })) === false');
+ });
+
+ });
+
+ describe('functions', function () {
+
+ it('returns true for same functions', function () {
+ function foo() {}
+ assert(eql(foo, foo), 'eql(function foo() {}, function foo() {})');
+ });
+
+ it('returns false for different functions', function () {
+ assert(eql(function foo() {}, function bar() {}) === false,
+ 'eql(function foo() {}, function bar() {}) === false');
+ });
+
+ });
+
+ describe('errors', function () {
+
+ it('returns true for same errors', function () {
+ var error = new Error('foo');
+ assert(eql(error, error), 'eql(error, error)');
+ });
+
+ it('returns false for different errors', function () {
+ assert(eql(new Error('foo'), new Error('foo')) === false,
+ 'eql(new Error("foo"), new Error("foo")) === false');
+ });
+
+ });
+
+});
+
+describe('Node Specific', function () {
+
+ describeIf(typeof Buffer === 'function')('buffers', function () {
+
+ it('returns true for same buffers', function () {
+ assert(eql(new Buffer([ 1 ]), new Buffer([ 1 ])) === true,
+ 'eql(new Buffer([ 1 ]), new Buffer([ 1 ])) === true');
+ });
+
+ it('returns false for different buffers', function () {
+ assert(eql(new Buffer([ 1 ]), new Buffer([ 2 ])) === false,
+ 'eql(new Buffer([ 1 ]), new Buffer([ 2 ])) === false');
+ });
+
+ });
+
+});
+
+describe('Memoize', function () {
+
+ it('returns true if MemoizeMap says so', function () {
+ var memoizeMap = new MemoizeMap();
+ var valueAMap = new MemoizeMap();
+ var valueA = {};
+ var valueB = { not: 'equal' };
+ valueAMap.set(valueB, true);
+ memoizeMap.set(valueA, valueAMap);
+ assert(eql(valueA, valueB, { memoize: memoizeMap }) === true,
+ 'eql({}, {not:"equal"}, <memoizeMap>) === true');
+ });
+
+ it('returns false if MemoizeMap says so', function () {
+ var memoizeMap = new MemoizeMap();
+ var valueAMap = new MemoizeMap();
+ var valueA = {};
+ var valueB = {};
+ valueAMap.set(valueB, false);
+ memoizeMap.set(valueA, valueAMap);
+ assert(eql(valueA, valueB, { memoize: memoizeMap }) === false,
+ 'eql({}, {}, <memoizeMap>) === false');
+ });
+
+ it('resorts to default behaviour if MemoizeMap has no answer (same objects)', function () {
+ var memoizeMap = new MemoizeMap();
+ var valueAMap = new MemoizeMap();
+ var valueA = {};
+ var valueB = {};
+ memoizeMap.set(valueA, valueAMap);
+ assert(eql(valueA, valueB, { memoize: memoizeMap }) === true,
+ 'eql({}, {}, <memoizeMap>) === true');
+ });
+
+ it('resorts to default behaviour if MemoizeMap has no answer (different objects)', function () {
+ var memoizeMap = new MemoizeMap();
+ var valueAMap = new MemoizeMap();
+ var valueA = {};
+ var valueB = { not: 'equal' };
+ memoizeMap.set(valueA, valueAMap);
+ assert(eql(valueA, valueB, { memoize: memoizeMap }) === false,
+ 'eql({}, {}, <memoizeMap>) === false');
+ });
+
+});
+
+describe('Comparator', function () {
+ function specialComparator(left, right) {
+ return left['@@specialValue'] === right['@@specialValue'];
+ }
+ function Matcher(func) {
+ this.func = func;
+ }
+ function matcherComparator(left, right) {
+ if (left instanceof Matcher) {
+ return left.func(right);
+ } else if (right instanceof Matcher) {
+ return right.func(left);
+ }
+ return null;
+ }
+ function falseComparator() {
+ return false;
+ }
+ function nullComparator() {
+ return null;
+ }
+
+ it('returns true if Comparator says so', function () {
+ var valueA = { '@@specialValue': 1, a: 1 };
+ var valueB = { '@@specialValue': 1, a: 2 };
+ assert(eql(valueA, valueB, { comparator: specialComparator }) === true,
+ 'eql({@@specialValue:1,a:1}, {@@specialValue:1,a:2}, <comparator>) === true');
+ });
+
+ it('returns true if Comparator says so even on primitives', function () {
+ var valueA = {
+ a: new Matcher(function (value) {
+ return typeof value === 'number';
+ }),
+ };
+ var valueB = { a: 1 };
+ assert(eql(valueA, valueB, { comparator: matcherComparator }) === true,
+ 'eql({a:value => typeof value === "number"}, {a:1}, <comparator>) === true');
+ });
+
+ it('returns true if Comparator says so even on primitives (switch arg order)', function () {
+ var valueA = { a: 1 };
+ var valueB = {
+ a: new Matcher(function (value) {
+ return typeof value === 'number';
+ }),
+ };
+ assert(eql(valueA, valueB, { comparator: matcherComparator }) === true,
+ 'eql({a:1}, {a:value => typeof value === "number"}, <comparator>) === true');
+ });
+
+ it('returns true if Comparator says so (deep-equality)', function () {
+ var valueA = { a: { '@@specialValue': 1, a: 1 }, b: 1 };
+ var valueB = { a: { '@@specialValue': 1, a: 2 }, b: 1 };
+ assert(eql(valueA, valueB, { comparator: specialComparator }) === true,
+ 'eql({a:{@@specialValue:1,a:1},b:1}, {a:{@@specialValue:2,a:2},b:1}, <comparator>) === true');
+ });
+
+ it('returns false if Comparator returns false (same objects)', function () {
+ var valueA = { a: 1 };
+ var valueB = { a: 1 };
+ assert(eql(valueA, valueB, { comparator: falseComparator }) === false,
+ 'eql({}, {}, <falseComparator>) === false');
+ });
+
+ it('resorts to deep-eql if Comparator returns null (same objects)', function () {
+ var valueA = { a: 1 };
+ var valueB = { a: 1 };
+ assert(eql(valueA, valueB, { comparator: nullComparator }) === true,
+ 'eql({}, {}, <nullComparator>) === true');
+ });
+
+ it('resorts to deep-eql behaviour if Comparator returns null (different objects)', function () {
+ var valueA = { a: 1 };
+ var valueB = { a: 2 };
+ assert(eql(valueA, valueB, { comparator: nullComparator }) === false,
+ 'eql({}, {}, <nullComparator>) === false');
+ });
+
+});
diff --git a/test/new-ecmascript-types.js b/test/new-ecmascript-types.js
new file mode 100644
index 0000000..2195dbe
--- /dev/null
+++ b/test/new-ecmascript-types.js
@@ -0,0 +1,660 @@
+'use strict';
+/* eslint-disable no-eval */
+var assert = require('simple-assert');
+var eql = require('..');
+var emptyFunction = Function.prototype;
+var symbolExists = typeof Symbol === 'function';
+var setExists = typeof Set === 'function';
+var mapExists = typeof Map === 'function';
+var symbolAndMapExist = symbolExists && mapExists;
+var symbolAndSetExist = symbolExists && setExists;
+var supportGenerators = false;
+var supportArrows = false;
+try {
+ eval('function * foo () {}; foo');
+ supportGenerators = true;
+} catch (error) {
+ supportGenerators = false;
+}
+try {
+ eval('() => {}');
+ supportArrows = true;
+} catch (error) {
+ supportArrows = false;
+}
+
+function describeIf(condition) {
+ return condition ? describe : describe.skip;
+}
+describe('ES2015 Specific', function () {
+
+ describeIf(symbolExists && typeof String.prototype[Symbol.iterator] === 'function')('string iterator', function () {
+
+ it('returns true for Strings with same entries', function () {
+ assert(eql('abc'[Symbol.iterator](), 'abc'[Symbol.iterator]()),
+ 'eql("abc"[Symbol.iterator](), "abc"[Symbol.iterator]())');
+ });
+
+ it('returns false for Strings with different entries', function () {
+ assert(eql('abc'[Symbol.iterator](), 'def'[Symbol.iterator]()) === false,
+ 'eql("abc"[Symbol.iterator](), "def"[Symbol.iterator]()) === false');
+ });
+
+ });
+
+ describeIf(symbolExists && typeof Array.prototype[Symbol.iterator] === 'function')('array iterator', function () {
+
+ it('returns true for Arrays with same entries', function () {
+ assert(eql([ 1, 2, 3 ][Symbol.iterator](), [ 1, 2, 3 ][Symbol.iterator]()),
+ 'eql([ 1, 2, 3 ][Symbol.iterator](), [ 1, 2, 3 ][Symbol.iterator]())');
+ });
+
+ it('returns false for Arrays with different entries', function () {
+ assert(eql([ 1, 2, 3 ][Symbol.iterator](), [ 4, 5, 6 ][Symbol.iterator]()) === false,
+ 'eql([ 1, 2, 3 ][Symbol.iterator](), [ 4, 5, 6 ][Symbol.iterator]()) === false');
+ });
+
+ });
+
+ describeIf(typeof Array.prototype.entries === 'function')('array iterator (entries)', function () {
+
+ it('returns true for Arrays with same entries', function () {
+ assert(eql([ 1, 2, 3 ].entries(), [ 1, 2, 3 ].entries()),
+ 'eql([ 1, 2, 3 ].entries(), [ 1, 2, 3 ].entries())');
+ });
+
+ it('returns false for Arrays with different entries', function () {
+ assert(eql([ 1, 2, 3 ].entries(), [ 4, 5, 6 ].entries()) === false,
+ 'eql([ 1, 2, 3 ].entries(), [ 4, 5, 6 ].entries()) === false');
+ });
+
+ });
+
+ describeIf(mapExists)('maps', function () {
+
+ it('returns true for Maps with same entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapA.set('b', 2);
+ mapA.set('c', 3);
+ mapB.set('c', 3);
+ mapB.set('b', 2);
+ mapB.set('a', 1);
+ assert(eql(mapA, mapB), 'eql(Map { a => 1, b => 2, c => 3 }, Map { a => 1, b => 2, c => 3 })');
+ });
+
+ it('returns false for Maps with different entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapB.set('a', 1);
+ mapA.set('b', 2);
+ mapB.set('b', 2);
+ mapA.set('c', 3);
+ mapB.set('c', 3);
+ assert(eql(mapA, mapB), 'eql(Map { a => 1, b => 2, c => 3 }, Map { a => 1, b => 2, c => 3 })');
+ });
+
+ });
+
+ describeIf(symbolAndMapExist && typeof Map.prototype[Symbol.iterator] === 'function')('map iterator', function () {
+
+ it('returns true for Map iterators with same entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapB.set('a', 1);
+ mapA.set('b', 2);
+ mapB.set('b', 2);
+ mapA.set('c', 3);
+ mapB.set('c', 3);
+ assert(eql(mapA[Symbol.iterator](), mapB[Symbol.iterator]()),
+ 'eql(Map { a => 1, b => 2, c => 3 }[Symbol.iterator](), Map { a => 1, b => 2, c => 3 }[Symbol.iterator]())');
+ });
+
+ it('returns false for Map iterators with different entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapB.set('a', 2);
+ mapA.set('b', 3);
+ mapB.set('b', 4);
+ mapA.set('c', 5);
+ mapB.set('c', 6);
+ assert(eql(mapA[Symbol.iterator](), mapB[Symbol.iterator]()) === false,
+ 'eql(Map { a => 1, b => 3, c => 5 }[Symbol.iterator](), ' +
+ 'Map { a => 2, b => 4, c => 6 }[Symbol.iterator]()) === false');
+ });
+
+ });
+
+ describeIf(mapExists && typeof Map.prototype.entries === 'function')('map iterator (entries)', function () {
+
+ it('returns true for Map iterators with same entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapB.set('a', 1);
+ mapA.set('b', 2);
+ mapB.set('b', 2);
+ mapA.set('c', 3);
+ mapB.set('c', 3);
+ assert(eql(mapA.entries(), mapB.entries()),
+ 'eql(Map { a => 1, b => 2, c => 3 }.entries(), Map { a => 1, b => 2, c => 3 }.entries())');
+ });
+
+ it('returns false for Map iterators with different entries', function () {
+ var mapA = new Map();
+ var mapB = new Map();
+ mapA.set('a', 1);
+ mapB.set('a', 2);
+ mapA.set('b', 3);
+ mapB.set('b', 4);
+ mapA.set('c', 5);
+ mapB.set('c', 6);
+ assert(eql(mapA.entries(), mapB.entries()) === false,
+ 'eql(Map { a => 1, b => 3, c => 5 }.entries(), ' +
+ 'Map { a => 2, b => 4, c => 6 }.entries()) === false');
+ });
+
+ });
+
+ describeIf(typeof WeakMap === 'function')('weakmaps', function () {
+
+ it('returns true for same WeakMaps', function () {
+ var weakMap = new WeakMap();
+ assert(eql(weakMap, weakMap), 'eql(weakMap, weakMap)');
+ });
+
+ it('returns false for different WeakMaps', function () {
+ assert(eql(new WeakMap(), new WeakMap()) === false,
+ 'eql(new WeakMap(), new WeakMap()) === false');
+ });
+
+ });
+
+ describeIf(setExists)('sets', function () {
+
+ it('returns true for Sets with same entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('a');
+ setB.add('b');
+ setB.add('c');
+ assert(eql(setA, setB), 'eql(Set { "a", "b", "c" }, Set { "a", "b", "c" })');
+ });
+
+ it('returns true for Sets with same entries in different order', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('b');
+ setB.add('c');
+ setB.add('a');
+ assert(eql(setA, setB), 'eql(Set { "a", "b", "c" }, Set { "b", "c", "a" })');
+ });
+
+ it('returns true for Sets with nested entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add([ [], [], [] ]);
+ setB.add([ [], [], [] ]);
+ assert(eql(setA, setB) === true, 'eql(Set [ [], [], [] ], Set [ [], [], [] ]) === true');
+ });
+
+ it('returns true for Sets with same circular references', function () {
+ var setA = new Set();
+ var setB = new Set();
+ var setC = new Set();
+ setA.add(setC);
+ setB.add(setC);
+ setC.add(setA);
+ setC.add(setB);
+ assert(eql(setA, setB) === true, 'eql(Set { setC }, Set { setC }) === true');
+ });
+
+ it('returns false for Sets with different entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('d');
+ setB.add('e');
+ setB.add('f');
+ assert(eql(setA, setB) === false, 'eql(Set { "a", "b", "c" }, Set { "d", "e", "f" }) === false');
+ });
+
+ it('returns true for circular Sets', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add(setB);
+ setB.add(setA);
+ assert(eql(setA, setB) === true, 'eql(Set { -> }, Set { <- }) === true');
+ });
+
+ });
+
+ describeIf(symbolAndSetExist && typeof Set.prototype[Symbol.iterator] === 'function')('set iterator', function () {
+
+ it('returns true for Sets with same entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('c');
+ setB.add('b');
+ setB.add('a');
+ assert(eql(setA[Symbol.iterator](), setB[Symbol.iterator]()),
+ 'eql(Set { "a", "b", "c" }[Symbol.iterator](), Set { "a", "b", "c" }[Symbol.iterator]())');
+ });
+
+ it('returns false for Sets with different entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('d');
+ setB.add('e');
+ setB.add('f');
+ assert(eql(setA[Symbol.iterator](), setB[Symbol.iterator]()) === false,
+ 'eql(Set { "a", "b", "c" }[Symbol.iterator](), Set { "d", "e", "f" }[Symbol.iterator]()) === false');
+ });
+
+ });
+
+ describeIf(setExists && typeof Set.prototype.entries === 'function')('set iterator (entries)', function () {
+
+ it('returns true for Sets with same entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('c');
+ setB.add('b');
+ setB.add('a');
+ assert(eql(setA.entries(), setB.entries()),
+ 'eql(Set { "a", "b", "c" }.entries(), Set { "a", "b", "c" }.entries())');
+ });
+
+ it('returns false for Sets with different entries', function () {
+ var setA = new Set();
+ var setB = new Set();
+ setA.add('a');
+ setA.add('b');
+ setA.add('c');
+ setB.add('d');
+ setB.add('e');
+ setB.add('f');
+ assert(eql(setA.entries(), setB.entries()) === false,
+ 'eql(Set { "a", "b", "c" }.entries(), Set { "d", "e", "f" }.entries()) === false');
+ });
+
+ });
+
+ describeIf(typeof WeakSet === 'function')('weaksets', function () {
+
+ it('returns true for same WeakSets', function () {
+ var weakSet = new WeakSet();
+ assert(eql(weakSet, weakSet), 'eql(weakSet, weakSet)');
+ });
+
+ it('returns false for different WeakSets', function () {
+ assert(eql(new WeakSet(), new WeakSet()) === false,
+ 'eql(new WeakSet(), new WeakSet()) === false');
+ });
+
+ });
+
+ describeIf(typeof Symbol === 'function')('symbol', function () {
+
+ it('returns true for the same symbols', function () {
+ var sym = Symbol();
+ assert(eql(sym, sym), 'eql(sym, sym)');
+ assert(eql(Symbol.iterator, Symbol.iterator), 'eql(Symbol.iterator, Symbol.iterator)');
+ });
+
+ it('returns false for different symbols', function () {
+ assert(eql(Symbol(), Symbol()) === false, 'eql(Symbol(), Symbol()) === false');
+ });
+
+ });
+
+ describeIf(typeof Promise === 'function')('promise', function () {
+
+ it('returns true for the same promises', function () {
+ var promiseResolve = Promise.resolve();
+ var promiseReject = Promise.reject();
+ var promisePending = new Promise(emptyFunction);
+ assert(eql(promiseResolve, promiseResolve), 'eql(promiseResolve, promiseResolve)');
+ assert(eql(promiseReject, promiseReject), 'eql(promiseReject, promiseReject)');
+ assert(eql(promisePending, promisePending), 'eql(promisePending, promisePending)');
+
+ promiseReject.catch(function () {});
+ });
+
+
+ it('returns false for different promises', function () {
+ assert(eql(Promise.resolve(), Promise.resolve()) === false,
+ 'eql(Promise.resolve(), Promise.resolve()) === false');
+
+ var promiseRejectA = Promise.reject();
+ var promiseRejectB = Promise.reject();
+ assert(eql(promiseRejectA, promiseRejectB) === false,
+ 'eql(Promise.reject(), Promise.reject()) === false');
+
+ promiseRejectA.catch(function () {});
+ promiseRejectB.catch(function () {});
+
+ assert(eql(new Promise(emptyFunction), new Promise(emptyFunction)) === false,
+ 'eql(new Promise(emptyFunction), new Promise(emptyFunction)) === false');
+ });
+
+ });
+
+ describeIf(typeof Int8Array === 'function')('int8array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Int8Array(1, 2, 3, 4), new Int8Array(1, 2, 3, 4)),
+ 'eql(new Int8Array(1, 2, 3, 4), new Int8Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Int8Array(1, 2, 3, 4), new Int8Array(5, 6, 7, 8)) === false,
+ 'eql(new Int8Array(1, 2, 3, 4), new Int8Array(5, 6, 7, 8)) === false');
+ assert(eql(new Int8Array(1, 2, 3, 4), new Int8Array(4, 2, 3, 4)) === false,
+ 'eql(new Int8Array(1, 2, 3, 4), new Int8Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Uint8Array === 'function')('uint8array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(1, 2, 3, 4)),
+ 'eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(5, 6, 7, 8)) === false,
+ 'eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(5, 6, 7, 8)) === false');
+ assert(eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(4, 2, 3, 4)) === false,
+ 'eql(new Uint8Array(1, 2, 3, 4), new Uint8Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Uint8ClampedArray === 'function')('uint8clampedarray', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(1, 2, 3, 4)),
+ 'eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(5, 6, 7, 8)) === false,
+ 'eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(5, 6, 7, 8)) === false');
+ assert(eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(4, 2, 3, 4)) === false,
+ 'eql(new Uint8ClampedArray(1, 2, 3, 4), new Uint8ClampedArray(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Int16Array === 'function')('int16array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Int16Array(1, 2, 3, 4), new Int16Array(1, 2, 3, 4)),
+ 'eql(new Int16Array(1, 2, 3, 4), new Int16Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Int16Array(1, 2, 3, 4), new Int16Array(5, 6, 7, 8)) === false,
+ 'eql(new Int16Array(1, 2, 3, 4), new Int16Array(5, 6, 7, 8)) === false');
+ assert(eql(new Int16Array(1, 2, 3, 4), new Int16Array(4, 2, 3, 4)) === false,
+ 'eql(new Int16Array(1, 2, 3, 4), new Int16Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Uint16Array === 'function')('uint16array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(1, 2, 3, 4)),
+ 'eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(5, 6, 7, 8)) === false,
+ 'eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(5, 6, 7, 8)) === false');
+ assert(eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(4, 2, 3, 4)) === false,
+ 'eql(new Uint16Array(1, 2, 3, 4), new Uint16Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Int32Array === 'function')('int32array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Int32Array(1, 2, 3, 4), new Int32Array(1, 2, 3, 4)),
+ 'eql(new Int32Array(1, 2, 3, 4), new Int32Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Int32Array(1, 2, 3, 4), new Int32Array(5, 6, 7, 8)) === false,
+ 'eql(new Int32Array(1, 2, 3, 4), new Int32Array(5, 6, 7, 8)) === false');
+ assert(eql(new Int32Array(1, 2, 3, 4), new Int32Array(4, 2, 3, 4)) === false,
+ 'eql(new Int32Array(1, 2, 3, 4), new Int32Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Uint32Array === 'function')('uint32array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(1, 2, 3, 4)),
+ 'eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(5, 6, 7, 8)) === false,
+ 'eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(5, 6, 7, 8)) === false');
+ assert(eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(4, 2, 3, 4)) === false,
+ 'eql(new Uint32Array(1, 2, 3, 4), new Uint32Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Float32Array === 'function')('float32array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Float32Array(1, 2, 3, 4), new Float32Array(1, 2, 3, 4)),
+ 'eql(new Float32Array(1, 2, 3, 4), new Float32Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Float32Array(1, 2, 3, 4), new Float32Array(5, 6, 7, 8)) === false,
+ 'eql(new Float32Array(1, 2, 3, 4), new Float32Array(5, 6, 7, 8)) === false');
+ assert(eql(new Float32Array(1, 2, 3, 4), new Float32Array(4, 2, 3, 4)) === false,
+ 'eql(new Float32Array(1, 2, 3, 4), new Float32Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof Float64Array === 'function')('float64array', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new Float64Array(1, 2, 3, 4), new Float64Array(1, 2, 3, 4)),
+ 'eql(new Float64Array(1, 2, 3, 4), new Float64Array(1, 2, 3, 4))');
+ });
+
+ it('returns false for arrays with different values', function () {
+ assert(eql(new Float64Array(1, 2, 3, 4), new Float64Array(5, 6, 7, 8)) === false,
+ 'eql(new Float64Array(1, 2, 3, 4), new Float64Array(5, 6, 7, 8)) === false');
+ assert(eql(new Float64Array(1, 2, 3, 4), new Float64Array(4, 2, 3, 4)) === false,
+ 'eql(new Float64Array(1, 2, 3, 4), new Float64Array(4, 2, 3, 4)) === false');
+ });
+
+ });
+
+ describeIf(typeof DataView === 'function')('dataview', function () {
+
+ it('returns true for arrays with same values', function () {
+ var dataViewA = new DataView(new ArrayBuffer(4));
+ dataViewA.setUint8(0, 1);
+ dataViewA.setUint8(1, 2);
+ dataViewA.setUint8(2, 3);
+ dataViewA.setUint8(3, 4);
+ var dataViewB = new DataView(new ArrayBuffer(4));
+ dataViewB.setUint8(0, 1);
+ dataViewB.setUint8(1, 2);
+ dataViewB.setUint8(2, 3);
+ dataViewB.setUint8(3, 4);
+ assert(eql(dataViewA, dataViewB),
+ 'eql(dataViewA, dataViewB)');
+ });
+
+ it('returns false for arrays with different lengths', function () {
+ assert(eql(new DataView(new ArrayBuffer(4)), new DataView(new ArrayBuffer(1))) === false,
+ 'eql(new DataView(new ArrayBuffer(4)), new DataView(new ArrayBuffer(1))) === false');
+ });
+
+ it('returns false for arrays with different values', function () {
+ var dataViewA = new DataView(new ArrayBuffer(4));
+ dataViewA.setUint8(0, 1);
+ dataViewA.setUint8(1, 2);
+ dataViewA.setUint8(2, 3);
+ dataViewA.setUint8(3, 4);
+ var dataViewB = new DataView(new ArrayBuffer(4));
+ dataViewB.setUint8(0, 5);
+ dataViewB.setUint8(1, 6);
+ dataViewB.setUint8(2, 7);
+ dataViewB.setUint8(3, 8);
+ assert(eql(dataViewA, dataViewB) === false,
+ 'eql(dataViewA, dataViewB) === false');
+ });
+
+ });
+
+ describeIf(typeof ArrayBuffer === 'function')('arraybuffer', function () {
+
+ it('returns true for arrays with same values', function () {
+ assert(eql(new ArrayBuffer(1), new ArrayBuffer(1)),
+ 'eql(new ArrayBuffer(1), new ArrayBuffer(1)))');
+ });
+
+ it('returns false for arrays with different lengths', function () {
+ assert(eql(new ArrayBuffer(1), new ArrayBuffer(4)) === false,
+ 'eql(new ArrayBuffer(1), new ArrayBuffer(4)) === false');
+ });
+
+ it('returns false for arrays with different values', function () {
+ var dataViewA = new DataView(new ArrayBuffer(4));
+ dataViewA.setUint8(0, 1);
+ dataViewA.setUint8(1, 2);
+ dataViewA.setUint8(2, 3);
+ dataViewA.setUint8(3, 4);
+ var dataViewB = new DataView(new ArrayBuffer(4));
+ dataViewB.setUint8(0, 5);
+ dataViewB.setUint8(1, 6);
+ dataViewB.setUint8(2, 7);
+ dataViewB.setUint8(3, 8);
+ assert(eql(dataViewA.buffer, dataViewB.buffer) === false,
+ 'eql(dataViewA.buffer, dataViewB.buffer) === false');
+ });
+
+ });
+
+ describeIf(supportArrows)('arrow function', function () {
+
+ it('returns true for same arrow functions', function () {
+ var arrow = eval('() => {}');
+ assert(eql(arrow, arrow),
+ 'eql(arrow, arrow)');
+ });
+
+ it('returns false for different arrow functions', function () {
+ assert(eql(eval('() => {}'), eval('() => {}')) === false,
+ 'eql(() => {}, () => {}) === false');
+ });
+
+ });
+
+ describeIf(supportGenerators)('generator function', function () {
+
+ it('returns true for same arrow functions', function () {
+ var generator = eval('function * generator() {}; generator');
+ assert(eql(generator, generator),
+ 'eql(generator, generator)');
+ });
+
+ it('returns false for different arrow functions', function () {
+ assert(eql(eval('function * generator() {}; generator'), eval('function * generator() {}; generator')) === false,
+ 'eql(function * generator() {}, function * generator() {}) === false');
+ });
+
+ });
+
+ describeIf(supportGenerators)('generator', function () {
+
+ it('returns true for same generator function calls', function () {
+ var generator = eval('function * generator() { yield 1; yield 2; }; generator');
+ assert(eql(generator(), generator()),
+ 'eql(generator(), generator())');
+ });
+
+ it('returns true for different generator function calls that return same results', function () {
+ var generatorA = eval('function * generatorA() { yield 1; yield 2; }; generatorA');
+ var generatorB = eval('function * generatorB() { yield 1; yield 2; }; generatorB');
+ assert(eql(generatorA(), generatorB()),
+ 'eql(generatorA(), generatorB())');
+ });
+
+ it('returns true for different generator function calls are at level of iteration with same results', function () {
+ var generatorA = eval('function * generatorA() { yield 1; yield 2; yield 3; }; generatorA');
+ var generatorB = eval('function * generatorB() { yield 6; yield 2; yield 3; }; generatorB');
+ var generatorAIterator = generatorA();
+ var generatorBIterator = generatorB();
+ generatorAIterator.next();
+ generatorBIterator.next();
+ assert(eql(generatorAIterator, generatorBIterator),
+ 'eql(generatorAIterator, generatorBIterator');
+ });
+
+ it('returns false for same generator function calls that return different results', function () {
+ var generator = eval('var set = 0; function * generator() { yield set++; }; generator');
+ assert(eql(generator(), generator()) === false,
+ 'eql(generator(), generator()) === false');
+ });
+
+ it('returns false for generators at different stages of iteration', function () {
+ var generatorA = eval('function * generatorA() { yield 1; yield 2; }; generatorA');
+ var generatorB = eval('function * generatorB() { yield 1; yield 2; }; generatorB');
+ var generatorBIterator = generatorB();
+ generatorBIterator.next();
+ assert(eql(generatorA(), generatorBIterator) === false,
+ 'eql(generatorA(), generatorBIterator) === false');
+ });
+
+ it('returns false for generators if one is done', function () {
+ var generatorA = eval('function * generatorA() { yield 1; yield 2; }; generatorA');
+ var generatorB = eval('function * generatorB() { yield 1; yield 2; }; generatorB');
+ var generatorBIterator = generatorB();
+ generatorBIterator.next();
+ generatorBIterator.next();
+ generatorBIterator.next();
+ assert(eql(generatorA(), generatorBIterator) === false,
+ 'eql(generatorA(), generatorBIterator) === false');
+ });
+
+ });
+
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-deep-eql.git
More information about the Pkg-javascript-commits
mailing list