chai 1.7.2 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +1 -1
- package/CONTRIBUTING.md +173 -0
- package/History.md +87 -1
- package/README.md +44 -22
- package/ReleaseNotes.md +188 -0
- package/bower.json +1 -1
- package/chai.js +738 -286
- package/karma.conf.js +28 -0
- package/karma.sauce.js +41 -0
- package/lib/chai/assertion.js +29 -29
- package/lib/chai/config.js +50 -0
- package/lib/chai/core/assertions.js +71 -27
- package/lib/chai/interface/assert.js +13 -37
- package/lib/chai/interface/expect.js +1 -1
- package/lib/chai/interface/should.js +27 -25
- package/lib/chai/utils/addChainableMethod.js +22 -5
- package/lib/chai/utils/addMethod.js +7 -1
- package/lib/chai/utils/addProperty.js +1 -1
- package/lib/chai/utils/flag.js +1 -1
- package/lib/chai/utils/getActual.js +2 -3
- package/lib/chai/utils/getEnumerableProperties.js +1 -1
- package/lib/chai/utils/getMessage.js +1 -1
- package/lib/chai/utils/getName.js +1 -1
- package/lib/chai/utils/getPathValue.js +1 -1
- package/lib/chai/utils/getProperties.js +1 -1
- package/lib/chai/utils/index.js +7 -1
- package/lib/chai/utils/objDisplay.js +3 -2
- package/lib/chai/utils/overwriteChainableMethod.js +53 -0
- package/lib/chai/utils/overwriteMethod.js +1 -1
- package/lib/chai/utils/overwriteProperty.js +1 -1
- package/lib/chai/utils/test.js +1 -1
- package/lib/chai/utils/transferFlags.js +1 -1
- package/lib/chai/utils/type.js +1 -1
- package/lib/chai.js +9 -2
- package/package.json +8 -8
- package/sauce.browsers.js +128 -0
- package/lib/chai/utils/eql.js +0 -129
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Chai - addChainingMethod utility
|
|
3
|
-
* Copyright(c) 2012-
|
|
3
|
+
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
var transferFlags = require('./transferFlags');
|
|
12
|
+
var flag = require('./flag');
|
|
13
|
+
var config = require('../config');
|
|
12
14
|
|
|
13
15
|
/*!
|
|
14
16
|
* Module variables
|
|
@@ -55,15 +57,30 @@ var call = Function.prototype.call,
|
|
|
55
57
|
*/
|
|
56
58
|
|
|
57
59
|
module.exports = function (ctx, name, method, chainingBehavior) {
|
|
58
|
-
if (typeof chainingBehavior !== 'function')
|
|
60
|
+
if (typeof chainingBehavior !== 'function') {
|
|
59
61
|
chainingBehavior = function () { };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var chainableBehavior = {
|
|
65
|
+
method: method
|
|
66
|
+
, chainingBehavior: chainingBehavior
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// save the methods so we can overwrite them later, if we need to.
|
|
70
|
+
if (!ctx.__methods) {
|
|
71
|
+
ctx.__methods = {};
|
|
72
|
+
}
|
|
73
|
+
ctx.__methods[name] = chainableBehavior;
|
|
60
74
|
|
|
61
75
|
Object.defineProperty(ctx, name,
|
|
62
76
|
{ get: function () {
|
|
63
|
-
chainingBehavior.call(this);
|
|
77
|
+
chainableBehavior.chainingBehavior.call(this);
|
|
64
78
|
|
|
65
|
-
var assert = function () {
|
|
66
|
-
var
|
|
79
|
+
var assert = function assert() {
|
|
80
|
+
var old_ssfi = flag(this, 'ssfi');
|
|
81
|
+
if (old_ssfi && config.includeStack === false)
|
|
82
|
+
flag(this, 'ssfi', assert);
|
|
83
|
+
var result = chainableBehavior.method.apply(this, arguments);
|
|
67
84
|
return result === undefined ? this : result;
|
|
68
85
|
};
|
|
69
86
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Chai - addMethod utility
|
|
3
|
-
* Copyright(c) 2012-
|
|
3
|
+
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
var config = require('../config');
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* ### .addMethod (ctx, name, method)
|
|
9
11
|
*
|
|
@@ -28,9 +30,13 @@
|
|
|
28
30
|
* @name addMethod
|
|
29
31
|
* @api public
|
|
30
32
|
*/
|
|
33
|
+
var flag = require('./flag');
|
|
31
34
|
|
|
32
35
|
module.exports = function (ctx, name, method) {
|
|
33
36
|
ctx[name] = function () {
|
|
37
|
+
var old_ssfi = flag(this, 'ssfi');
|
|
38
|
+
if (old_ssfi && config.includeStack === false)
|
|
39
|
+
flag(this, 'ssfi', ctx[name]);
|
|
34
40
|
var result = method.apply(this, arguments);
|
|
35
41
|
return result === undefined ? this : result;
|
|
36
42
|
};
|
package/lib/chai/utils/flag.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Chai - getActual utility
|
|
3
|
-
* Copyright(c) 2012-
|
|
3
|
+
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -14,6 +14,5 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
module.exports = function (obj, args) {
|
|
17
|
-
|
|
18
|
-
return 'undefined' !== typeof actual ? actual : obj._obj;
|
|
17
|
+
return args.length > 4 ? args[4] : obj._obj;
|
|
19
18
|
};
|
package/lib/chai/utils/index.js
CHANGED
|
@@ -62,7 +62,7 @@ exports.transferFlags = require('./transferFlags');
|
|
|
62
62
|
* Deep equal utility
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
|
-
exports.eql = require('
|
|
65
|
+
exports.eql = require('deep-eql');
|
|
66
66
|
|
|
67
67
|
/*!
|
|
68
68
|
* Deep path value
|
|
@@ -106,3 +106,9 @@ exports.overwriteMethod = require('./overwriteMethod');
|
|
|
106
106
|
|
|
107
107
|
exports.addChainableMethod = require('./addChainableMethod');
|
|
108
108
|
|
|
109
|
+
/*!
|
|
110
|
+
* Overwrite chainable method
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
exports.overwriteChainableMethod = require('./overwriteChainableMethod');
|
|
114
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Chai - flag utility
|
|
3
|
-
* Copyright(c) 2012-
|
|
3
|
+
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
var inspect = require('./inspect');
|
|
12
|
+
var config = require('../config');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* ### .objDisplay (object)
|
|
@@ -26,7 +27,7 @@ module.exports = function (obj) {
|
|
|
26
27
|
var str = inspect(obj)
|
|
27
28
|
, type = Object.prototype.toString.call(obj);
|
|
28
29
|
|
|
29
|
-
if (str.length >=
|
|
30
|
+
if (config.truncateThreshold && str.length >= config.truncateThreshold) {
|
|
30
31
|
if (type === '[object Function]') {
|
|
31
32
|
return !obj.name || obj.name === ''
|
|
32
33
|
? '[Function]'
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Chai - overwriteChainableMethod utility
|
|
3
|
+
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* ### overwriteChainableMethod (ctx, name, fn)
|
|
9
|
+
*
|
|
10
|
+
* Overwites an already existing chainable method
|
|
11
|
+
* and provides access to the previous function or
|
|
12
|
+
* property. Must return functions to be used for
|
|
13
|
+
* name.
|
|
14
|
+
*
|
|
15
|
+
* utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
|
|
16
|
+
* function (_super) {
|
|
17
|
+
* }
|
|
18
|
+
* , function (_super) {
|
|
19
|
+
* }
|
|
20
|
+
* );
|
|
21
|
+
*
|
|
22
|
+
* Can also be accessed directly from `chai.Assertion`.
|
|
23
|
+
*
|
|
24
|
+
* chai.Assertion.overwriteChainableMethod('foo', fn, fn);
|
|
25
|
+
*
|
|
26
|
+
* Then can be used as any other assertion.
|
|
27
|
+
*
|
|
28
|
+
* expect(myFoo).to.have.length(3);
|
|
29
|
+
* expect(myFoo).to.have.length.above(3);
|
|
30
|
+
*
|
|
31
|
+
* @param {Object} ctx object whose method / property is to be overwritten
|
|
32
|
+
* @param {String} name of method / property to overwrite
|
|
33
|
+
* @param {Function} method function that returns a function to be used for name
|
|
34
|
+
* @param {Function} chainingBehavior function that returns a function to be used for property
|
|
35
|
+
* @name overwriteChainableMethod
|
|
36
|
+
* @api public
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
module.exports = function (ctx, name, method, chainingBehavior) {
|
|
40
|
+
var chainableBehavior = ctx.__methods[name];
|
|
41
|
+
|
|
42
|
+
var _chainingBehavior = chainableBehavior.chainingBehavior;
|
|
43
|
+
chainableBehavior.chainingBehavior = function () {
|
|
44
|
+
var result = chainingBehavior(_chainingBehavior).call(this);
|
|
45
|
+
return result === undefined ? this : result;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
var _method = chainableBehavior.method;
|
|
49
|
+
chainableBehavior.method = function () {
|
|
50
|
+
var result = method(_method).apply(this, arguments);
|
|
51
|
+
return result === undefined ? this : result;
|
|
52
|
+
};
|
|
53
|
+
};
|
package/lib/chai/utils/test.js
CHANGED
package/lib/chai/utils/type.js
CHANGED
package/lib/chai.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* chai
|
|
3
|
-
* Copyright(c) 2011-
|
|
3
|
+
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
|
4
4
|
* MIT Licensed
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ var used = []
|
|
|
11
11
|
* Chai version
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
exports.version = '1.
|
|
14
|
+
exports.version = '1.9.1';
|
|
15
15
|
|
|
16
16
|
/*!
|
|
17
17
|
* Assertion Error
|
|
@@ -44,6 +44,13 @@ exports.use = function (fn) {
|
|
|
44
44
|
return this;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
/*!
|
|
48
|
+
* Configuration
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
var config = require('./chai/config');
|
|
52
|
+
exports.config = config;
|
|
53
|
+
|
|
47
54
|
/*!
|
|
48
55
|
* Primary `Assertion` prototype
|
|
49
56
|
*/
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"Veselin Todorov <hi@vesln.com>",
|
|
12
12
|
"John Firebaugh <john.firebaugh@gmail.com>"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.9.1",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "https://github.com/chaijs/chai"
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"assertion-error": "1.0.0"
|
|
31
|
+
, "deep-eql": "0.1.3"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"component": "*"
|
|
34
|
-
, "
|
|
35
|
-
, "mocha": "
|
|
36
|
-
, "
|
|
37
|
-
, "
|
|
38
|
-
, "mocha
|
|
39
|
-
, "
|
|
40
|
-
, "jscoverage": "0.3.7"
|
|
35
|
+
, "karma": "0.12.x"
|
|
36
|
+
, "karma-mocha": "*"
|
|
37
|
+
, "karma-sauce-launcher": "0.2.x"
|
|
38
|
+
, "karma-phantomjs-launcher": "0.1.1"
|
|
39
|
+
, "mocha": "1.17.x"
|
|
40
|
+
, "istanbul": "0.2.x"
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
|
|
2
|
+
/*!
|
|
3
|
+
* Chrome
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
exports['SL_Chrome'] = {
|
|
7
|
+
base: 'SauceLabs'
|
|
8
|
+
, browserName: 'chrome'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/*!
|
|
12
|
+
* Firefox
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/*!
|
|
16
|
+
* TODO: Karma doesn't seem to like this, though sauce boots its up
|
|
17
|
+
*
|
|
18
|
+
|
|
19
|
+
exports['SL_Firefox_23'] = {
|
|
20
|
+
base: 'SauceLabs'
|
|
21
|
+
, browserName: 'firefox'
|
|
22
|
+
, platform: 'Windows XP'
|
|
23
|
+
, version: '23'
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
exports['SL_Firefox_22'] = {
|
|
29
|
+
base: 'SauceLabs'
|
|
30
|
+
, browserName: 'firefox'
|
|
31
|
+
, platform: 'Windows 7'
|
|
32
|
+
, version: '22'
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/*!
|
|
36
|
+
* Opera
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
exports['SL_Opera_12'] = {
|
|
40
|
+
base: 'SauceLabs'
|
|
41
|
+
, browserName: 'opera'
|
|
42
|
+
, platform: 'Windows 7'
|
|
43
|
+
, version: '12'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports['SL_Opera_11'] = {
|
|
47
|
+
base: 'SauceLabs'
|
|
48
|
+
, browserName: 'opera'
|
|
49
|
+
, platform: 'Windows 7'
|
|
50
|
+
, version: '11'
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/*!
|
|
54
|
+
* Internet Explorer
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
exports['SL_IE_10'] = {
|
|
58
|
+
base: 'SauceLabs'
|
|
59
|
+
, browserName: 'internet explorer'
|
|
60
|
+
, platform: 'Windows 2012'
|
|
61
|
+
, version: '10'
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/*!
|
|
65
|
+
* Safari
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
exports['SL_Safari_6'] = {
|
|
69
|
+
base: 'SauceLabs'
|
|
70
|
+
, browserName: 'safari'
|
|
71
|
+
, platform: 'Mac 10.8'
|
|
72
|
+
, version: '6'
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
exports['SL_Safari_5'] = {
|
|
76
|
+
base: 'SauceLabs'
|
|
77
|
+
, browserName: 'safari'
|
|
78
|
+
, platform: 'Mac 10.6'
|
|
79
|
+
, version: '5'
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/*!
|
|
83
|
+
* iPhone
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
/*!
|
|
87
|
+
* TODO: These take forever to boot or shut down. Causes timeout.
|
|
88
|
+
*
|
|
89
|
+
|
|
90
|
+
exports['SL_iPhone_6'] = {
|
|
91
|
+
base: 'SauceLabs'
|
|
92
|
+
, browserName: 'iphone'
|
|
93
|
+
, platform: 'Mac 10.8'
|
|
94
|
+
, version: '6'
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
exports['SL_iPhone_5-1'] = {
|
|
98
|
+
base: 'SauceLabs'
|
|
99
|
+
, browserName: 'iphone'
|
|
100
|
+
, platform: 'Mac 10.8'
|
|
101
|
+
, version: '5.1'
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
exports['SL_iPhone_5'] = {
|
|
105
|
+
base: 'SauceLabs'
|
|
106
|
+
, browserName: 'iphone'
|
|
107
|
+
, platform: 'Mac 10.6'
|
|
108
|
+
, version: '5'
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
/*!
|
|
114
|
+
* Android
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/*!
|
|
118
|
+
* TODO: fails because of error serialization
|
|
119
|
+
*
|
|
120
|
+
|
|
121
|
+
exports['SL_Android_4'] = {
|
|
122
|
+
base: 'SauceLabs'
|
|
123
|
+
, browserName: 'android'
|
|
124
|
+
, platform: 'Linux'
|
|
125
|
+
, version: '4'
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
*/
|
package/lib/chai/utils/eql.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
// This is (almost) directly from Node.js assert
|
|
2
|
-
// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js
|
|
3
|
-
|
|
4
|
-
module.exports = _deepEqual;
|
|
5
|
-
|
|
6
|
-
var getEnumerableProperties = require('./getEnumerableProperties');
|
|
7
|
-
|
|
8
|
-
// for the browser
|
|
9
|
-
var Buffer;
|
|
10
|
-
try {
|
|
11
|
-
Buffer = require('buffer').Buffer;
|
|
12
|
-
} catch (ex) {
|
|
13
|
-
Buffer = {
|
|
14
|
-
isBuffer: function () { return false; }
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function _deepEqual(actual, expected, memos) {
|
|
19
|
-
|
|
20
|
-
// 7.1. All identical values are equivalent, as determined by ===.
|
|
21
|
-
if (actual === expected) {
|
|
22
|
-
return true;
|
|
23
|
-
|
|
24
|
-
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
|
25
|
-
if (actual.length != expected.length) return false;
|
|
26
|
-
|
|
27
|
-
for (var i = 0; i < actual.length; i++) {
|
|
28
|
-
if (actual[i] !== expected[i]) return false;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return true;
|
|
32
|
-
|
|
33
|
-
// 7.2. If the expected value is a Date object, the actual value is
|
|
34
|
-
// equivalent if it is also a Date object that refers to the same time.
|
|
35
|
-
} else if (expected instanceof Date) {
|
|
36
|
-
if (!(actual instanceof Date)) return false;
|
|
37
|
-
return actual.getTime() === expected.getTime();
|
|
38
|
-
|
|
39
|
-
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
|
40
|
-
// equivalence is determined by ==.
|
|
41
|
-
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
42
|
-
return actual === expected;
|
|
43
|
-
|
|
44
|
-
} else if (expected instanceof RegExp) {
|
|
45
|
-
if (!(actual instanceof RegExp)) return false;
|
|
46
|
-
return actual.toString() === expected.toString();
|
|
47
|
-
|
|
48
|
-
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
49
|
-
// determined by having the same number of owned properties (as verified
|
|
50
|
-
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
51
|
-
// (although not necessarily the same order), equivalent values for every
|
|
52
|
-
// corresponding key, and an identical 'prototype' property. Note: this
|
|
53
|
-
// accounts for both named and indexed properties on Arrays.
|
|
54
|
-
} else {
|
|
55
|
-
return objEquiv(actual, expected, memos);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function isUndefinedOrNull(value) {
|
|
60
|
-
return value === null || value === undefined;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function isArguments(object) {
|
|
64
|
-
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function objEquiv(a, b, memos) {
|
|
68
|
-
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
69
|
-
return false;
|
|
70
|
-
|
|
71
|
-
// an identical 'prototype' property.
|
|
72
|
-
if (a.prototype !== b.prototype) return false;
|
|
73
|
-
|
|
74
|
-
// check if we have already compared a and b
|
|
75
|
-
var i;
|
|
76
|
-
if (memos) {
|
|
77
|
-
for(i = 0; i < memos.length; i++) {
|
|
78
|
-
if ((memos[i][0] === a && memos[i][1] === b) ||
|
|
79
|
-
(memos[i][0] === b && memos[i][1] === a))
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
} else {
|
|
83
|
-
memos = [];
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
87
|
-
// Converting to array solves the problem.
|
|
88
|
-
if (isArguments(a)) {
|
|
89
|
-
if (!isArguments(b)) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
a = pSlice.call(a);
|
|
93
|
-
b = pSlice.call(b);
|
|
94
|
-
return _deepEqual(a, b, memos);
|
|
95
|
-
}
|
|
96
|
-
try {
|
|
97
|
-
var ka = getEnumerableProperties(a),
|
|
98
|
-
kb = getEnumerableProperties(b),
|
|
99
|
-
key;
|
|
100
|
-
} catch (e) {//happens when one is a string literal and the other isn't
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// having the same number of owned properties (keys incorporates
|
|
105
|
-
// hasOwnProperty)
|
|
106
|
-
if (ka.length != kb.length)
|
|
107
|
-
return false;
|
|
108
|
-
|
|
109
|
-
//the same set of keys (although not necessarily the same order),
|
|
110
|
-
ka.sort();
|
|
111
|
-
kb.sort();
|
|
112
|
-
//~~~cheap key test
|
|
113
|
-
for (i = ka.length - 1; i >= 0; i--) {
|
|
114
|
-
if (ka[i] != kb[i])
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// remember objects we have compared to guard against circular references
|
|
119
|
-
memos.push([ a, b ]);
|
|
120
|
-
|
|
121
|
-
//equivalent values for every corresponding key, and
|
|
122
|
-
//~~~possibly expensive deep test
|
|
123
|
-
for (i = ka.length - 1; i >= 0; i--) {
|
|
124
|
-
key = ka[i];
|
|
125
|
-
if (!_deepEqual(a[key], b[key], memos)) return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return true;
|
|
129
|
-
}
|