chai 5.0.3 → 5.1.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.
Files changed (38) hide show
  1. package/README.md +3 -3
  2. package/chai.js +94 -220
  3. package/eslint.config.js +12 -0
  4. package/lib/chai/assertion.js +30 -31
  5. package/lib/chai/config.js +18 -24
  6. package/lib/chai/core/assertions.js +253 -223
  7. package/lib/chai/interface/assert.js +574 -670
  8. package/lib/chai/interface/expect.js +12 -7
  9. package/lib/chai/interface/should.js +43 -40
  10. package/lib/chai/utils/addChainableMethod.js +6 -11
  11. package/lib/chai/utils/addLengthGuard.js +3 -3
  12. package/lib/chai/utils/addMethod.js +5 -6
  13. package/lib/chai/utils/addProperty.js +5 -6
  14. package/lib/chai/utils/compareByInspect.js +4 -9
  15. package/lib/chai/utils/expectTypes.js +7 -8
  16. package/lib/chai/utils/flag.js +5 -5
  17. package/lib/chai/utils/getActual.js +3 -3
  18. package/lib/chai/utils/getEnumerableProperties.js +2 -3
  19. package/lib/chai/utils/getMessage.js +4 -8
  20. package/lib/chai/utils/getOperator.js +8 -4
  21. package/lib/chai/utils/getOwnEnumerableProperties.js +2 -7
  22. package/lib/chai/utils/getOwnEnumerablePropertySymbols.js +2 -3
  23. package/lib/chai/utils/getProperties.js +5 -3
  24. package/lib/chai/utils/index.js +42 -109
  25. package/lib/chai/utils/inspect.js +5 -4
  26. package/lib/chai/utils/isNaN.js +3 -3
  27. package/lib/chai/utils/isProxyEnabled.js +1 -1
  28. package/lib/chai/utils/objDisplay.js +2 -7
  29. package/lib/chai/utils/overwriteChainableMethod.js +7 -8
  30. package/lib/chai/utils/overwriteMethod.js +10 -11
  31. package/lib/chai/utils/overwriteProperty.js +10 -12
  32. package/lib/chai/utils/proxify.js +9 -9
  33. package/lib/chai/utils/test.js +3 -7
  34. package/lib/chai/utils/transferFlags.js +4 -6
  35. package/lib/chai/utils/type-detect.js +4 -0
  36. package/lib/chai.js +9 -31
  37. package/package.json +6 -3
  38. package/web-test-runner.config.js +4 -1
@@ -39,7 +39,7 @@ const {flag} = _;
39
39
  *
40
40
  * @name language chains
41
41
  * @namespace BDD
42
- * @api public
42
+ * @public
43
43
  */
44
44
 
45
45
  [ 'to', 'be', 'been', 'is'
@@ -69,7 +69,7 @@ const {flag} = _;
69
69
  *
70
70
  * @name not
71
71
  * @namespace BDD
72
- * @api public
72
+ * @public
73
73
  */
74
74
 
75
75
  Assertion.addProperty('not', function () {
@@ -110,7 +110,7 @@ Assertion.addProperty('not', function () {
110
110
  *
111
111
  * @name deep
112
112
  * @namespace BDD
113
- * @api public
113
+ * @public
114
114
  */
115
115
 
116
116
  Assertion.addProperty('deep', function () {
@@ -136,7 +136,7 @@ Assertion.addProperty('deep', function () {
136
136
  *
137
137
  * @name nested
138
138
  * @namespace BDD
139
- * @api public
139
+ * @public
140
140
  */
141
141
 
142
142
  Assertion.addProperty('nested', function () {
@@ -162,7 +162,7 @@ Assertion.addProperty('nested', function () {
162
162
  *
163
163
  * @name own
164
164
  * @namespace BDD
165
- * @api public
165
+ * @public
166
166
  */
167
167
 
168
168
  Assertion.addProperty('own', function () {
@@ -186,7 +186,7 @@ Assertion.addProperty('own', function () {
186
186
  *
187
187
  * @name ordered
188
188
  * @namespace BDD
189
- * @api public
189
+ * @public
190
190
  */
191
191
 
192
192
  Assertion.addProperty('ordered', function () {
@@ -206,7 +206,7 @@ Assertion.addProperty('ordered', function () {
206
206
  *
207
207
  * @name any
208
208
  * @namespace BDD
209
- * @api public
209
+ * @public
210
210
  */
211
211
 
212
212
  Assertion.addProperty('any', function () {
@@ -231,7 +231,7 @@ Assertion.addProperty('any', function () {
231
231
  *
232
232
  * @name all
233
233
  * @namespace BDD
234
- * @api public
234
+ * @public
235
235
  */
236
236
 
237
237
  Assertion.addProperty('all', function () {
@@ -265,7 +265,7 @@ const functionTypes = {
265
265
  * `.a` supports objects that have a custom type set via `Symbol.toStringTag`.
266
266
  *
267
267
  * var myObj = {
268
- * [Symbol.toStringTag]: 'myCustomType'
268
+ * [Symbol.toStringTag]: 'myCustomType'
269
269
  * };
270
270
  *
271
271
  * expect(myObj).to.be.a('myCustomType').but.not.an('object');
@@ -300,10 +300,10 @@ const functionTypes = {
300
300
  *
301
301
  * @name a
302
302
  * @alias an
303
- * @param {String} type
304
- * @param {String} msg _optional_
303
+ * @param {string} type
304
+ * @param {string} msg _optional_
305
305
  * @namespace BDD
306
- * @api public
306
+ * @public
307
307
  */
308
308
  function an (type, msg) {
309
309
  if (msg) flag(this, 'message', msg);
@@ -331,6 +331,23 @@ function an (type, msg) {
331
331
  Assertion.addChainableMethod('an', an);
332
332
  Assertion.addChainableMethod('a', an);
333
333
 
334
+ /**
335
+ *
336
+ * @param {unknown} a
337
+ * @param {unknown} b
338
+ * @returns {boolean}
339
+ */
340
+ function SameValueZero(a, b) {
341
+ return (_.isNaN(a) && _.isNaN(b)) || a === b;
342
+ }
343
+
344
+ /**
345
+ *
346
+ */
347
+ function includeChainingBehavior () {
348
+ flag(this, 'contains', true);
349
+ }
350
+
334
351
  /**
335
352
  * ### .include(val[, msg])
336
353
  *
@@ -472,20 +489,11 @@ Assertion.addChainableMethod('a', an);
472
489
  * @alias contain
473
490
  * @alias includes
474
491
  * @alias contains
475
- * @param {Mixed} val
476
- * @param {String} msg _optional_
492
+ * @param {unknown} val
493
+ * @param {string} msg _optional_
477
494
  * @namespace BDD
478
- * @api public
495
+ * @public
479
496
  */
480
-
481
- function SameValueZero(a, b) {
482
- return (_.isNaN(a) && _.isNaN(b)) || a === b;
483
- }
484
-
485
- function includeChainingBehavior () {
486
- flag(this, 'contains', true);
487
- }
488
-
489
497
  function include (val, msg) {
490
498
  if (msg) flag(this, 'message', msg);
491
499
 
@@ -643,9 +651,8 @@ Assertion.addChainableMethod('includes', include, includeChainingBehavior);
643
651
  *
644
652
  * @name ok
645
653
  * @namespace BDD
646
- * @api public
654
+ * @public
647
655
  */
648
-
649
656
  Assertion.addProperty('ok', function () {
650
657
  this.assert(
651
658
  flag(this, 'object')
@@ -676,9 +683,8 @@ Assertion.addProperty('ok', function () {
676
683
  *
677
684
  * @name true
678
685
  * @namespace BDD
679
- * @api public
686
+ * @public
680
687
  */
681
-
682
688
  Assertion.addProperty('true', function () {
683
689
  this.assert(
684
690
  true === flag(this, 'object')
@@ -701,7 +707,7 @@ Assertion.addProperty('true', function () {
701
707
  *
702
708
  * @name callable
703
709
  * @namespace BDD
704
- * @api public
710
+ * @public
705
711
  */
706
712
  Assertion.addProperty('callable', function () {
707
713
  const val = flag(this, 'object')
@@ -748,9 +754,8 @@ Assertion.addProperty('callable', function () {
748
754
  *
749
755
  * @name false
750
756
  * @namespace BDD
751
- * @api public
757
+ * @public
752
758
  */
753
-
754
759
  Assertion.addProperty('false', function () {
755
760
  this.assert(
756
761
  false === flag(this, 'object')
@@ -780,9 +785,8 @@ Assertion.addProperty('false', function () {
780
785
  *
781
786
  * @name null
782
787
  * @namespace BDD
783
- * @api public
788
+ * @public
784
789
  */
785
-
786
790
  Assertion.addProperty('null', function () {
787
791
  this.assert(
788
792
  null === flag(this, 'object')
@@ -811,9 +815,8 @@ Assertion.addProperty('null', function () {
811
815
  *
812
816
  * @name undefined
813
817
  * @namespace BDD
814
- * @api public
818
+ * @public
815
819
  */
816
-
817
820
  Assertion.addProperty('undefined', function () {
818
821
  this.assert(
819
822
  undefined === flag(this, 'object')
@@ -842,9 +845,8 @@ Assertion.addProperty('undefined', function () {
842
845
  *
843
846
  * @name NaN
844
847
  * @namespace BDD
845
- * @api public
848
+ * @public
846
849
  */
847
-
848
850
  Assertion.addProperty('NaN', function () {
849
851
  this.assert(
850
852
  _.isNaN(flag(this, 'object'))
@@ -883,9 +885,8 @@ Assertion.addProperty('NaN', function () {
883
885
  * @name exist
884
886
  * @alias exists
885
887
  * @namespace BDD
886
- * @api public
888
+ * @public
887
889
  */
888
-
889
890
  function assertExist () {
890
891
  var val = flag(this, 'object');
891
892
  this.assert(
@@ -944,9 +945,8 @@ Assertion.addProperty('exists', assertExist);
944
945
  *
945
946
  * @name empty
946
947
  * @namespace BDD
947
- * @api public
948
+ * @public
948
949
  */
949
-
950
950
  Assertion.addProperty('empty', function () {
951
951
  var val = flag(this, 'object')
952
952
  , ssfi = flag(this, 'ssfi')
@@ -998,7 +998,7 @@ Assertion.addProperty('empty', function () {
998
998
  * Asserts that the target is an `arguments` object.
999
999
  *
1000
1000
  * function test () {
1001
- * expect(arguments).to.be.arguments;
1001
+ * expect(arguments).to.be.arguments;
1002
1002
  * }
1003
1003
  *
1004
1004
  * test();
@@ -1019,9 +1019,8 @@ Assertion.addProperty('empty', function () {
1019
1019
  * @name arguments
1020
1020
  * @alias Arguments
1021
1021
  * @namespace BDD
1022
- * @api public
1022
+ * @public
1023
1023
  */
1024
-
1025
1024
  function checkArguments () {
1026
1025
  var obj = flag(this, 'object')
1027
1026
  , type = _.type(obj);
@@ -1074,12 +1073,11 @@ Assertion.addProperty('Arguments', checkArguments);
1074
1073
  * @name equal
1075
1074
  * @alias equals
1076
1075
  * @alias eq
1077
- * @param {Mixed} val
1078
- * @param {String} msg _optional_
1076
+ * @param {unknown} val
1077
+ * @param {string} msg _optional_
1079
1078
  * @namespace BDD
1080
- * @api public
1079
+ * @public
1081
1080
  */
1082
-
1083
1081
  function assertEqual (val, msg) {
1084
1082
  if (msg) flag(this, 'message', msg);
1085
1083
  var obj = flag(this, 'object');
@@ -1139,12 +1137,11 @@ Assertion.addMethod('eq', assertEqual);
1139
1137
  *
1140
1138
  * @name eql
1141
1139
  * @alias eqls
1142
- * @param {Mixed} obj
1143
- * @param {String} msg _optional_
1140
+ * @param {unknown} obj
1141
+ * @param {string} msg _optional_
1144
1142
  * @namespace BDD
1145
- * @api public
1143
+ * @public
1146
1144
  */
1147
-
1148
1145
  function assertEql(obj, msg) {
1149
1146
  if (msg) flag(this, 'message', msg);
1150
1147
  var eql = flag(this, 'eql');
@@ -1198,12 +1195,11 @@ Assertion.addMethod('eqls', assertEql);
1198
1195
  * @name above
1199
1196
  * @alias gt
1200
1197
  * @alias greaterThan
1201
- * @param {Number} n
1202
- * @param {String} msg _optional_
1198
+ * @param {number} n
1199
+ * @param {string} msg _optional_
1203
1200
  * @namespace BDD
1204
- * @api public
1201
+ * @public
1205
1202
  */
1206
-
1207
1203
  function assertAbove (n, msg) {
1208
1204
  if (msg) flag(this, 'message', msg);
1209
1205
  var obj = flag(this, 'object')
@@ -1303,12 +1299,11 @@ Assertion.addMethod('greaterThan', assertAbove);
1303
1299
  * @name least
1304
1300
  * @alias gte
1305
1301
  * @alias greaterThanOrEqual
1306
- * @param {Number} n
1307
- * @param {String} msg _optional_
1302
+ * @param {number} n
1303
+ * @param {string} msg _optional_
1308
1304
  * @namespace BDD
1309
- * @api public
1305
+ * @public
1310
1306
  */
1311
-
1312
1307
  function assertLeast (n, msg) {
1313
1308
  if (msg) flag(this, 'message', msg);
1314
1309
  var obj = flag(this, 'object')
@@ -1407,12 +1402,11 @@ Assertion.addMethod('greaterThanOrEqual', assertLeast);
1407
1402
  * @name below
1408
1403
  * @alias lt
1409
1404
  * @alias lessThan
1410
- * @param {Number} n
1411
- * @param {String} msg _optional_
1405
+ * @param {number} n
1406
+ * @param {string} msg _optional_
1412
1407
  * @namespace BDD
1413
- * @api public
1408
+ * @public
1414
1409
  */
1415
-
1416
1410
  function assertBelow (n, msg) {
1417
1411
  if (msg) flag(this, 'message', msg);
1418
1412
  var obj = flag(this, 'object')
@@ -1512,12 +1506,11 @@ Assertion.addMethod('lessThan', assertBelow);
1512
1506
  * @name most
1513
1507
  * @alias lte
1514
1508
  * @alias lessThanOrEqual
1515
- * @param {Number} n
1516
- * @param {String} msg _optional_
1509
+ * @param {number} n
1510
+ * @param {string} msg _optional_
1517
1511
  * @namespace BDD
1518
- * @api public
1512
+ * @public
1519
1513
  */
1520
-
1521
1514
  function assertMost (n, msg) {
1522
1515
  if (msg) flag(this, 'message', msg);
1523
1516
  var obj = flag(this, 'object')
@@ -1615,13 +1608,12 @@ Assertion.addMethod('lessThanOrEqual', assertMost);
1615
1608
  * expect(4, 'nooo why fail??').to.be.within(1, 3);
1616
1609
  *
1617
1610
  * @name within
1618
- * @param {Number} start lower bound inclusive
1619
- * @param {Number} finish upper bound inclusive
1620
- * @param {String} msg _optional_
1611
+ * @param {number} start lower bound inclusive
1612
+ * @param {number} finish upper bound inclusive
1613
+ * @param {string} msg _optional_
1621
1614
  * @namespace BDD
1622
- * @api public
1615
+ * @public
1623
1616
  */
1624
-
1625
1617
  Assertion.addMethod('within', function (start, finish, msg) {
1626
1618
  if (msg) flag(this, 'message', msg);
1627
1619
  var obj = flag(this, 'object')
@@ -1712,13 +1704,12 @@ Assertion.addMethod('within', function (start, finish, msg) {
1712
1704
  * The alias `.instanceOf` can be used interchangeably with `.instanceof`.
1713
1705
  *
1714
1706
  * @name instanceof
1715
- * @param {Constructor} constructor
1716
- * @param {String} msg _optional_
1707
+ * @param {unknown} constructor
1708
+ * @param {string} msg _optional_
1717
1709
  * @alias instanceOf
1718
1710
  * @namespace BDD
1719
- * @api public
1711
+ * @public
1720
1712
  */
1721
-
1722
1713
  function assertInstanceOf (constructor, msg) {
1723
1714
  if (msg) flag(this, 'message', msg);
1724
1715
 
@@ -1860,14 +1851,12 @@ Assertion.addMethod('instanceOf', assertInstanceOf);
1860
1851
  * interchangeably with `.own.property`.
1861
1852
  *
1862
1853
  * @name property
1863
- * @param {String} name
1864
- * @param {Mixed} val (optional)
1865
- * @param {String} msg _optional_
1866
- * @returns value of property for chaining
1854
+ * @param {string} name
1855
+ * @param {unknown} val (optional)
1856
+ * @param {string} msg _optional_
1867
1857
  * @namespace BDD
1868
- * @api public
1858
+ * @public
1869
1859
  */
1870
-
1871
1860
  function assertProperty (name, val, msg) {
1872
1861
  if (msg) flag(this, 'message', msg);
1873
1862
 
@@ -1958,6 +1947,12 @@ function assertProperty (name, val, msg) {
1958
1947
 
1959
1948
  Assertion.addMethod('property', assertProperty);
1960
1949
 
1950
+ /**
1951
+ *
1952
+ * @param {unknown} name
1953
+ * @param {unknown} value
1954
+ * @param {string} msg
1955
+ */
1961
1956
  function assertOwnProperty (name, value, msg) {
1962
1957
  flag(this, 'own', true);
1963
1958
  assertProperty.apply(this, arguments);
@@ -1981,10 +1976,10 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
1981
1976
  * https://github.com/chaijs/deep-eql.
1982
1977
  *
1983
1978
  * expect({a: 1}).to.have.ownPropertyDescriptor('a', {
1984
- * configurable: true,
1985
- * enumerable: true,
1986
- * writable: true,
1987
- * value: 1,
1979
+ * configurable: true,
1980
+ * enumerable: true,
1981
+ * writable: true,
1982
+ * value: 1,
1988
1983
  * });
1989
1984
  *
1990
1985
  * Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`.
@@ -2007,10 +2002,10 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
2007
2002
  *
2008
2003
  * // Not recommended
2009
2004
  * expect({b: 2}).to.not.have.ownPropertyDescriptor('a', {
2010
- * configurable: true,
2011
- * enumerable: true,
2012
- * writable: true,
2013
- * value: 1,
2005
+ * configurable: true,
2006
+ * enumerable: true,
2007
+ * writable: true,
2008
+ * value: 1,
2014
2009
  * });
2015
2010
  *
2016
2011
  * When the target is expected to have a property descriptor with the given
@@ -2020,18 +2015,18 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
2020
2015
  *
2021
2016
  * // Recommended
2022
2017
  * expect({a: 3}).to.have.ownPropertyDescriptor('a', {
2023
- * configurable: true,
2024
- * enumerable: true,
2025
- * writable: true,
2026
- * value: 3,
2018
+ * configurable: true,
2019
+ * enumerable: true,
2020
+ * writable: true,
2021
+ * value: 3,
2027
2022
  * });
2028
2023
  *
2029
2024
  * // Not recommended
2030
2025
  * expect({a: 3}).to.not.have.ownPropertyDescriptor('a', {
2031
- * configurable: true,
2032
- * enumerable: true,
2033
- * writable: true,
2034
- * value: 1,
2026
+ * configurable: true,
2027
+ * enumerable: true,
2028
+ * writable: true,
2029
+ * value: 1,
2035
2030
  * });
2036
2031
  *
2037
2032
  * `.ownPropertyDescriptor` changes the target of any assertions that follow
@@ -2048,18 +2043,18 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
2048
2043
  *
2049
2044
  * // Recommended
2050
2045
  * expect({a: 1}).to.have.ownPropertyDescriptor('a', {
2051
- * configurable: true,
2052
- * enumerable: true,
2053
- * writable: true,
2054
- * value: 2,
2046
+ * configurable: true,
2047
+ * enumerable: true,
2048
+ * writable: true,
2049
+ * value: 2,
2055
2050
  * }, 'nooo why fail??');
2056
2051
  *
2057
2052
  * // Recommended
2058
2053
  * expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', {
2059
- * configurable: true,
2060
- * enumerable: true,
2061
- * writable: true,
2062
- * value: 2,
2054
+ * configurable: true,
2055
+ * enumerable: true,
2056
+ * writable: true,
2057
+ * value: 2,
2063
2058
  * });
2064
2059
  *
2065
2060
  * // Recommended
@@ -2078,13 +2073,12 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
2078
2073
  *
2079
2074
  * @name ownPropertyDescriptor
2080
2075
  * @alias haveOwnPropertyDescriptor
2081
- * @param {String} name
2082
- * @param {Object} descriptor _optional_
2083
- * @param {String} msg _optional_
2076
+ * @param {string} name
2077
+ * @param {object} descriptor _optional_
2078
+ * @param {string} msg _optional_
2084
2079
  * @namespace BDD
2085
- * @api public
2080
+ * @public
2086
2081
  */
2087
-
2088
2082
  function assertOwnPropertyDescriptor (name, descriptor, msg) {
2089
2083
  if (typeof descriptor === 'string') {
2090
2084
  msg = descriptor;
@@ -2116,6 +2110,13 @@ function assertOwnPropertyDescriptor (name, descriptor, msg) {
2116
2110
  Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
2117
2111
  Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
2118
2112
 
2113
+ /**
2114
+ *
2115
+ */
2116
+ function assertLengthChain () {
2117
+ flag(this, 'doLength', true);
2118
+ }
2119
+
2119
2120
  /**
2120
2121
  * ### .lengthOf(n[, msg])
2121
2122
  *
@@ -2168,16 +2169,11 @@ Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
2168
2169
  *
2169
2170
  * @name lengthOf
2170
2171
  * @alias length
2171
- * @param {Number} n
2172
- * @param {String} msg _optional_
2172
+ * @param {number} n
2173
+ * @param {string} msg _optional_
2173
2174
  * @namespace BDD
2174
- * @api public
2175
+ * @public
2175
2176
  */
2176
-
2177
- function assertLengthChain () {
2178
- flag(this, 'doLength', true);
2179
- }
2180
-
2181
2177
  function assertLength (n, msg) {
2182
2178
  if (msg) flag(this, 'message', msg);
2183
2179
  var obj = flag(this, 'object')
@@ -2233,9 +2229,9 @@ Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);
2233
2229
  * @name match
2234
2230
  * @alias matches
2235
2231
  * @param {RegExp} re
2236
- * @param {String} msg _optional_
2232
+ * @param {string} msg _optional_
2237
2233
  * @namespace BDD
2238
- * @api public
2234
+ * @public
2239
2235
  */
2240
2236
  function assertMatch(re, msg) {
2241
2237
  if (msg) flag(this, 'message', msg);
@@ -2269,12 +2265,11 @@ Assertion.addMethod('matches', assertMatch);
2269
2265
  * expect('foobar', 'nooo why fail??').to.have.string('taco');
2270
2266
  *
2271
2267
  * @name string
2272
- * @param {String} str
2273
- * @param {String} msg _optional_
2268
+ * @param {string} str
2269
+ * @param {string} msg _optional_
2274
2270
  * @namespace BDD
2275
- * @api public
2271
+ * @public
2276
2272
  */
2277
-
2278
2273
  Assertion.addMethod('string', function (str, msg) {
2279
2274
  if (msg) flag(this, 'message', msg);
2280
2275
  var obj = flag(this, 'object')
@@ -2388,11 +2383,10 @@ Assertion.addMethod('string', function (str, msg) {
2388
2383
  *
2389
2384
  * @name keys
2390
2385
  * @alias key
2391
- * @param {...String|Array|Object} keys
2386
+ * @param {...string | Array | object} keys
2392
2387
  * @namespace BDD
2393
- * @api public
2388
+ * @public
2394
2389
  */
2395
-
2396
2390
  function assertKeys (keys) {
2397
2391
  var obj = flag(this, 'object')
2398
2392
  , objType = _.type(obj)
@@ -2522,7 +2516,6 @@ Assertion.addMethod('key', assertKeys);
2522
2516
  * asserts that an error is thrown.
2523
2517
  *
2524
2518
  * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2525
- *
2526
2519
  * expect(badFn).to.throw();
2527
2520
  *
2528
2521
  * When one argument is provided, and it's an error constructor, `.throw`
@@ -2530,7 +2523,6 @@ Assertion.addMethod('key', assertKeys);
2530
2523
  * instance of that error constructor.
2531
2524
  *
2532
2525
  * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2533
- *
2534
2526
  * expect(badFn).to.throw(TypeError);
2535
2527
  *
2536
2528
  * When one argument is provided, and it's an error instance, `.throw` invokes
@@ -2547,7 +2539,6 @@ Assertion.addMethod('key', assertKeys);
2547
2539
  * contains that string.
2548
2540
  *
2549
2541
  * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2550
- *
2551
2542
  * expect(badFn).to.throw('salmon');
2552
2543
  *
2553
2544
  * When one argument is provided, and it's a regular expression, `.throw`
@@ -2555,7 +2546,6 @@ Assertion.addMethod('key', assertKeys);
2555
2546
  * message that matches that regular expression.
2556
2547
  *
2557
2548
  * var badFn = function () { throw new TypeError('Illegal salmon!'); };
2558
- *
2559
2549
  * expect(badFn).to.throw(/salmon/);
2560
2550
  *
2561
2551
  * When two arguments are provided, and the first is an error instance or
@@ -2574,7 +2564,6 @@ Assertion.addMethod('key', assertKeys);
2574
2564
  * Add `.not` earlier in the chain to negate `.throw`.
2575
2565
  *
2576
2566
  * var goodFn = function () {};
2577
- *
2578
2567
  * expect(goodFn).to.not.throw();
2579
2568
  *
2580
2569
  * However, it's dangerous to negate `.throw` when providing any arguments.
@@ -2671,15 +2660,14 @@ Assertion.addMethod('key', assertKeys);
2671
2660
  * @name throw
2672
2661
  * @alias throws
2673
2662
  * @alias Throw
2674
- * @param {Error|ErrorConstructor} errorLike
2675
- * @param {String|RegExp} errMsgMatcher error message
2676
- * @param {String} msg _optional_
2663
+ * @param {Error} errorLike
2664
+ * @param {string | RegExp} errMsgMatcher error message
2665
+ * @param {string} msg _optional_
2677
2666
  * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
2678
- * @returns error for chaining (null if no error)
2667
+ * @returns {void} error for chaining (null if no error)
2679
2668
  * @namespace BDD
2680
- * @api public
2669
+ * @public
2681
2670
  */
2682
-
2683
2671
  function assertThrows (errorLike, errMsgMatcher, msg) {
2684
2672
  if (msg) flag(this, 'message', msg);
2685
2673
  var obj = flag(this, 'object')
@@ -2688,15 +2676,17 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
2688
2676
  , negate = flag(this, 'negate') || false;
2689
2677
  new Assertion(obj, flagMsg, ssfi, true).is.a('function');
2690
2678
 
2691
- if (errorLike instanceof RegExp || typeof errorLike === 'string') {
2679
+ if (_.isRegExp(errorLike) || typeof errorLike === 'string') {
2692
2680
  errMsgMatcher = errorLike;
2693
2681
  errorLike = null;
2694
2682
  }
2695
2683
 
2696
- var caughtErr;
2684
+ let caughtErr;
2685
+ let errorWasThrown = false;
2697
2686
  try {
2698
2687
  obj();
2699
2688
  } catch (err) {
2689
+ errorWasThrown = true;
2700
2690
  caughtErr = err;
2701
2691
  }
2702
2692
 
@@ -2720,14 +2710,26 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
2720
2710
  errorLikeString = _.checkError.getConstructorName(errorLike);
2721
2711
  }
2722
2712
 
2713
+ let actual = caughtErr;
2714
+ if (caughtErr instanceof Error) {
2715
+ actual = caughtErr.toString();
2716
+ } else if (typeof caughtErr === 'string') {
2717
+ actual = caughtErr;
2718
+ } else if (caughtErr && (typeof caughtErr === 'object' || typeof caughtErr === 'function')) {
2719
+ try {
2720
+ actual = _.checkError.getConstructorName(caughtErr);
2721
+ } catch (_err) {
2722
+ // somehow wasn't a constructor, maybe we got a function thrown
2723
+ // or similar
2724
+ }
2725
+ }
2726
+
2723
2727
  this.assert(
2724
- caughtErr
2728
+ errorWasThrown
2725
2729
  , 'expected #{this} to throw ' + errorLikeString
2726
2730
  , 'expected #{this} to not throw an error but #{act} was thrown'
2727
2731
  , errorLike && errorLike.toString()
2728
- , (caughtErr instanceof Error ?
2729
- caughtErr.toString() : (typeof caughtErr === 'string' ? caughtErr : caughtErr &&
2730
- _.checkError.getConstructorName(caughtErr)))
2732
+ , actual
2731
2733
  );
2732
2734
  }
2733
2735
 
@@ -2772,7 +2774,7 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
2772
2774
  if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) {
2773
2775
  // Here we check compatible messages
2774
2776
  var placeholder = 'including';
2775
- if (errMsgMatcher instanceof RegExp) {
2777
+ if (_.isRegExp(errMsgMatcher)) {
2776
2778
  placeholder = 'matching'
2777
2779
  }
2778
2780
 
@@ -2869,12 +2871,11 @@ Assertion.addMethod('Throw', assertThrows);
2869
2871
  *
2870
2872
  * @name respondTo
2871
2873
  * @alias respondsTo
2872
- * @param {String} method
2873
- * @param {String} msg _optional_
2874
+ * @param {string} method
2875
+ * @param {string} msg _optional_
2874
2876
  * @namespace BDD
2875
- * @api public
2877
+ * @public
2876
2878
  */
2877
-
2878
2879
  function respondTo (method, msg) {
2879
2880
  if (msg) flag(this, 'message', msg);
2880
2881
  var obj = flag(this, 'object')
@@ -2910,9 +2911,8 @@ Assertion.addMethod('respondsTo', respondTo);
2910
2911
  *
2911
2912
  * @name itself
2912
2913
  * @namespace BDD
2913
- * @api public
2914
+ * @public
2914
2915
  */
2915
-
2916
2916
  Assertion.addProperty('itself', function () {
2917
2917
  flag(this, 'itself', true);
2918
2918
  });
@@ -2924,13 +2924,13 @@ Assertion.addProperty('itself', function () {
2924
2924
  * first argument, and asserts that the value returned is truthy.
2925
2925
  *
2926
2926
  * expect(1).to.satisfy(function(num) {
2927
- * return num > 0;
2927
+ * return num > 0;
2928
2928
  * });
2929
2929
  *
2930
2930
  * Add `.not` earlier in the chain to negate `.satisfy`.
2931
2931
  *
2932
2932
  * expect(1).to.not.satisfy(function(num) {
2933
- * return num > 2;
2933
+ * return num > 2;
2934
2934
  * });
2935
2935
  *
2936
2936
  * `.satisfy` accepts an optional `msg` argument which is a custom error
@@ -2938,11 +2938,11 @@ Assertion.addProperty('itself', function () {
2938
2938
  * the second argument to `expect`.
2939
2939
  *
2940
2940
  * expect(1).to.satisfy(function(num) {
2941
- * return num > 2;
2941
+ * return num > 2;
2942
2942
  * }, 'nooo why fail??');
2943
2943
  *
2944
2944
  * expect(1, 'nooo why fail??').to.satisfy(function(num) {
2945
- * return num > 2;
2945
+ * return num > 2;
2946
2946
  * });
2947
2947
  *
2948
2948
  * The alias `.satisfies` can be used interchangeably with `.satisfy`.
@@ -2950,11 +2950,10 @@ Assertion.addProperty('itself', function () {
2950
2950
  * @name satisfy
2951
2951
  * @alias satisfies
2952
2952
  * @param {Function} matcher
2953
- * @param {String} msg _optional_
2953
+ * @param {string} msg _optional_
2954
2954
  * @namespace BDD
2955
- * @api public
2955
+ * @public
2956
2956
  */
2957
-
2958
2957
  function satisfy (matcher, msg) {
2959
2958
  if (msg) flag(this, 'message', msg);
2960
2959
  var obj = flag(this, 'object');
@@ -3002,13 +3001,12 @@ Assertion.addMethod('satisfies', satisfy);
3002
3001
  *
3003
3002
  * @name closeTo
3004
3003
  * @alias approximately
3005
- * @param {Number} expected
3006
- * @param {Number} delta
3007
- * @param {String} msg _optional_
3004
+ * @param {number} expected
3005
+ * @param {number} delta
3006
+ * @param {string} msg _optional_
3008
3007
  * @namespace BDD
3009
- * @api public
3008
+ * @public
3010
3009
  */
3011
-
3012
3010
  function closeTo(expected, delta, msg) {
3013
3011
  if (msg) flag(this, 'message', msg);
3014
3012
  var obj = flag(this, 'object')
@@ -3036,8 +3034,17 @@ function closeTo(expected, delta, msg) {
3036
3034
  Assertion.addMethod('closeTo', closeTo);
3037
3035
  Assertion.addMethod('approximately', closeTo);
3038
3036
 
3039
- // Note: Duplicates are ignored if testing for inclusion instead of sameness.
3040
- function isSubsetOf(subset, superset, cmp, contains, ordered) {
3037
+ /**
3038
+ * @param {unknown} _subset
3039
+ * @param {unknown} _superset
3040
+ * @param {unknown} cmp
3041
+ * @param {unknown} contains
3042
+ * @param {unknown} ordered
3043
+ * @returns {boolean}
3044
+ */
3045
+ function isSubsetOf(_subset, _superset, cmp, contains, ordered) {
3046
+ let superset = Array.from(_superset);
3047
+ let subset = Array.from(_subset);
3041
3048
  if (!contains) {
3042
3049
  if (subset.length !== superset.length) return false;
3043
3050
  superset = superset.slice();
@@ -3129,19 +3136,18 @@ function isSubsetOf(subset, superset, cmp, contains, ordered) {
3129
3136
  *
3130
3137
  * @name members
3131
3138
  * @param {Array} set
3132
- * @param {String} msg _optional_
3139
+ * @param {string} msg _optional_
3133
3140
  * @namespace BDD
3134
- * @api public
3141
+ * @public
3135
3142
  */
3136
-
3137
3143
  Assertion.addMethod('members', function (subset, msg) {
3138
3144
  if (msg) flag(this, 'message', msg);
3139
3145
  var obj = flag(this, 'object')
3140
3146
  , flagMsg = flag(this, 'message')
3141
3147
  , ssfi = flag(this, 'ssfi');
3142
3148
 
3143
- new Assertion(obj, flagMsg, ssfi, true).to.be.an('array');
3144
- new Assertion(subset, flagMsg, ssfi, true).to.be.an('array');
3149
+ new Assertion(obj, flagMsg, ssfi, true).to.be.iterable;
3150
+ new Assertion(subset, flagMsg, ssfi, true).to.be.iterable;
3145
3151
 
3146
3152
  var contains = flag(this, 'contains');
3147
3153
  var ordered = flag(this, 'ordered');
@@ -3170,6 +3176,39 @@ Assertion.addMethod('members', function (subset, msg) {
3170
3176
  );
3171
3177
  });
3172
3178
 
3179
+ /**
3180
+ * ### .iterable
3181
+ *
3182
+ * Asserts that the target is an iterable, which means that it has a iterator.
3183
+ *
3184
+ * expect([1, 2]).to.be.iterable;
3185
+ * expect("foobar").to.be.iterable;
3186
+ *
3187
+ * Add `.not` earlier in the chain to negate `.iterable`.
3188
+ *
3189
+ * expect(1).to.not.be.iterable;
3190
+ * expect(true).to.not.be.iterable;
3191
+ *
3192
+ * A custom error message can be given as the second argument to `expect`.
3193
+ *
3194
+ * expect(1, 'nooo why fail??').to.be.iterable;
3195
+ *
3196
+ * @name iterable
3197
+ * @namespace BDD
3198
+ * @public
3199
+ */
3200
+ Assertion.addProperty('iterable', function(msg) {
3201
+ if (msg) flag(this, 'message', msg);
3202
+ var obj = flag(this, 'object');
3203
+
3204
+ this.assert(
3205
+ obj != undefined && obj[Symbol.iterator]
3206
+ , 'expected #{this} to be an iterable'
3207
+ , 'expected #{this} to not be an iterable'
3208
+ , obj
3209
+ );
3210
+ });
3211
+
3173
3212
  /**
3174
3213
  * ### .oneOf(list[, msg])
3175
3214
  *
@@ -3203,11 +3242,10 @@ Assertion.addMethod('members', function (subset, msg) {
3203
3242
  *
3204
3243
  * @name oneOf
3205
3244
  * @param {Array<*>} list
3206
- * @param {String} msg _optional_
3245
+ * @param {string} msg _optional_
3207
3246
  * @namespace BDD
3208
- * @api public
3247
+ * @public
3209
3248
  */
3210
-
3211
3249
  function oneOf (list, msg) {
3212
3250
  if (msg) flag(this, 'message', msg);
3213
3251
  var expected = flag(this, 'object')
@@ -3258,8 +3296,8 @@ Assertion.addMethod('oneOf', oneOf);
3258
3296
  * to assert that `subject` is equal to its expected value.
3259
3297
  *
3260
3298
  * var dots = ''
3261
- * , addDot = function () { dots += '.'; }
3262
- * , getDots = function () { return dots; };
3299
+ * , addDot = function () { dots += '.'; }
3300
+ * , getDots = function () { return dots; };
3263
3301
  *
3264
3302
  * // Recommended
3265
3303
  * expect(getDots()).to.equal('');
@@ -3274,7 +3312,7 @@ Assertion.addMethod('oneOf', oneOf);
3274
3312
  * target function compared to afterward.
3275
3313
  *
3276
3314
  * var myObj = {dots: ''}
3277
- * , addDot = function () { myObj.dots += '.'; };
3315
+ * , addDot = function () { myObj.dots += '.'; };
3278
3316
  *
3279
3317
  * // Recommended
3280
3318
  * expect(myObj).to.have.property('dots', '');
@@ -3289,13 +3327,13 @@ Assertion.addMethod('oneOf', oneOf);
3289
3327
  * Add `.not` earlier in the chain to negate `.change`.
3290
3328
  *
3291
3329
  * var dots = ''
3292
- * , noop = function () {}
3293
- * , getDots = function () { return dots; };
3330
+ * , noop = function () {}
3331
+ * , getDots = function () { return dots; };
3294
3332
  *
3295
3333
  * expect(noop).to.not.change(getDots);
3296
3334
  *
3297
3335
  * var myObj = {dots: ''}
3298
- * , noop = function () {};
3336
+ * , noop = function () {};
3299
3337
  *
3300
3338
  * expect(noop).to.not.change(myObj, 'dots');
3301
3339
  *
@@ -3305,13 +3343,13 @@ Assertion.addMethod('oneOf', oneOf);
3305
3343
  * use the second form.
3306
3344
  *
3307
3345
  * var myObj = {dots: ''}
3308
- * , addDot = function () { myObj.dots += '.'; };
3346
+ * , addDot = function () { myObj.dots += '.'; };
3309
3347
  *
3310
3348
  * expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??');
3311
3349
  *
3312
3350
  * var dots = ''
3313
- * , addDot = function () { dots += '.'; }
3314
- * , getDots = function () { return dots; };
3351
+ * , addDot = function () { dots += '.'; }
3352
+ * , getDots = function () { return dots; };
3315
3353
  *
3316
3354
  * expect(addDot, 'nooo why fail??').to.not.change(getDots);
3317
3355
  *
@@ -3324,8 +3362,8 @@ Assertion.addMethod('oneOf', oneOf);
3324
3362
  * that only accepts that exact output.
3325
3363
  *
3326
3364
  * var myObj = {val: 1}
3327
- * , addTwo = function () { myObj.val += 2; }
3328
- * , subtractTwo = function () { myObj.val -= 2; };
3365
+ * , addTwo = function () { myObj.val += 2; }
3366
+ * , subtractTwo = function () { myObj.val -= 2; };
3329
3367
  *
3330
3368
  * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3331
3369
  * expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended
@@ -3337,13 +3375,12 @@ Assertion.addMethod('oneOf', oneOf);
3337
3375
  *
3338
3376
  * @name change
3339
3377
  * @alias changes
3340
- * @param {String} subject
3341
- * @param {String} prop name _optional_
3342
- * @param {String} msg _optional_
3378
+ * @param {string} subject
3379
+ * @param {string} prop name _optional_
3380
+ * @param {string} msg _optional_
3343
3381
  * @namespace BDD
3344
- * @api public
3382
+ * @public
3345
3383
  */
3346
-
3347
3384
  function assertChanges (subject, prop, msg) {
3348
3385
  if (msg) flag(this, 'message', msg);
3349
3386
  var fn = flag(this, 'object')
@@ -3394,8 +3431,8 @@ Assertion.addMethod('changes', assertChanges);
3394
3431
  * by any amount.
3395
3432
  *
3396
3433
  * var val = 1
3397
- * , addTwo = function () { val += 2; }
3398
- * , getVal = function () { return val; };
3434
+ * , addTwo = function () { val += 2; }
3435
+ * , getVal = function () { return val; };
3399
3436
  *
3400
3437
  * expect(addTwo).to.increase(getVal).by(2); // Recommended
3401
3438
  * expect(addTwo).to.increase(getVal); // Not recommended
@@ -3405,7 +3442,7 @@ Assertion.addMethod('changes', assertChanges);
3405
3442
  * target function compared to beforehand.
3406
3443
  *
3407
3444
  * var myObj = {val: 1}
3408
- * , addTwo = function () { myObj.val += 2; };
3445
+ * , addTwo = function () { myObj.val += 2; };
3409
3446
  *
3410
3447
  * expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
3411
3448
  * expect(addTwo).to.increase(myObj, 'val'); // Not recommended
@@ -3420,7 +3457,7 @@ Assertion.addMethod('changes', assertChanges);
3420
3457
  * decreased by the expected amount.
3421
3458
  *
3422
3459
  * var myObj = {val: 1}
3423
- * , subtractTwo = function () { myObj.val -= 2; };
3460
+ * , subtractTwo = function () { myObj.val -= 2; };
3424
3461
  *
3425
3462
  * expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
3426
3463
  * expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended
@@ -3429,7 +3466,7 @@ Assertion.addMethod('changes', assertChanges);
3429
3466
  * exactly that.
3430
3467
  *
3431
3468
  * var myObj = {val: 1}
3432
- * , noop = function () {};
3469
+ * , noop = function () {};
3433
3470
  *
3434
3471
  * expect(noop).to.not.change(myObj, 'val'); // Recommended
3435
3472
  * expect(noop).to.not.increase(myObj, 'val'); // Not recommended
@@ -3440,13 +3477,13 @@ Assertion.addMethod('changes', assertChanges);
3440
3477
  * use the second form.
3441
3478
  *
3442
3479
  * var myObj = {val: 1}
3443
- * , noop = function () {};
3480
+ * , noop = function () {};
3444
3481
  *
3445
3482
  * expect(noop).to.increase(myObj, 'val', 'nooo why fail??');
3446
3483
  *
3447
3484
  * var val = 1
3448
- * , noop = function () {}
3449
- * , getVal = function () { return val; };
3485
+ * , noop = function () {}
3486
+ * , getVal = function () { return val; };
3450
3487
  *
3451
3488
  * expect(noop, 'nooo why fail??').to.increase(getVal);
3452
3489
  *
@@ -3454,13 +3491,12 @@ Assertion.addMethod('changes', assertChanges);
3454
3491
  *
3455
3492
  * @name increase
3456
3493
  * @alias increases
3457
- * @param {String|Function} subject
3458
- * @param {String} prop name _optional_
3459
- * @param {String} msg _optional_
3494
+ * @param {string | Function} subject
3495
+ * @param {string} prop name _optional_
3496
+ * @param {string} msg _optional_
3460
3497
  * @namespace BDD
3461
- * @api public
3498
+ * @public
3462
3499
  */
3463
-
3464
3500
  function assertIncreases (subject, prop, msg) {
3465
3501
  if (msg) flag(this, 'message', msg);
3466
3502
  var fn = flag(this, 'object')
@@ -3573,13 +3609,12 @@ Assertion.addMethod('increases', assertIncreases);
3573
3609
  *
3574
3610
  * @name decrease
3575
3611
  * @alias decreases
3576
- * @param {String|Function} subject
3577
- * @param {String} prop name _optional_
3578
- * @param {String} msg _optional_
3612
+ * @param {string | Function} subject
3613
+ * @param {string} prop name _optional_
3614
+ * @param {string} msg _optional_
3579
3615
  * @namespace BDD
3580
- * @api public
3616
+ * @public
3581
3617
  */
3582
-
3583
3618
  function assertDecreases (subject, prop, msg) {
3584
3619
  if (msg) flag(this, 'message', msg);
3585
3620
  var fn = flag(this, 'object')
@@ -3680,12 +3715,11 @@ Assertion.addMethod('decreases', assertDecreases);
3680
3715
  * expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3);
3681
3716
  *
3682
3717
  * @name by
3683
- * @param {Number} delta
3684
- * @param {String} msg _optional_
3718
+ * @param {number} delta
3719
+ * @param {string} msg _optional_
3685
3720
  * @namespace BDD
3686
- * @api public
3721
+ * @public
3687
3722
  */
3688
-
3689
3723
  function assertDelta(delta, msg) {
3690
3724
  if (msg) flag(this, 'message', msg);
3691
3725
 
@@ -3722,8 +3756,8 @@ Assertion.addMethod('by', assertDelta);
3722
3756
  * Add `.not` earlier in the chain to negate `.extensible`.
3723
3757
  *
3724
3758
  * var nonExtensibleObject = Object.preventExtensions({})
3725
- * , sealedObject = Object.seal({})
3726
- * , frozenObject = Object.freeze({});
3759
+ * , sealedObject = Object.seal({})
3760
+ * , frozenObject = Object.freeze({});
3727
3761
  *
3728
3762
  * expect(nonExtensibleObject).to.not.be.extensible;
3729
3763
  * expect(sealedObject).to.not.be.extensible;
@@ -3736,9 +3770,8 @@ Assertion.addMethod('by', assertDelta);
3736
3770
  *
3737
3771
  * @name extensible
3738
3772
  * @namespace BDD
3739
- * @api public
3773
+ * @public
3740
3774
  */
3741
-
3742
3775
  Assertion.addProperty('extensible', function() {
3743
3776
  var obj = flag(this, 'object');
3744
3777
 
@@ -3781,9 +3814,8 @@ Assertion.addProperty('extensible', function() {
3781
3814
  *
3782
3815
  * @name sealed
3783
3816
  * @namespace BDD
3784
- * @api public
3817
+ * @public
3785
3818
  */
3786
-
3787
3819
  Assertion.addProperty('sealed', function() {
3788
3820
  var obj = flag(this, 'object');
3789
3821
 
@@ -3823,9 +3855,8 @@ Assertion.addProperty('sealed', function() {
3823
3855
  *
3824
3856
  * @name frozen
3825
3857
  * @namespace BDD
3826
- * @api public
3858
+ * @public
3827
3859
  */
3828
-
3829
3860
  Assertion.addProperty('frozen', function() {
3830
3861
  var obj = flag(this, 'object');
3831
3862
 
@@ -3889,9 +3920,8 @@ Assertion.addProperty('frozen', function() {
3889
3920
  *
3890
3921
  * @name finite
3891
3922
  * @namespace BDD
3892
- * @api public
3923
+ * @public
3893
3924
  */
3894
-
3895
3925
  Assertion.addProperty('finite', function(msg) {
3896
3926
  var obj = flag(this, 'object');
3897
3927