5cba7523b404c96c032c420ea686e0d1dbfb8c9229f82864375552d6e010594e7869a6f23ccc20399f624f0c5a7ce89a916f37bbd2e5866c700e61f7737f7c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. var hasStrictMode = require('has-strict-mode')();
  2. var global = Function('return this')(); // eslint-disable-line no-new-func
  3. var identity = function (x) { return x; };
  4. var canDistinguishSparseFromUndefined = 0 in [undefined]; // IE 6 - 8 have a bug where this returns false.
  5. var undefinedIfNoSparseBug = canDistinguishSparseFromUndefined ? undefined : { valueOf: function () { return 0; } };
  6. var createArrayLikeFromArray = function createArrayLike(arr) {
  7. var o = {};
  8. for (var i = 0; i < arr.length; i += 1) {
  9. if (i in arr) {
  10. o[i] = arr[i];
  11. }
  12. }
  13. o.length = arr.length;
  14. return o;
  15. };
  16. module.exports = function (reduce, t) {
  17. t.test('passes the correct values to the callback', function (st) {
  18. st.plan(7);
  19. var expectedValue = {};
  20. var initialValue = {};
  21. var expectedResult = {};
  22. var arr = [expectedValue];
  23. var result = reduce(
  24. arr,
  25. function (accumulator, value, key, list) {
  26. st.equal(arguments.length, 4);
  27. st.equal(accumulator, initialValue, 'first argument is the accumulator');
  28. st.equal(value, expectedValue, 'second argument is the value');
  29. st.equal(key, 0, 'third argument is the index');
  30. st.equal(list, arr, 'fourth argument is the array being iterated');
  31. st.equal(this, global, 'sloppy: receiver is the expected value');
  32. return expectedResult;
  33. },
  34. initialValue
  35. );
  36. st.equal(result, expectedResult, 'result is last return value of accumulator');
  37. st.end();
  38. });
  39. t.test('strict mode callback receiver', { skip: !hasStrictMode }, function (st) {
  40. reduce(
  41. [null],
  42. function () {
  43. 'use strict';
  44. st.equal(this, undefined, 'strict: receiver is the expected value');
  45. }
  46. );
  47. st.end();
  48. });
  49. t.test('starts with the right initialValue', function (st) {
  50. var firstValue = {};
  51. var secondValue = {};
  52. reduce(
  53. [firstValue, secondValue],
  54. function (accumulator, value) {
  55. st.equal(accumulator, firstValue, 'accumulator starts out as the first value when initialValue is omitted');
  56. st.equal(value, secondValue, 'value starts out as the second value when initialValue is omitted');
  57. }
  58. );
  59. reduce(
  60. [secondValue],
  61. function (accumulator, value) {
  62. st.equal(accumulator, firstValue, 'accumulator starts out as the initialValue when provided');
  63. st.equal(value, secondValue, 'value starts out as the first value when initialValue is provided');
  64. },
  65. firstValue
  66. );
  67. st.end();
  68. });
  69. t.test('does not visit elements added to the array after it has begun', function (st) {
  70. st.plan(8);
  71. var arr = [1, 2, 3];
  72. var i = 0;
  73. reduce(arr, function (acc, v) {
  74. i += 1;
  75. arr.push(v + 3);
  76. });
  77. st.deepEqual(arr, [1, 2, 3, 5, 6], 'array has received 3 new elements. initialValue omitted');
  78. st.equal(i, 2, 'reduce callback only called twice');
  79. i = 0;
  80. arr = [1, 2, 3];
  81. reduce(
  82. arr,
  83. function (acc, v) {
  84. i += 1;
  85. arr.push(v + 3);
  86. },
  87. null
  88. );
  89. st.deepEqual(arr, [1, 2, 3, 4, 5, 6], 'array has received 3 new elements. initialValue provided');
  90. st.equal(i, 3, 'reduce callback only called thrice');
  91. var arrayLike = createArrayLikeFromArray([1, 2, 3]);
  92. i = 0;
  93. reduce(arrayLike, function (acc, v) {
  94. i += 1;
  95. arrayLike[arrayLike.length] = v + 3;
  96. arrayLike.length += 1;
  97. });
  98. st.deepEqual(Array.prototype.slice.call(arrayLike), [1, 2, 3, 5, 6], 'arrayLike has received 3 new elements. initialValue omitted');
  99. st.equal(i, 2, 'reduce callback only called twice');
  100. arrayLike = createArrayLikeFromArray([1, 2, 3]);
  101. i = 0;
  102. reduce(
  103. arrayLike,
  104. function (acc, v) {
  105. i += 1;
  106. arrayLike[arrayLike.length] = v + 3;
  107. arrayLike.length += 1;
  108. },
  109. null
  110. );
  111. st.deepEqual(Array.prototype.slice.call(arrayLike), [1, 2, 3, 4, 5, 6], 'arrayLike has received 3 new elements. initialValue provided');
  112. st.equal(i, 3, 'reduce callback only called thrice');
  113. st.end();
  114. });
  115. t.test('empty array', function (st) {
  116. var initialValue = {};
  117. var actual = reduce([], identity, initialValue);
  118. st.equal(actual, initialValue, 'empty array returns callback return');
  119. st['throws'](
  120. function () { reduce([], identity); },
  121. TypeError,
  122. 'empty array with omitted initialValue throws'
  123. );
  124. var sparse = Array(10);
  125. st['throws'](
  126. function () { reduce(sparse, identity); },
  127. TypeError,
  128. 'only-holes array with omitted initialValue throws (test262: 15.4.4.21-8-c-1)'
  129. );
  130. st.end();
  131. });
  132. t.test('skips holes', function (st) {
  133. var arr = [1, undefinedIfNoSparseBug, 3];
  134. var visited = {};
  135. reduce(
  136. arr,
  137. function (a, b) {
  138. if (a) { visited[a] = true; }
  139. if (b) { visited[b] = true; }
  140. return 0;
  141. },
  142. null
  143. );
  144. st.deepEqual(visited, { 1: true, 3: true }, 'only non-holes are visited; initialValue provided');
  145. visited = {};
  146. reduce(
  147. arr,
  148. function (a, b) {
  149. if (a) { visited[a] = true; }
  150. if (b) { visited[b] = true; }
  151. return 0;
  152. }
  153. );
  154. st.deepEqual(visited, { 1: true, 3: true }, 'only non-holes are visited; initialValue omitted');
  155. st.end();
  156. });
  157. t.test('list arg boxing', function (st) {
  158. st.plan(4);
  159. reduce(
  160. 'f',
  161. function (acc, item, index, list) {
  162. st.equal(acc, null, 'accumulator matches');
  163. st.equal(item, 'f', 'letter matches');
  164. st.equal(typeof list, 'object', 'primitive list arg is boxed');
  165. st.equal(Object.prototype.toString.call(list), '[object String]', 'boxed list arg is a String');
  166. },
  167. null
  168. );
  169. st.end();
  170. });
  171. t.test('test262: 15.4.4.21-3-12', function (st) {
  172. var obj = {
  173. 1: 11,
  174. 2: 9,
  175. length: '-4294967294'
  176. };
  177. var cb = function callbackfn(prevVal, curVal, idx, object) {
  178. st.equal(object, obj, '4th argument is receiver');
  179. return curVal === 11 && idx === 1;
  180. };
  181. st.equal(reduce(obj, cb, 1), 1, 'reduce(obj, callbackfn, 1)');
  182. st.end();
  183. });
  184. };