Skip to content
This repository
Browse code

Merge branch 'ecma5' of https://github.com/arthurschreiber/prototype

  • Loading branch information...
commit c4a9149df10abecd80ad695ea91ed3720cad858d 2 parents c22e224 + 1f569ae
Andrew Dupont authored February 17, 2012
4  src/prototype/ajax/responders.js
@@ -69,8 +69,8 @@
69 69
 Ajax.Responders = {
70 70
   responders: [],
71 71
 
72  
-  _each: function(iterator) {
73  
-    this.responders._each(iterator);
  72
+  _each: function(iterator, context) {
  73
+    this.responders._each(iterator, context);
74 74
   },
75 75
 
76 76
   /**
4  src/prototype/deprecated.js
@@ -156,10 +156,10 @@ Element.ClassNames.prototype = {
156 156
     this.element = $(element);
157 157
   },
158 158
 
159  
-  _each: function(iterator) {
  159
+  _each: function(iterator, context) {
160 160
     this.element.className.split(/\s+/).select(function(name) {
161 161
       return name.length > 0;
162  
-    })._each(iterator);
  162
+    })._each(iterator, context);
163 163
   },
164 164
 
165 165
   set: function(className) {
131  src/prototype/lang/array.js
@@ -447,19 +447,122 @@ Array.from = $A;
447 447
   }
448 448
 
449 449
   // Replaces a built-in function. No PDoc needed.
450  
-  function concat() {
451  
-    var array = slice.call(this, 0), item;
452  
-    for (var i = 0, length = arguments.length; i < length; i++) {
453  
-      item = arguments[i];
  450
+  function concat(_) {
  451
+    var array = [], items = slice.call(arguments, 0), item, n = 0;
  452
+    items.unshift(this);
  453
+    for (var i = 0, length = items.length; i < length; i++) {
  454
+      item = items[i];
454 455
       if (Object.isArray(item) && !('callee' in item)) {
455  
-        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
456  
-          array.push(item[j]);
  456
+        for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
  457
+          if (j in item) array[n] = item[j];
  458
+          n++;
  459
+        }
457 460
       } else {
458  
-        array.push(item);
  461
+        array[n++] = item;
459 462
       }
460 463
     }
  464
+    array.length = n;
461 465
     return array;
462 466
   }
  467
+  
  468
+  function wrapNative(method) {
  469
+    return function() {
  470
+      if (arguments.length === 0) {
  471
+        return method.call(this, Prototype.K);
  472
+      } else if (arguments[0] === undefined) {
  473
+        var args = slice.call(arguments, 1);
  474
+        args.unshift(Prototype.K)
  475
+        return method.apply(this, args);
  476
+      } else {
  477
+        return method.apply(this, arguments);
  478
+      }
  479
+    };
  480
+  }
  481
+  
  482
+  if (arrayProto.map) {
  483
+    var map = wrapNative(Array.prototype.map);
  484
+  } else {
  485
+    function map(iterator) {
  486
+      iterator = iterator || Prototype.K;
  487
+      var results = [], context = arguments[1], n = 0;
  488
+
  489
+      for (var i = 0, length = this.length; i < length; i++) {
  490
+        if (i in this) {
  491
+          results[n] = iterator.call(context, this[i], i, this);
  492
+        }
  493
+        n++;
  494
+      }
  495
+      results.length = n;
  496
+      return results;
  497
+    }
  498
+  }
  499
+  
  500
+  if (arrayProto.filter) {
  501
+    var filter = Array.prototype.filter;
  502
+  } else {
  503
+    function filter(iterator) {
  504
+      if (!Object.isFunction(iterator)) { throw new TypeError(); }
  505
+      var results = [], context = arguments[1], value;
  506
+
  507
+      for (var i = 0, length = this.length; i < length; i++) {
  508
+        if (i in this) {
  509
+          value = this[i];
  510
+          if (iterator.call(context, value, i, this)) {
  511
+            results.push(value);
  512
+          }
  513
+        }
  514
+      }
  515
+      return results;
  516
+    }
  517
+  }
  518
+  
  519
+  if (arrayProto.some) {
  520
+    var some = wrapNative(Array.prototype.some);
  521
+  } else {
  522
+    function some(iterator) {
  523
+      iterator = iterator || Prototype.K;
  524
+      var context = arguments[1];
  525
+
  526
+      for (var i = 0, length = this.length; i < length; i++) {
  527
+        if (i in this && iterator.call(context, this[i], i, this)) {
  528
+          return true;
  529
+        }
  530
+      }
  531
+      
  532
+      return false;
  533
+    }
  534
+  }
  535
+  
  536
+  if (arrayProto.every) {
  537
+    var every = wrapNative(Array.prototype.every);
  538
+  } else {
  539
+    function every(iterator) {
  540
+      iterator = iterator || Prototype.K;
  541
+      var context = arguments[1];
  542
+
  543
+      for (var i = 0, length = this.length; i < length; i++) {
  544
+        if (i in this && !iterator.call(context, this[i], i, this)) {
  545
+          return false;
  546
+        }
  547
+      }
  548
+      
  549
+      return true;
  550
+    }
  551
+  }
  552
+  
  553
+  if (arrayProto.reduce) {
  554
+    // Keep a copy of the native reduce
  555
+    var _reduce = arrayProto.reduce;
  556
+    function inject(memo, iterator) {
  557
+      iterator = iterator || Prototype.K;
  558
+      var context = arguments[2];
  559
+      // The iterator has to be bound, as Array.prototype.reduce
  560
+      // always executes the iterator in the global context.
  561
+      return _reduce.call(this, iterator.bind(context), memo, context);
  562
+    }
  563
+  } else {
  564
+    var inject = Enumerable.inject;
  565
+  }
463 566
 
464 567
   Object.extend(arrayProto, Enumerable);
465 568
 
@@ -468,6 +571,18 @@ Array.from = $A;
468 571
 
469 572
   Object.extend(arrayProto, {
470 573
     _each:     _each,
  574
+    
  575
+    map:       map,
  576
+    collect:   map,
  577
+    select:    filter,
  578
+    filter:    filter,
  579
+    findAll:   filter,
  580
+    some:      some,
  581
+    any:       some,
  582
+    every:     every,
  583
+    all:       every,
  584
+    inject:    inject,
  585
+    
471 586
     clear:     clear,
472 587
     first:     first,
473 588
     last:      last,
@@ -486,7 +601,7 @@ Array.from = $A;
486 601
   // fix for opera
487 602
   var CONCAT_ARGUMENTS_BUGGY = (function() {
488 603
     return [].concat(arguments)[0][0] !== 1;
489  
-  })(1,2)
  604
+  })(1,2);
490 605
 
491 606
   if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
492 607
 
53  src/prototype/lang/enumerable.js
@@ -107,11 +107,8 @@ var Enumerable = (function() {
107 107
    *  has a method to do that for you.
108 108
   **/
109 109
   function each(iterator, context) {
110  
-    var index = 0;
111 110
     try {
112  
-      this._each(function(value) {
113  
-        iterator.call(context, value, index++);
114  
-      });
  111
+      this._each(iterator, context);
115 112
     } catch (e) {
116 113
       if (e != $break) throw e;
117 114
     }
@@ -186,9 +183,9 @@ var Enumerable = (function() {
186 183
     iterator = iterator || Prototype.K;
187 184
     var result = true;
188 185
     this.each(function(value, index) {
189  
-      result = result && !!iterator.call(context, value, index);
  186
+      result = result && !!iterator.call(context, value, index, this);
190 187
       if (!result) throw $break;
191  
-    });
  188
+    }, this);
192 189
     return result;
193 190
   }
194 191
 
@@ -218,9 +215,9 @@ var Enumerable = (function() {
218 215
     iterator = iterator || Prototype.K;
219 216
     var result = false;
220 217
     this.each(function(value, index) {
221  
-      if (result = !!iterator.call(context, value, index))
  218
+      if (result = !!iterator.call(context, value, index, this))
222 219
         throw $break;
223  
-    });
  220
+    }, this);
224 221
     return result;
225 222
   }
226 223
 
@@ -251,8 +248,8 @@ var Enumerable = (function() {
251 248
     iterator = iterator || Prototype.K;
252 249
     var results = [];
253 250
     this.each(function(value, index) {
254  
-      results.push(iterator.call(context, value, index));
255  
-    });
  251
+      results.push(iterator.call(context, value, index, this));
  252
+    }, this);
256 253
     return results;
257 254
   }
258 255
 
@@ -274,11 +271,11 @@ var Enumerable = (function() {
274 271
   function detect(iterator, context) {
275 272
     var result;
276 273
     this.each(function(value, index) {
277  
-      if (iterator.call(context, value, index)) {
  274
+      if (iterator.call(context, value, index, this)) {
278 275
         result = value;
279 276
         throw $break;
280 277
       }
281  
-    });
  278
+    }, this);
282 279
     return result;
283 280
   }
284 281
 
@@ -299,9 +296,9 @@ var Enumerable = (function() {
299 296
   function findAll(iterator, context) {
300 297
     var results = [];
301 298
     this.each(function(value, index) {
302  
-      if (iterator.call(context, value, index))
  299
+      if (iterator.call(context, value, index, this))
303 300
         results.push(value);
304  
-    });
  301
+    }, this);
305 302
     return results;
306 303
   }
307 304
 
@@ -345,8 +342,8 @@ var Enumerable = (function() {
345 342
 
346 343
     this.each(function(value, index) {
347 344
       if (filter.match(value))
348  
-        results.push(iterator.call(context, value, index));
349  
-    });
  345
+        results.push(iterator.call(context, value, index, this));
  346
+    }, this);
350 347
     return results;
351 348
   }
352 349
 
@@ -449,8 +446,8 @@ var Enumerable = (function() {
449 446
   **/
450 447
   function inject(memo, iterator, context) {
451 448
     this.each(function(value, index) {
452  
-      memo = iterator.call(context, memo, value, index);
453  
-    });
  449
+      memo = iterator.call(context, memo, value, index, this);
  450
+    }, this);
454 451
     return memo;
455 452
   }
456 453
 
@@ -514,10 +511,10 @@ var Enumerable = (function() {
514 511
     iterator = iterator || Prototype.K;
515 512
     var result;
516 513
     this.each(function(value, index) {
517  
-      value = iterator.call(context, value, index);
  514
+      value = iterator.call(context, value, index, this);
518 515
       if (result == null || value >= result)
519 516
         result = value;
520  
-    });
  517
+    }, this);
521 518
     return result;
522 519
   }
523 520
 
@@ -554,10 +551,10 @@ var Enumerable = (function() {
554 551
     iterator = iterator || Prototype.K;
555 552
     var result;
556 553
     this.each(function(value, index) {
557  
-      value = iterator.call(context, value, index);
  554
+      value = iterator.call(context, value, index, this);
558 555
       if (result == null || value < result)
559 556
         result = value;
560  
-    });
  557
+    }, this);
561 558
     return result;
562 559
   }
563 560
 
@@ -592,9 +589,9 @@ var Enumerable = (function() {
592 589
     iterator = iterator || Prototype.K;
593 590
     var trues = [], falses = [];
594 591
     this.each(function(value, index) {
595  
-      (iterator.call(context, value, index) ?
  592
+      (iterator.call(context, value, index, this) ?
596 593
         trues : falses).push(value);
597  
-    });
  594
+    }, this);
598 595
     return [trues, falses];
599 596
   }
600 597
 
@@ -636,9 +633,9 @@ var Enumerable = (function() {
636 633
   function reject(iterator, context) {
637 634
     var results = [];
638 635
     this.each(function(value, index) {
639  
-      if (!iterator.call(context, value, index))
  636
+      if (!iterator.call(context, value, index, this))
640 637
         results.push(value);
641  
-    });
  638
+    }, this);
642 639
     return results;
643 640
   }
644 641
 
@@ -668,9 +665,9 @@ var Enumerable = (function() {
668 665
     return this.map(function(value, index) {
669 666
       return {
670 667
         value: value,
671  
-        criteria: iterator.call(context, value, index)
  668
+        criteria: iterator.call(context, value, index, this)
672 669
       };
673  
-    }).sort(function(left, right) {
  670
+    }, this).sort(function(left, right) {
674 671
       var a = left.criteria, b = right.criteria;
675 672
       return a < b ? -1 : a > b ? 1 : 0;
676 673
     }).pluck('value');
4  src/prototype/lang/hash.js
@@ -93,12 +93,12 @@ var Hash = Class.create(Enumerable, (function() {
93 93
   **/
94 94
 
95 95
   // Our _internal_ each
96  
-  function _each(iterator) {
  96
+  function _each(iterator, context) {
97 97
     for (var key in this._object) {
98 98
       var value = this._object[key], pair = [key, value];
99 99
       pair.key = key;
100 100
       pair.value = value;
101  
-      iterator(pair);
  101
+      iterator.call(context, pair);
102 102
     }
103 103
   }
104 104
 
4  src/prototype/lang/range.js
@@ -107,10 +107,10 @@ var ObjectRange = Class.create(Enumerable, (function() {
107 107
     this.exclusive = exclusive;
108 108
   }
109 109
 
110  
-  function _each(iterator) {
  110
+  function _each(iterator, context) {
111 111
     var value = this.start;
112 112
     while (this.include(value)) {
113  
-      iterator(value);
  113
+      iterator.call(context, value);
114 114
       value = value.succ();
115 115
     }
116 116
   }
124  test/unit/array_test.js
@@ -182,7 +182,35 @@ new Test.Unit.Runner({
182 182
     this.assertEnumEqual(['a', 'b', 'c', 'd'], $w(' a   b\nc\t\nd\n'));
183 183
   },
184 184
   
185  
-  testConcat: function(){
  185
+  testConcat: function() {
  186
+    var x = {};
  187
+
  188
+    this.assertIdentical(1, Array.prototype.concat.length);
  189
+
  190
+    this.assertEnumEqual([0, 1], [0, 1].concat());
  191
+    this.assertIdentical(2, [0, 1].concat().length);
  192
+    
  193
+    this.assertEnumEqual([0, 1, 2, 3, 4], [].concat([0, 1], [2, 3, 4]));
  194
+    this.assertIdentical(5, [].concat([0, 1], [2, 3, 4]).length);
  195
+
  196
+    this.assertEnumEqual([0, x, 1, 2, true, "NaN"], [0].concat(x, [1, 2], true, "NaN"));
  197
+    this.assertIdentical(6, [0].concat(x, [1, 2], true, "NaN").length);
  198
+    
  199
+    this.assertEnumEqual([undefined, 1, undefined], [,1].concat([], [,]));
  200
+    this.assertIdentical(3, [,1].concat([], [,]).length);
  201
+    this.assertEnumEqual([1], Object.keys([,1].concat([], [,])));
  202
+
  203
+    // Check that Array.prototype.concat can be used in a generic way
  204
+    x.concat = Array.prototype.concat;
  205
+    this.assertEnumEqual([x], x.concat());
  206
+    this.assertIdentical(1, x.concat().length);
  207
+    
  208
+    // Checking an edge case
  209
+    var arr = []; arr[2] = true;
  210
+    this.assertEnumEqual([undefined, undefined, true], [].concat(arr));
  211
+    this.assertIdentical(3, [].concat(arr).length);
  212
+    this.assertEnumEqual([2], Object.keys([].concat(arr)));
  213
+
186 214
     var args = (function() { return [].concat(arguments) })(1, 2);
187 215
     this.assertIdentical(1, args[0][0]);
188 216
   },
@@ -191,5 +219,99 @@ new Test.Unit.Runner({
191 219
     var sparseArray = [0, 1];
192 220
     sparseArray[5] = 5;
193 221
     this.assertEqual('[0, 1, 5]', sparseArray.inspect(), "Array#each should skip nonexistent keys in an array");
  222
+  },
  223
+  
  224
+  testMapGeneric: function() {
  225
+    var result = Array.prototype.map.call({0:0, 1:1, length:2});
  226
+    this.assertEnumEqual([0, 1], result);
  227
+  },
  228
+  
  229
+  testMap: function() {
  230
+    this.assertEnumEqual([1,2,3], [1,2,3].map());
  231
+    this.assertEnumEqual([2,4,6], [1,2,3].map(function(x) { return x * 2; }));
  232
+    
  233
+    var x = [1,2,3,4];
  234
+    delete x[1];
  235
+    delete x[3];
  236
+    this.assertEnumEqual([1, undefined, 3, undefined], x.map());
  237
+    this.assertIdentical(4, x.map().length);
  238
+    
  239
+    var traversed = [];
  240
+    x.map(function(val) {
  241
+      traversed.push(val);
  242
+    });
  243
+    this.assertEnumEqual([1, 3], traversed);
  244
+    this.assertIdentical(2, traversed.length);
  245
+  },
  246
+  
  247
+  testFindAllGeneric: function() {
  248
+    var result = Array.prototype.findAll.call({0:0, 1:1, length:2}, function(x) {
  249
+      return x === 1;
  250
+    });
  251
+    this.assertEnumEqual([1], result);
  252
+  },
  253
+  
  254
+  testFindAll: function() {
  255
+    this.assertEnumEqual([2, 4, 6], [1, 2, 3, 4, 5, 6].findAll(function(x) {
  256
+      return (x % 2) == 0;
  257
+    }));
  258
+    
  259
+    var x = [1,2,3], traversed = [];
  260
+    delete x[1];
  261
+    x.findAll(function(val) { traversed.push(val); });
  262
+    this.assertEnumEqual([1, 3], traversed);
  263
+    this.assertIdentical(2, traversed.length);
  264
+  },
  265
+
  266
+  testAnyGeneric: function() {
  267
+    this.assert(Array.prototype.any.call({ 0:false, 1:true, length:2 }));
  268
+    this.assert(!Array.prototype.any.call({ 0:false, 1:false, length:2 }));
  269
+  },
  270
+  
  271
+  testAny: function() {
  272
+    this.assert(!([].any()));
  273
+    
  274
+    this.assert([true, true, true].any());
  275
+    this.assert([true, false, false].any());
  276
+    this.assert(![false, false, false].any());
  277
+    
  278
+    this.assert([1,2,3,4,5].any(function(value) {
  279
+      return value > 2;
  280
+    }));
  281
+    this.assert(![1,2,3,4,5].any(function(value) {
  282
+      return value > 5;
  283
+    }));
  284
+    
  285
+    var x = [1,2,3], traversed = [];
  286
+    delete x[1];
  287
+    x.any(function(val) { traversed.push(val); });
  288
+    this.assertEnumEqual([1, 3], traversed);
  289
+    this.assertIdentical(2, traversed.length);
  290
+  },
  291
+  
  292
+  testAllGeneric: function() {
  293
+    this.assert(Array.prototype.all.call({ 0:true, 1:true, length:2 }));
  294
+    this.assert(!Array.prototype.all.call({ 0:false, 1:true, length:2 }));
  295
+  },
  296
+  
  297
+  testAll: function() {
  298
+    this.assert([].all());
  299
+    
  300
+    this.assert([true, true, true].all());
  301
+    this.assert(![true, false, false].all());
  302
+    this.assert(![false, false, false].all());
  303
+
  304
+    this.assert([1,2,3,4,5].all(function(value) {
  305
+      return value > 0;
  306
+    }));
  307
+    this.assert(![1,2,3,4,5].all(function(value) {
  308
+      return value > 1;
  309
+    }));
  310
+    
  311
+    var x = [1,2,3], traversed = [];
  312
+    delete x[1];
  313
+    x.all(function(val) { traversed.push(val); return true; });
  314
+    this.assertEnumEqual([1, 3], traversed);
  315
+    this.assertIdentical(2, traversed.length);
194 316
   }
195 317
 });
149  test/unit/enumerable_test.js
@@ -24,6 +24,16 @@ new Test.Unit.Runner({
24 24
     this.assertEqual('1, 3', results.join(', '));
25 25
   },
26 26
   
  27
+  "test #each passes value, index and collection to the iterator": function() {
  28
+    var i = 0;
  29
+    Fixtures.Basic.each(function(value, index, collection) {
  30
+      this.assertIdentical(Fixtures.Basic[i], value);
  31
+      this.assertIdentical(i, index);
  32
+      this.assertIdentical(Fixtures.Basic, collection);
  33
+      i++;
  34
+    }, this);
  35
+  },
  36
+  
27 37
   testEachChaining: function() {
28 38
     this.assertEqual(Fixtures.Primes, Fixtures.Primes.each(Prototype.emptyFunction));
29 39
     this.assertEqual(3, Fixtures.Basic.each(Prototype.emptyFunction).length);
@@ -63,6 +73,19 @@ new Test.Unit.Runner({
63 73
     }));
64 74
   },
65 75
   
  76
+  "test #any passes value, index and collection to the iterator": function() {
  77
+    var i = 0;
  78
+    Fixtures.Basic.any(function(value, index, collection) {
  79
+      this.assertIdentical(Fixtures.Basic[i], value);
  80
+      this.assertIdentical(i, index);
  81
+      this.assertIdentical(Fixtures.Basic, collection);
  82
+      i++;
  83
+      
  84
+      // Iterate over all values
  85
+      return value > 5;
  86
+    }, this);
  87
+  },
  88
+  
66 89
   testAll: function() {
67 90
     this.assert([].all());
68 91
     
@@ -78,6 +101,19 @@ new Test.Unit.Runner({
78 101
     }));
79 102
   },
80 103
   
  104
+  "test #all passes value, index and collection to the iterator": function() {
  105
+    var i = 0;
  106
+    Fixtures.Basic.all(function(value, index, collection) {
  107
+      this.assertIdentical(Fixtures.Basic[i], value);
  108
+      this.assertIdentical(i, index);
  109
+      this.assertIdentical(Fixtures.Basic, collection);
  110
+      i++;
  111
+      
  112
+      // Iterate over all values
  113
+      return value > 0;
  114
+    }, this);
  115
+  },
  116
+  
81 117
   testCollect: function() {
82 118
     this.assertEqual(Fixtures.Nicknames.join(', '), 
83 119
       Fixtures.People.collect(function(person) {
@@ -87,6 +123,17 @@ new Test.Unit.Runner({
87 123
     this.assertEqual(26,  Fixtures.Primes.map().length);
88 124
   },
89 125
   
  126
+  "test #collect passes value, index and collection to the iterator": function() {
  127
+    var i = 0;
  128
+    Fixtures.Basic.collect(function(value, index, collection) {
  129
+      this.assertIdentical(Fixtures.Basic[i], value);
  130
+      this.assertIdentical(i, index);
  131
+      this.assertIdentical(Fixtures.Basic, collection);
  132
+      i++;
  133
+      return value;
  134
+    }, this);
  135
+  },
  136
+  
90 137
   testDetect: function() {
91 138
     this.assertEqual('Marcel Molina Jr.', 
92 139
       Fixtures.People.detect(function(person) {
@@ -94,6 +141,19 @@ new Test.Unit.Runner({
94 141
       }).name);
95 142
   },
96 143
   
  144
+  "test #detect passes value, index and collection to the iterator": function() {
  145
+    var i = 0;
  146
+    Fixtures.Basic.detect(function(value, index, collection) {
  147
+      this.assertIdentical(Fixtures.Basic[i], value);
  148
+      this.assertIdentical(i, index);
  149
+      this.assertIdentical(Fixtures.Basic, collection);
  150
+      i++;
  151
+      
  152
+      // Iterate over all values
  153
+      return value > 5;
  154
+    }, this);
  155
+  },
  156
+  
97 157
   testEachSlice: function() {
98 158
     this.assertEnumEqual([], [].eachSlice(2));
99 159
     this.assertEqual(1, [1].eachSlice(1).length);
@@ -125,6 +185,17 @@ new Test.Unit.Runner({
125 185
       Fixtures.Z.findAll(prime).join(', '));
126 186
   },
127 187
   
  188
+  "test #findAll passes value, index and collection to the iterator": function() {
  189
+    var i = 0;
  190
+    Fixtures.Basic.findAll(function(value, index, collection) {
  191
+      this.assertIdentical(Fixtures.Basic[i], value);
  192
+      this.assertIdentical(i, index);
  193
+      this.assertIdentical(Fixtures.Basic, collection);
  194
+      i++;
  195
+      return value > 5;
  196
+    }, this);
  197
+  },
  198
+  
128 199
   testGrep: function() {
129 200
     this.assertEqual('noradio, htonl', 
130 201
       Fixtures.Nicknames.grep(/o/).join(", "));
@@ -146,6 +217,17 @@ new Test.Unit.Runner({
146 217
     this.assertEnumEqual(['|a', 'c|'], ['|a','b','c|'].grep('|'));
147 218
   },
148 219
   
  220
+  "test #grep passes value, index and collection to the iterator": function() {
  221
+    var i = 0;
  222
+    Fixtures.Basic.grep(/\d/, function(value, index, collection) {
  223
+      this.assertIdentical(Fixtures.Basic[i], value);
  224
+      this.assertIdentical(i, index);
  225
+      this.assertIdentical(Fixtures.Basic, collection);
  226
+      i++;
  227
+      return value;
  228
+    }, this);
  229
+  },
  230
+  
149 231
   testInclude: function() {
150 232
     this.assert(Fixtures.Nicknames.include('sam-'));
151 233
     this.assert(Fixtures.Nicknames.include('noradio'));
@@ -191,6 +273,18 @@ new Test.Unit.Runner({
191 273
       }));
192 274
   },
193 275
   
  276
+  "test #inject passes memo, value, index and collection to the iterator": function() {
  277
+    var i = 0;
  278
+    Fixtures.Basic.inject(0, function(memo, value, index, collection) {
  279
+      this.assertIdentical(Fixtures.Basic[i], value);
  280
+      this.assertIdentical(i, index);
  281
+      this.assertIdentical(Fixtures.Basic, collection);
  282
+      i++;
  283
+
  284
+      return memo + value;
  285
+    }, this);
  286
+  },
  287
+  
194 288
   testInvoke: function() {
195 289
     var result = [[2, 1, 3], [6, 5, 4]].invoke('sort');
196 290
     this.assertEqual(2, result.length);
@@ -209,12 +303,34 @@ new Test.Unit.Runner({
209 303
     this.assertEqual('sam-', Fixtures.Nicknames.max()); // ?s > ?U
210 304
   },
211 305
   
  306
+  "test #max passes value, index and collection to the iterator": function() {
  307
+    var i = 0;
  308
+    Fixtures.Basic.max(function(value, index, collection) {
  309
+      this.assertIdentical(Fixtures.Basic[i], value);
  310
+      this.assertIdentical(i, index);
  311
+      this.assertIdentical(Fixtures.Basic, collection);
  312
+      i++;
  313
+      return value;
  314
+    }, this);
  315
+  },
  316
+  
212 317
   testMin: function() {
213 318
     this.assertEqual(1, Fixtures.Z.min());
214 319
     this.assertEqual(0, [  1, 2, 3, 4, 5, 6, 7, 8, 0, 9 ].min());
215 320
     this.assertEqual('Ulysses', Fixtures.Nicknames.min()); // ?U < ?h
216 321
   },
217 322
   
  323
+  "test #min passes value, index and collection to the iterator": function() {
  324
+    var i = 0;
  325
+    Fixtures.Basic.min(function(value, index, collection) {
  326
+      this.assertIdentical(Fixtures.Basic[i], value);
  327
+      this.assertIdentical(i, index);
  328
+      this.assertIdentical(Fixtures.Basic, collection);
  329
+      i++;
  330
+      return value;
  331
+    }, this);
  332
+  },
  333
+  
218 334
   testPartition: function() {
219 335
     var result = Fixtures.People.partition(function(person) {
220 336
       return person.name.length < 15;
@@ -225,6 +341,17 @@ new Test.Unit.Runner({
225 341
     this.assertEqual('noradio, Ulysses', result[1].join(', '));
226 342
   },
227 343
   
  344
+  "test #partition passes value, index and collection to the iterator": function() {
  345
+    var i = 0;
  346
+    Fixtures.Basic.partition(function(value, index, collection) {
  347
+      this.assertIdentical(Fixtures.Basic[i], value);
  348
+      this.assertIdentical(i, index);
  349
+      this.assertIdentical(Fixtures.Basic, collection);
  350
+      i++;
  351
+      return value < 2;
  352
+    }, this);
  353
+  },
  354
+  
228 355
   testPluck: function() {
229 356
     this.assertEqual(Fixtures.Nicknames.join(', '),
230 357
       Fixtures.People.pluck('nickname').join(', '));
@@ -240,6 +367,17 @@ new Test.Unit.Runner({
240 367
       }).join(', '));
241 368
   },
242 369
   
  370
+  "test #reject passes value, index and collection to the iterator": function() {
  371
+    var i = 0;
  372
+    Fixtures.Basic.reject(function(value, index, collection) {
  373
+      this.assertIdentical(Fixtures.Basic[i], value);
  374
+      this.assertIdentical(i, index);
  375
+      this.assertIdentical(Fixtures.Basic, collection);
  376
+      i++;
  377
+      return value < 2;
  378
+    }, this);
  379
+  },
  380
+  
243 381
   testSortBy: function() {
244 382
     this.assertEqual('htonl, noradio, sam-, Ulysses',
245 383
       Fixtures.People.sortBy(function(value) {
@@ -247,6 +385,17 @@ new Test.Unit.Runner({
247 385
       }).pluck('nickname').join(', '));
248 386
   },
249 387
   
  388
+  "test #sortBy passes value, index and collection to the iterator": function() {
  389
+    var i = 0;
  390
+    Fixtures.Basic.sortBy(function(value, index, collection) {
  391
+      this.assertIdentical(Fixtures.Basic[i], value);
  392
+      this.assertIdentical(i, index);
  393
+      this.assertIdentical(Fixtures.Basic, collection);
  394
+      i++;
  395
+      return value;
  396
+    }, this);
  397
+  },
  398
+  
250 399
   testToArray: function() {
251 400
     var result = Fixtures.People.toArray();
252 401
     this.assert(result != Fixtures.People); // they're different objects...

0 notes on commit c4a9149

John-David Dalton

While you are at the ES5 fixes might wanna spruce up Function#bind too.

John-David Dalton

Function declarations in blocks is super gross.

Andrew Dupont

I might change it before release.

John-David Dalton

Here is a note from ES5 spec:

NOTE Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context.

John-David Dalton

Also it will throw an error in strict mode in Chrome too.

Juriy Zaytsev

IIRC, latest FF actually throws when encountering FD in blocks while in strict mode.

Andrew Dupont

FINE I'LL CHANGE IT

John-David Dalton

I think every method that's using wrapNative has the same arguments signature so that means you can avoid .apply and use .call.

Please sign in to comment.
Something went wrong with that request. Please try again.