Skip to content
This repository
Browse code

Update Benchmark.js to use Lo-Dash.

  • Loading branch information...
commit 7650014f82ab84a917a628ca9583edb8bdc699cf 1 parent a421927
John-David Dalton authored March 09, 2013
6,006  benchmark.js
2452 additions, 3554 deletions not shown
26  test/index.html
@@ -13,29 +13,11 @@
13 13
 	</head>
14 14
 	<body>
15 15
 		<div id="qunit"></div>
  16
+		<script src="../vendor/qunit/qunit/qunit.js"></script>
  17
+		<script src="../vendor/lodash/lodash.js"></script>
16 18
 		<script src="../benchmark.js"></script>
17 19
 		<script src="../vendor/platform.js/platform.js"></script>
18 20
 		<script>
19  
-			(function() {
20  
-				var hasOwnProperty = function hasOwnProperty(key) {
21  
-					var parent = (this.constructor || Object).prototype;
22  
-					return key in this && !(key in parent && this[key] === parent[key]);
23  
-				};
24  
-				if (typeof {}.hasOwnProperty != 'function') {
25  
-					// redefine for Safari 2, else use the less accurate fallback for others
26  
-					if ({}.__proto__ == Object.prototype) {
27  
-						hasOwnProperty = function hasOwnProperty(key) {
28  
-							var result;
29  
-							this.__proto__ = [this.__proto__, this.__proto__ = null, result = key in this][0];
30  
-							return result;
31  
-						};
32  
-					}
33  
-					Object.prototype.hasOwnProperty = hasOwnProperty;
34  
-				}
35  
-			}());
36  
-		</script>
37  
-		<script src="../vendor/qunit/qunit/qunit.js"></script>
38  
-		<script>
39 21
 			// populate `QUnit.urlParams`
40 22
 			QUnit.urlParams.nojava = /[?&]nojava=true(?:&|$)/.test(location.search);
41 23
 			QUnit.urlParams.norequire = /[?&]norequire=true(?:&|$)/.test(location.search);
@@ -70,12 +52,12 @@
70 52
 				'urlArgs': 't=' + (+new Date),
71 53
 				'paths': {
72 54
 					'benchmark': '../../benchmark',
  55
+					'lodash': '../lodash/lodash',
73 56
 					'platform': '../platform.js/platform'
74 57
 				}
75 58
 			},
76  
-			['benchmark', 'platform'], function(Benchmark, platform) {
  59
+			['benchmark'], function(Benchmark) {
77 60
 				Benchmark2 = Benchmark;
78  
-				Benchmark2.platform = platform;
79 61
 			});
80 62
 
81 63
 			window.onload = function() {
994  test/test.js
@@ -4,65 +4,35 @@
4 4
   /** Use a single "load" function */
5 5
   var load = typeof require == 'function' ? require : window.load;
6 6
 
7  
-  /** The `platform` object to check */
8  
-  var platform =
9  
-    window.platform ||
10  
-    load('../vendor/platform.js/platform.js') ||
11  
-    window.platform;
12  
-
13 7
   /** The unit testing framework */
14  
-  var QUnit =
15  
-    window.QUnit || (
16  
-      window.addEventListener || (window.addEventListener = Function.prototype),
17  
-      window.setTimeout || (window.setTimeout = Function.prototype),
  8
+  var QUnit = (function() {
  9
+    var noop = Function.prototype;
  10
+    return  window.QUnit || (
  11
+      window.addEventListener || (window.addEventListener = noop),
  12
+      window.setTimeout || (window.setTimeout = noop),
18 13
       window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit,
19  
-      load('../vendor/qunit-clib/qunit-clib.js'),
20  
-      window.addEventListener === Function.prototype && delete window.addEventListener,
  14
+      (load('../vendor/qunit-clib/qunit-clib.js') || { 'runInContext': noop }).runInContext(window),
  15
+      addEventListener === noop && delete window.addEventListener,
21 16
       window.QUnit
22 17
     );
  18
+  }());
23 19
 
24  
-  /** The `Benchmark` constructor to test */
25  
-  var Benchmark =
26  
-    window.Benchmark || (
27  
-      Benchmark = load('../benchmark.js') || window.Benchmark,
28  
-      Benchmark.Benchmark || Benchmark
29  
-    );
30  
-
31  
-  /** API shortcut */
32  
-  var forOwn = Benchmark.forOwn;
33  
-
34  
-  /** Used to get property descriptors */
35  
-  var getDescriptor = Object.getOwnPropertyDescriptor;
  20
+  /** The `lodash` utility function */
  21
+  var _ = window._ || (window._ = (
  22
+    _ = load('../vendor/lodash/lodash.js') || window._,
  23
+    _ = _._ || _,
  24
+    _.runInContext(window)
  25
+  ));
36 26
 
37  
-  /** Used to set property descriptors */
38  
-  var setDescriptor = Object.defineProperty;
  27
+  /** The `Benchmark` constructor to test */
  28
+  var Benchmark = window.Benchmark || (window.Benchmark = (
  29
+    Benchmark = load('../benchmark.js') || window.Benchmark,
  30
+    Benchmark = Benchmark.Benchmark || Benchmark,
  31
+    Benchmark.runInContext(window)
  32
+  ));
39 33
 
40 34
   /** Shortcut used to convert array-like objects to arrays */
41  
-  var slice = [].slice;
42  
-
43  
-  /** Used to resolve a value's internal [[Class]] */
44  
-  var toString = {}.toString;
45  
-
46  
-  /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */
47  
-  var shadowed = {
48  
-    'constructor': 1,
49  
-    'hasOwnProperty': 2,
50  
-    'isPrototypeOf': 3,
51  
-    'propertyIsEnumerable': 4,
52  
-    'toLocaleString': 5,
53  
-    'toString': 6,
54  
-    'valueOf': 7
55  
-  };
56  
-
57  
-  /** Used to flag environments/features */
58  
-  var support = {
59  
-    'descriptors': !!function() {
60  
-      try {
61  
-        var o = {};
62  
-        return (setDescriptor(o, o, o), 'value' in getDescriptor(o, o));
63  
-      } catch(e) { }
64  
-    }()
65  
-  };
  35
+  var slice = Array.prototype.slice;
66 36
 
67 37
   /*--------------------------------------------------------------------------*/
68 38
 
@@ -93,7 +63,7 @@
93 63
 
94 64
   (function() {
95 65
     test('has the default `Benchmark.platform` value', function() {
96  
-      if (window.document) {
  66
+      if (window.navigator) {
97 67
         equal(String(Benchmark.platform), navigator.userAgent);
98 68
       } else {
99 69
         skipTest(1);
@@ -242,7 +212,7 @@
242 212
       }
243 213
     };
244 214
 
245  
-    forOwn(tests, function(fn, title) {
  215
+    _.forOwn(tests, function(fn, title) {
246 216
       test('has correct binding for ' + title, function() {
247 217
         var bench = Benchmark({
248 218
           'setup': 'if(/ops/.test(this))this._setup=true;',
@@ -266,331 +236,15 @@
266 236
 
267 237
   /*--------------------------------------------------------------------------*/
268 238
 
269  
-  QUnit.module('Benchmark.deepClone');
270  
-
271  
-  (function() {
272  
-    function createCircularObject() {
273  
-      var result = {
274  
-        'foo': { 'b': { 'foo': { 'c': { } } } },
275  
-        'bar': { }
276  
-      };
277  
-
278  
-      result.foo.b.foo.c.foo = result;
279  
-      result.bar.b = result.foo.b;
280  
-      return result;
281  
-    }
282  
-
283  
-    function Klass() {
284  
-      this.a = 1;
285  
-    }
286  
-
287  
-    Klass.prototype = { 'b': 1 };
288  
-
289  
-    var notCloneable = {
290  
-      'an arguments object': arguments,
291  
-      'an element': window.document && document.body,
292  
-      'a function': Klass,
293  
-      'a Klass instance': new Klass
294  
-    };
295  
-
296  
-    var objects = {
297  
-      'an array': ['a', 'b', 'c', ''],
298  
-      'an array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 },
299  
-      'boolean': false,
300  
-      'boolean object': Object(false),
301  
-      'an object': { 'a': 0, 'b': 1, 'c': 3 },
302  
-      'an object with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } },
303  
-      'null': null,
304  
-      'a number': 3,
305  
-      'a number object': Object(3),
306  
-      'a regexp': /x/gim,
307  
-      'a string': 'x',
308  
-      'a string object': Object('x'),
309  
-      'undefined': undefined
310  
-    };
311  
-
312  
-    objects['an array'].length = 5;
313  
-
314  
-    forOwn(objects, function(object, key) {
315  
-      test('clones ' + key + ' correctly', function() {
316  
-        var kind = toString.call(object),
317  
-            clone = Benchmark.deepClone(object);
318  
-
319  
-        if (object == null) {
320  
-          equal(clone, object);
321  
-        } else {
322  
-          deepEqual(clone.valueOf(), object.valueOf());
323  
-        }
324  
-        if (object === Object(object)) {
325  
-          ok(clone !== object);
326  
-        } else {
327  
-          skipTest();
328  
-        }
329  
-      });
330  
-    });
331  
-
332  
-    forOwn(notCloneable, function(object, key) {
333  
-      test('does not clone ' + key, function() {
334  
-        ok(Benchmark.deepClone(object) === object);
335  
-      });
336  
-    });
337  
-
338  
-    test('clones using Klass#deepClone', function() {
339  
-      var object = new Klass;
340  
-      Klass.prototype.deepClone = function() { return new Klass; };
341  
-
342  
-      var clone = Benchmark.deepClone(object);
343  
-      ok(clone !== object && clone instanceof Klass);
344  
-
345  
-      delete Klass.prototype.clone;
346  
-    });
347  
-
348  
-    test('clones problem JScript properties', function() {
349  
-      var clone = Benchmark.deepClone(shadowed);
350  
-      deepEqual(clone, shadowed);
351  
-    });
352  
-
353  
-    test('clones string object with custom property', function() {
354  
-      var object = new String('x');
355  
-      object.x = 1;
356  
-
357  
-      var clone = Benchmark.deepClone(object);
358  
-      ok(clone == 'x' && typeof clone == 'object' && clone.x === 1 && toString.call(clone) == '[object String]');
359  
-    });
360  
-
361  
-    test('clones objects with circular references', function() {
362  
-      var object = createCircularObject(),
363  
-          clone = Benchmark.deepClone(object);
364  
-
365  
-      ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c.foo && clone !== object);
366  
-    });
367  
-
368  
-    test('clones non-extensible objects with circular references', function() {
369  
-      if (Object.preventExtensions) {
370  
-        var object = Object.preventExtensions(createCircularObject());
371  
-        Object.preventExtensions(object.bar.b);
372  
-
373  
-        var clone = Benchmark.deepClone(object);
374  
-        ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c.foo && clone !== object);
375  
-      } else {
376  
-        skipTest(1);
377  
-      }
378  
-    });
379  
-
380  
-    test('clones sealed objects with circular references', function() {
381  
-      if (Object.seal) {
382  
-        var object = Object.seal(createCircularObject());
383  
-        Object.seal(object.bar.b);
384  
-
385  
-        var clone = Benchmark.deepClone(object);
386  
-        ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c.foo && clone !== object);
387  
-      } else {
388  
-        skipTest(1);
389  
-      }
390  
-    });
391  
-
392  
-    test('clones frozen objects with circular references', function() {
393  
-      if (Object.freeze) {
394  
-        var object = Object.freeze(createCircularObject());
395  
-        Object.freeze(object.bar.b);
396  
-
397  
-        var clone = Benchmark.deepClone(object);
398  
-        ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c.foo && clone !== object);
399  
-      } else {
400  
-        skipTest(1);
401  
-      }
402  
-    });
403  
-
404  
-    test('clones objects with custom descriptors and circular references', function() {
405  
-      var accessor,
406  
-          descriptor;
407  
-
408  
-      if (support.descriptors) {
409  
-        var object = setDescriptor({}, 'foo', {
410  
-          'configurable': true,
411  
-          'value': setDescriptor({}, 'b', {
412  
-            'writable': true,
413  
-            'value': setDescriptor({}, 'foo', {
414  
-              'get': function() { return accessor; },
415  
-              'set': function(value) { accessor = value; }
416  
-            })
417  
-          })
418  
-        });
419  
-
420  
-        setDescriptor(object, 'bar', { 'value': {} });
421  
-        object.foo.b.foo = { 'c': object };
422  
-        object.bar.b = object.foo.b;
423  
-
424  
-        var clone = Benchmark.deepClone(object);
425  
-        ok(clone !== object &&
426  
-          clone.bar.b === clone.foo.b &&
427  
-          clone !== clone.foo.b.foo.c.foo &&
428  
-          (descriptor = getDescriptor(clone, 'foo')) &&
429  
-          descriptor.configurable && !(descriptor.enumerable && descriptor.writable) &&
430  
-          (descriptor = getDescriptor(clone.foo, 'b')) &&
431  
-          descriptor.writable && !(descriptor.configurable && descriptor.enumerable) &&
432  
-          (descriptor = getDescriptor(clone.foo.b, 'foo')) &&
433  
-          descriptor.get && descriptor.set &&
434  
-          (descriptor = getDescriptor(clone.foo.b, 'foo')) &&
435  
-          !(descriptor.configurable && descriptor.enumerable && descriptor.writable) &&
436  
-          (descriptor = getDescriptor(clone, 'bar')) &&
437  
-          !(descriptor.configurable && descriptor.enumerable && descriptor.writable));
438  
-      }
439  
-      else {
440  
-        skipTest(1);
441  
-      }
442  
-    });
443  
-  }());
444  
-
445  
-  /*--------------------------------------------------------------------------*/
446  
-
447  
-  QUnit.module('Benchmark.each');
448  
-
449  
-  (function() {
450  
-    var xpathResult;
451  
-
452  
-    var objects = {
453  
-      'array': ['a', 'b', 'c', ''],
454  
-      'array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 },
455  
-      'xpath snapshot': null
456  
-    };
457  
-
458  
-    if (window.document && document.evaluate) {
459  
-      xpathResult = [document.documentElement, document.getElementsByTagName('head')[0], document.body];
460  
-      objects['xpath snapshot'] = document.evaluate('//*[self::html or self::head or self::body]', document, null, 7, null);
461  
-    }
462  
-
463  
-    objects.array.length = 5;
464  
-
465  
-    forOwn(objects, function(object, key) {
466  
-      test('passes the correct arguments when passing an ' + key, function() {
467  
-        if (object) {
468  
-          var args
469  
-          Benchmark.each(object, function() {
470  
-            args || (args = slice.call(arguments));
471  
-          });
472  
-
473  
-          if (key == 'xpath snapshot') {
474  
-            ok(args[0] === xpathResult[0]);
475  
-          } else {
476  
-            equal(args[0], 'a');
477  
-          }
478  
-          equal(args[1], 0);
479  
-          ok(args[2] === object);
480  
-        }
481  
-        else {
482  
-          skipTest(3);
483  
-        }
484  
-      });
485  
-
486  
-      test('returns the passed object when passing an ' + key, function() {
487  
-        if (object) {
488  
-          var actual = Benchmark.each(object, function() { });
489  
-          ok(actual === object);
490  
-        }
491  
-        else {
492  
-          skipTest();
493  
-        }
494  
-      });
495  
-
496  
-      test('iterates over all indexes when passing an ' + key, function() {
497  
-        if (object) {
498  
-          var values = [];
499  
-          Benchmark.each(object, function(value) {
500  
-            values.push(value);
501  
-          });
502  
-
503  
-          deepEqual(values, key == 'xpath snapshot' ? xpathResult : ['a', 'b', 'c', '']);
504  
-        }
505  
-        else {
506  
-          skipTest();
507  
-        }
508  
-      });
509  
-
510  
-      test('exits early when returning `false` when passing an ' + key, function() {
511  
-        if (object) {
512  
-          var values = [];
513  
-          Benchmark.each(object, function(value) {
514  
-            values.push(value);
515  
-            return values.length < 2;
516  
-          });
517  
-
518  
-          deepEqual(values, key == 'xpath snapshot' ? xpathResult.slice(0, 2) : ['a', 'b']);
519  
-        }
520  
-        else {
521  
-          skipTest();
522  
-        }
523  
-      });
524  
-    });
525  
-
526  
-    test('passes the third callback argument as an object', function() {
527  
-      var thirdArg;
528  
-      Benchmark.each('hello', function(value, index, object) {
529  
-        thirdArg = object;
530  
-      });
531  
-
532  
-      ok(thirdArg && typeof thirdArg == 'object');
533  
-    });
534  
-
535  
-    test('iterates over strings by index', function() {
536  
-      var values = [];
537  
-      Benchmark.each('hello', function(value) {
538  
-        values.push(value)
539  
-      });
540  
-
541  
-      deepEqual(values, ['h', 'e', 'l', 'l', 'o']);
542  
-    });
543  
-  }());
544  
-
545  
-  /*--------------------------------------------------------------------------*/
546  
-
547  
-  QUnit.module('Benchmark.extend');
548  
-
549  
-  (function() {
550  
-    test('allows no source argument', function() {
551  
-      var object = {};
552  
-      equal(Benchmark.extend(object), object);
553  
-    });
554  
-
555  
-    test('allows a single source argument', function() {
556  
-      var source = { 'x': 1, 'y': 1 },
557  
-          actual = Benchmark.extend({}, source);
558  
-
559  
-      deepEqual(Benchmark.extend({}, source), { 'x': 1, 'y': 1 });
560  
-    });
561  
-
562  
-    test('allows multiple source arguments', function() {
563  
-      var source1 = { 'x': 1, 'y': 1 },
564  
-          source2 = { 'y': 2, 'z': 2 },
565  
-          actual = Benchmark.extend({}, source1, source2);
566  
-
567  
-      deepEqual(actual, { 'x': 1, 'y': 2, 'z': 2 });
568  
-    });
569  
-
570  
-    test('will add inherited source properties', function() {
571  
-      function Source() { }
572  
-      Source.prototype.x = 1;
573  
-      deepEqual(Benchmark.extend({}, new Source), { 'x': 1 });
574  
-    });
575  
-
576  
-    test('will add problem JScript properties', function() {
577  
-      deepEqual(Benchmark.extend({}, shadowed), shadowed);
578  
-    });
579  
-  }());
580  
-
581  
-  /*--------------------------------------------------------------------------*/
582  
-
583 239
   QUnit.module('Benchmark.filter');
584 240
 
585 241
   (function() {
586 242
     var objects = {
587 243
       'array': ['a', 'b', 'c', ''],
588  
-      'array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 }
  244
+      'array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 4 }
589 245
     };
590 246
 
591  
-    objects.array.length = 5;
592  
-
593  
-    forOwn(objects, function(object, key) {
  247
+    _.forOwn(objects, function(object, key) {
594 248
       test('passes the correct arguments when passing an ' + key, function() {
595 249
         var args;
596 250
         Benchmark.filter(object, function() {
@@ -607,122 +261,11 @@
607 261
 
608 262
         deepEqual(actual, ['b', 'c', '']);
609 263
       });
610  
-
611  
-      test('iterates over sparse ' + key + 's correctly', function() {
612  
-        var actual = Benchmark.filter(object, function(value) {
613  
-          return value === undefined;
614  
-        });
615  
-
616  
-        deepEqual(actual, []);
617  
-      });
618 264
     });
619 265
   }());
620 266
 
621 267
   /*--------------------------------------------------------------------------*/
622 268
 
623  
-  QUnit.module('Benchmark.forOwn');
624  
-
625  
-  (function() {
626  
-    function fn() {
627  
-      // no-op
628  
-    }
629  
-
630  
-    function KlassA() {
631  
-      this.a = 1;
632  
-      this.b = 2;
633  
-      this.c = 3;
634  
-    }
635  
-
636  
-    function KlassB() {
637  
-      this.a = 1;
638  
-      this.constructor = 2;
639  
-      this.hasOwnProperty = 3;
640  
-      this.isPrototypeOf = 4;
641  
-      this.propertyIsEnumerable = 5;
642  
-      this.toLocaleString = 6;
643  
-      this.toString = 7;
644  
-      this.valueOf = 8;
645  
-    }
646  
-
647  
-    function KlassC() {
648  
-      // no-op
649  
-    }
650  
-
651  
-    fn.a = 1;
652  
-    fn.b = 2;
653  
-    fn.c = 3;
654  
-
655  
-    KlassC.prototype.a = 1;
656  
-    KlassC.prototype.b = 2;
657  
-    KlassC.prototype.c = 3;
658  
-
659  
-    var objects = {
660  
-      'an arguments object': arguments,
661  
-      'a function': fn,
662  
-      'an object': new KlassA,
663  
-      'an object shadowing properties on Object.prototype': new KlassB,
664  
-      'a prototype object': KlassC.prototype,
665  
-      'a string': 'abc'
666  
-    };
667  
-
668  
-    forOwn(objects, function(object, key) {
669  
-      test('passes the correct arguments when passing ' + key, function() {
670  
-        var args;
671  
-        Benchmark.forOwn(object, function() {
672  
-          args || (args = slice.call(arguments));
673  
-        });
674  
-
675  
-        equal(typeof args[0], key == 'a string' ? 'string' : 'number');
676  
-        equal(typeof args[1], 'string');
677  
-        equal(args[2] && typeof args[2], key == 'a function' ? 'function' : 'object');
678  
-      });
679  
-
680  
-      test('returns the passed object when passing ' + key, function() {
681  
-        var actual = Benchmark.forOwn(object, function() { });
682  
-        deepEqual(actual, object);
683  
-      });
684  
-
685  
-      test('iterates over own properties when passing ' + key, function() {
686  
-        var values = [];
687  
-        Benchmark.forOwn(object, function(value) {
688  
-          values.push(value);
689  
-        });
690  
-
691  
-        if (object instanceof KlassB) {
692  
-          deepEqual(values.sort(), [1, 2, 3, 4, 5, 6, 7, 8]);
693  
-        } else if (key == 'a string') {
694  
-          deepEqual(values, ['a', 'b', 'c']);
695  
-        } else {
696  
-          deepEqual(values.sort(), [1, 2, 3]);
697  
-        }
698  
-      });
699  
-
700  
-      test('exits early when returning `false` when passing ' + key, function() {
701  
-        var values = [];
702  
-        Benchmark.forOwn(object, function(value) {
703  
-          values.push(value);
704  
-          return false;
705  
-        });
706  
-
707  
-        equal(values.length, 1);
708  
-      });
709  
-
710  
-      if (object instanceof KlassB) {
711  
-        test('exits correctly when transitioning to the JScript [[DontEnum]] fix', function() {
712  
-          var values = [];
713  
-          Benchmark.forOwn(object, function(value) {
714  
-            values.push(value);
715  
-            return values.length < 2;
716  
-          });
717  
-
718  
-          equal(values.length, 2);
719  
-        });
720  
-      }
721  
-    });
722  
-  }(1, 2, 3));
723  
-
724  
-  /*--------------------------------------------------------------------------*/
725  
-
726 269
   QUnit.module('Benchmark.formatNumber');
727 270
 
728 271
   (function() {
@@ -745,132 +288,23 @@
745 288
 
746 289
   /*--------------------------------------------------------------------------*/
747 290
 
748  
-  QUnit.module('Benchmark.hasKey');
749  
-
750  
-  (function() {
751  
-    test('returns `true` for own properties', function() {
752  
-      var object = { 'x': 1 };
753  
-      equal(Benchmark.hasKey(object, 'x'), true);
754  
-    });
755  
-
756  
-    test('returns `false` for inherited properties', function() {
757  
-      equal(Benchmark.hasKey({}, 'toString'), false);
758  
-    });
759  
-
760  
-    test('doesn\'t use an object\'s `hasOwnProperty` method', function() {
761  
-      var object = { 'hasOwnProperty': function() { return true; } };
762  
-      equal(Benchmark.hasKey(object, 'x'), false);
763  
-    });
764  
-  }());
765  
-
766  
-  /*--------------------------------------------------------------------------*/
767  
-
768  
-  QUnit.module('Benchmark.indexOf');
769  
-
770  
-  (function() {
771  
-    var objects = {
772  
-      'array': ['a', 'b', 'c', ''],
773  
-      'array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 }
774  
-    };
775  
-
776  
-    objects.array.length = 5;
777  
-
778  
-    forOwn(objects, function(object, key) {
779  
-      test('produces the correct result when passing an ' + key, function() {
780  
-        equal(Benchmark.indexOf(object, 'b'), 1);
781  
-      });
782  
-
783  
-      test('matches values by strict equality when passing an ' + key, function() {
784  
-        equal(Benchmark.indexOf(object, new String('b')), -1);
785  
-      });
786  
-
787  
-      test('iterates over sparse ' + key + 's correctly', function() {
788  
-        equal(Benchmark.indexOf(object, undefined), -1);
789  
-      });
790  
-    });
791  
-
792  
-    test('searches from the given `fromIndex`', function() {
793  
-      var array = ['a', 'b', 'c', 'a'];
794  
-      equal(Benchmark.indexOf(array, 'a', 1), 3);
795  
-    });
796  
-
797  
-    test('handles extreme negative `fromIndex` values correctly', function() {
798  
-      var array = ['a'];
799  
-      array['-1'] = 'z';
800  
-      equal(Benchmark.indexOf(array, 'z', -2), -1);
801  
-    });
802  
-
803  
-    test('handles extreme positive `fromIndex` values correctly', function() {
804  
-      var object = { '0': 'a', '1': 'b', '2': 'c', 'length': 2 };
805  
-      equal(Benchmark.indexOf(object, 'c', 2), -1);
806  
-    });
807  
-  }());
808  
-
809  
-  /*--------------------------------------------------------------------------*/
810  
-
811  
-  QUnit.module('Benchmark.interpolate');
812  
-
813  
-  (function() {
814  
-    test('replaces tokens correctly', function() {
815  
-      var actual = Benchmark.interpolate('#{greeting} #{location}.', {
816  
-        'greeting': 'Hello',
817  
-        'location': 'world'
818  
-      });
819  
-
820  
-      equal(actual, 'Hello world.');
821  
-    });
822  
-
823  
-    test('ignores inherited object properties', function() {
824  
-      var actual = Benchmark.interpolate('x#{toString}', {});
825  
-      equal(actual, 'x#{toString}');
826  
-    });
827  
-
828  
-    test('allows for no template object', function() {
829  
-      var actual = Benchmark.interpolate('x');
830  
-      equal(actual, 'x');
831  
-    });
832  
-
833  
-    test('replaces duplicate tokens', function() {
834  
-      var actual = Benchmark.interpolate('#{x}#{x}#{x}', { 'x': 'a' });
835  
-      equal(actual, 'aaa');
836  
-    });
837  
-
838  
-    test('handles keys containing RegExp special characters', function() {
839  
-      var actual = Benchmark.interpolate('#{.*+?^=!:${}()|[]\\/}', { '.*+?^=!:${}()|[]\\/': 'x' });
840  
-      equal(actual, 'x');
841  
-    });
842  
-
843  
-    test('handles values containing `$` patterns', function() {
844  
-      var expected = "$$,$&,$`,$',$0",
845  
-          actual = Benchmark.interpolate('#{x}', { 'x': expected });
846  
-
847  
-      equal(actual, expected);
848  
-    });
849  
-  }());
850  
-
851  
-  /*--------------------------------------------------------------------------*/
852  
-
853 291
   QUnit.module('Benchmark.invoke');
854 292
 
855 293
   (function() {
856 294
     var objects = {
857 295
       'array': ['a', ['b'], 'c', null],
858  
-      'array-like-object': { '0': 'a', '1': ['b'], '2': 'c',  '3': null, 'length': 5 }
  296
+      'array-like-object': { '0': 'a', '1': ['b'], '2': 'c',  '3': null, 'length': 4 }
859 297
     };
860 298
 
861  
-    objects.array.length = 5;
862  
-
863  
-    forOwn(objects, function(object, key) {
  299
+    _.forOwn(objects, function(object, key) {
864 300
       test('produces the correct result when passing an ' + key, function() {
865 301
         var actual = Benchmark.invoke(object, 'concat');
866  
-        deepEqual(actual, ['a', ['b'], 'c', undefined, undefined]);
867  
-        equal('4' in actual, false);
  302
+        deepEqual(actual, ['a', ['b'], 'c', undefined]);
868 303
       });
869 304
 
870 305
       test('passes the correct arguments to the invoked method when passing an ' + key, function() {
871 306
         var actual = Benchmark.invoke(object, 'concat', 'x', 'y', 'z');
872  
-        deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined, undefined]);
873  
-        equal('4' in actual, false);
  307
+        deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined]);
874 308
       });
875 309
 
876 310
       test('handles options object with callbacks correctly when passing an ' + key, function() {
@@ -887,8 +321,7 @@
887 321
           'onComplete': callback
888 322
         });
889 323
 
890  
-        deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined, undefined]);
891  
-        equal('4' in actual, false);
  324
+        deepEqual(actual, ['axyz', ['b', 'x', 'y', 'z'], 'cxyz', undefined]);
892 325
 
893 326
         equal(callbacks[0].length, 1);
894 327
         equal(callbacks[0][0].target, 'a');
@@ -909,8 +342,8 @@
909 342
           }
910 343
         });
911 344
 
912  
-        deepEqual(lengths, [5, 4, 3, 2]);
913  
-        deepEqual(actual, ['ax', ['b', 'x'], 'cx', undefined, undefined]);
  345
+        deepEqual(lengths, [4, 3, 2, 1]);
  346
+        deepEqual(actual, ['ax', ['b', 'x'], 'cx', undefined]);
914 347
       });
915 348
     });
916 349
   }());
@@ -922,13 +355,11 @@
922 355
   (function() {
923 356
     var objects = {
924 357
       'array': ['a', 'b', ''],
925  
-      'array-like-object': { '0': 'a', '1': 'b', '2': '', 'length': 4 },
  358
+      'array-like-object': { '0': 'a', '1': 'b', '2': '', 'length': 3 },
926 359
       'object': { 'a': '0', 'b': '1', '': '2' }
927 360
     };
928 361
 
929  
-    objects.array.length = 4;
930  
-
931  
-    forOwn(objects, function(object, key) {
  362
+    _.forOwn(objects, function(object, key) {
932 363
       test('joins correctly using the default separator when passing an ' + key, function() {
933 364
         equal(Benchmark.join(object), key == 'object' ? 'a: 0,b: 1,: 2' : 'a,b,');
934 365
       });
@@ -941,111 +372,6 @@
941 372
 
942 373
   /*--------------------------------------------------------------------------*/
943 374
 
944  
-  QUnit.module('Benchmark.map');
945  
-
946  
-  (function() {
947  
-    var objects = {
948  
-      'array': ['a', 'b', 'c', ''],
949  
-      'array-like-object': { '0': 'a', '1': 'b', '2': 'c',  '3': '', 'length': 5 }
950  
-    };
951  
-
952  
-    objects.array.length = 5;
953  
-
954  
-    forOwn(objects, function(object, key) {
955  
-      test('passes the correct arguments when passing an ' + key, function() {
956  
-        var args;
957  
-        Benchmark.map(object, function() {
958  
-          args || (args = slice.call(arguments));
959  
-        });
960  
-
961  
-        deepEqual(args, ['a', 0, object]);
962  
-      });
963  
-
964  
-      test('produces the correct result when passing an ' + key, function() {
965  
-        var actual = Benchmark.map(object, function(value, index) {
966  
-          return value + index;
967  
-        });
968  
-
969  
-        deepEqual(actual, ['a0', 'b1', 'c2', '3', undefined]);
970  
-        equal('4' in actual, false);
971  
-      });
972  
-
973  
-      test('produces an array of the correct length for sparse ' + key + 's', function() {
974  
-        equal(Benchmark.map(object, function() { }).length, 5);
975  
-      });
976  
-    });
977  
-  }());
978  
-
979  
-  /*--------------------------------------------------------------------------*/
980  
-
981  
-  QUnit.module('Benchmark.pluck');
982  
-
983  
-  (function() {
984  
-    var objects = {
985  
-      'array': [{ '_': 'a' }, { '_': 'b' }, { '_': 'c' }, null],
986  
-      'array-like-object': { '0': { '_': 'a' }, '1': { '_': 'b' }, '2': { '_': 'c' },  '3': null, 'length': 5 }
987  
-    };
988  
-
989  
-    objects.array.length = 5;
990  
-
991  
-    forOwn(objects, function(object, key) {
992  
-      test('produces the correct result when passing an ' + key, function() {
993  
-        var actual = Benchmark.pluck(object, '_');
994  
-        deepEqual(actual, ['a', 'b', 'c', undefined, undefined]);
995  
-        equal('4' in actual, false);
996  
-      });
997  
-
998  
-      test('produces the correct result for non-existent keys when passing an ' + key, function() {
999  
-        var actual = Benchmark.pluck(object, 'non-existent');
1000  
-        deepEqual(actual, [undefined, undefined, undefined, undefined, undefined]);
1001  
-        equal('4' in actual, false);
1002  
-      });
1003  
-    });
1004  
-  }());
1005  
-
1006  
-  /*--------------------------------------------------------------------------*/
1007  
-
1008  
-  QUnit.module('Benchmark.reduce');
1009  
-
1010  
-  (function() {
1011  
-    var objects = {
1012  
-      'array': ['b', 'c', ''],
1013  
-      'array-like-object': { '0': 'b', '1': 'c',  '2': '', 'length': 4 }
1014  
-    };
1015  
-
1016  
-    objects.array.length = 4;
1017  
-
1018  
-    forOwn(objects, function(object, key) {
1019  
-      test('passes the correct arguments when passing an ' + key, function() {
1020  
-        var args;
1021  
-        Benchmark.reduce(object, function() {
1022  
-          args || (args = slice.call(arguments));
1023  
-        }, 'a');
1024  
-
1025  
-        deepEqual(args, ['a', 'b', 0, object]);
1026  
-      });
1027  
-
1028  
-      test('accumulates correctly when passing an ' + key, function() {
1029  
-        var actual = Benchmark.reduce(object, function(string, value) {
1030  
-          return string + value;
1031  
-        }, 'a');
1032  
-
1033  
-        equal(actual, 'abc');
1034  
-      });
1035  
-
1036  
-      test('handles arguments with no initial value correctly when passing an ' + key, function() {
1037  
-        var args;
1038  
-        Benchmark.reduce(object, function() {
1039  
-          args || (args = slice.call(arguments));
1040  
-        });
1041  
-
1042  
-        deepEqual(args, ['b', 'c', 1, object]);
1043  
-      });
1044  
-    });
1045  
-  }());
1046  
-
1047  
-  /*--------------------------------------------------------------------------*/
1048  
-
1049 375
   QUnit.module('Benchmark#clone');
1050 376
 
1051 377
   (function() {
@@ -1092,7 +418,7 @@
1092 418
 
1093 419
   /*--------------------------------------------------------------------------*/
1094 420
 
1095  
-  forOwn({
  421
+  _.forOwn({
1096 422
     'Benchmark': Benchmark,
1097 423
     'Benchmark.Suite': Benchmark.Suite
1098 424
   },
@@ -1484,96 +810,6 @@
1484 810
 
1485 811
   /*--------------------------------------------------------------------------*/
1486 812
 
1487  
-  QUnit.module('Benchmark.Suite#score');
1488  
-
1489  
-  (function() {
1490  
-    asyncTest('should compute a score', function() {
1491  
-      Benchmark.Suite()
1492  
-        .add('a', {
1493  
-          'reference': 120.35,
1494  
-          'fn': function() {
1495  
-            var array = [];
1496  
-            for (var index = 0; index < 1e3; index++) {
1497  
-              array.push(index % 2 ? String(index) : index);
1498  
-            }
1499  
-          }
1500  
-        })
1501  
-        .add('b', {
1502  
-          'reference': 360.95,
1503  
-          'fn': function() {
1504  
-            var array = [];
1505  
-            for (var index = 0; index < 3e3; index++) {
1506  
-              array.push(index % 2 ? String(index) : index);
1507  
-            }
1508  
-          }
1509  
-        })
1510  
-        .add('c', {
1511  
-          'reference': 720.10,
1512  
-          'fn': function() {
1513  
-            var array = [];
1514  
-            for (var index = 0; index < 6e3; index++) {
1515  
-              array.push(index % 2 ? String(index) : index);
1516  
-            }
1517  
-          }
1518  
-        })
1519  
-        .on('complete', function() {
1520  
-          var score = this.score;
1521  
-          ok(score && typeof score == 'number');
1522  
-          QUnit.start();
1523  
-        })
1524  
-        .run({ 'async': true });
1525  
-    });
1526  
-  }());
1527  
-
1528  
-  /*--------------------------------------------------------------------------*/
1529  
-
1530  
-  QUnit.module('Benchmark.Suite#concat');
1531  
-
1532  
-  (function() {
1533  
-    var args = arguments;
1534  
-
1535  
-    test('doesn\'t treat an arguments object like an array', function() {
1536  
-      var suite = Benchmark.Suite();
1537  
-      deepEqual(suite.concat(args), [args]);
1538  
-    });
1539  
-
1540  
-    test('flattens array arguments', function() {
1541  
-      var suite = Benchmark.Suite();
1542  
-      deepEqual(suite.concat([1, 2], 3, [4, 5]), [1, 2, 3, 4, 5]);
1543  
-    });
1544  
-
1545  
-    test('supports concating sparse arrays', function() {
1546  
-      var suite = Benchmark.Suite();
1547  
-      suite[0] = 0;
1548  
-      suite[2] = 2;
1549  
-      suite.length = 3;
1550  
-
1551  
-      var actual = suite.concat(3);
1552  
-      deepEqual(actual, [0, undefined, 2, 3]);
1553  
-      equal('1' in actual, false);
1554  
-    });
1555  
-
1556  
-    test('supports sparse arrays as arguments', function() {
1557  
-      var suite = Benchmark.Suite(),
1558  
-          sparse = [];
1559  
-
1560  
-      sparse[0] = 0;
1561  
-      sparse[2] = 2;
1562  
-      sparse.length = 3;
1563  
-
1564  
-      var actual = suite.concat(sparse);
1565  
-      deepEqual(actual, [0, undefined, 2]);
1566  
-      equal('1' in actual, false);
1567  
-    });
1568  
-
1569  
-    test('creates a new array', function() {
1570  
-      var suite = Benchmark.Suite();
1571  
-      ok(suite.concat(1) !== suite);
1572  
-    });
1573  
-  }(1, 2, 3));
1574  
-
1575  
-  /*--------------------------------------------------------------------------*/
1576  
-
1577 813
   QUnit.module('Benchmark.Suite#reverse');
1578 814
 
1579 815
   (function() {
@@ -1587,18 +823,6 @@
1587 823
       equal(actual, suite);
1588 824
       deepEqual(slice.call(actual), [1, 0]);
1589 825
     });
1590  
-
1591  
-    test('supports reversing sparse arrays', function() {
1592  
-      var suite = Benchmark.Suite();
1593  
-      suite[0] = 0;
1594  
-      suite[2] = 2;
1595  
-      suite.length = 3;
1596  
-
1597  
-      var actual = suite.reverse();
1598  
-      equal(actual, suite);
1599  
-      deepEqual(slice.call(actual), [2, undefined, 0]);
1600  
-      equal('1' in actual, false);
1601  
-    });
1602 826
   }());
1603 827
 
1604 828
   /*--------------------------------------------------------------------------*/
@@ -1635,83 +859,6 @@
1635 859
       equal('0' in suite, false);
1636 860
       equal(suite.length, 0);
1637 861
     });
1638  
-
1639  
-    test('supports shifting sparse arrays', function() {
1640  
-      var suite = Benchmark.Suite();
1641  
-      suite[1] = 1;
1642  
-      suite[3] = 3;
1643  
-      suite.length = 4;
1644  
-
1645  
-      var actual = suite.shift();
1646  
-      equal(actual, undefined);
1647  
-      deepEqual(slice.call(suite), [1, undefined, 3]);
1648  
-      equal('1' in suite, false);
1649  
-    });
1650  
-  }());
1651  
-
1652  
-  /*--------------------------------------------------------------------------*/
1653  
-
1654  
-  QUnit.module('Benchmark.Suite#slice');
1655  
-
1656  
-  (function() {
1657  
-    var suite = Benchmark.Suite();
1658  
-    suite[0] = 0;
1659  
-    suite[1] = 1;
1660  
-    suite[2] = 2;
1661  
-    suite[3] = 3;
1662  
-    suite.length = 4;
1663  
-
1664  
-    test('works with no arguments', function() {
1665  
-      var actual = suite.slice();
1666  
-      deepEqual(actual, [0, 1, 2, 3]);
1667  
-      ok(suite !== actual);
1668  
-    });
1669  
-
1670  
-    test('works with positive `start` argument', function() {
1671  
-      var actual = suite.slice(2);
1672  
-      deepEqual(actual, [2, 3]);
1673  
-      ok(suite !== actual);
1674  
-    });
1675  
-
1676  
-    test('works with positive `start` and `end` arguments', function() {
1677  
-      var actual = suite.slice(1, 3);
1678  
-      deepEqual(actual, [1, 2]);
1679  
-      ok(suite !== actual);
1680  
-    });
1681  
-
1682  
-    test('works with `end` values exceeding length', function() {
1683  
-      var actual = suite.slice(1, 10);
1684  
-      deepEqual(actual, [1, 2, 3]);
1685  
-      ok(suite !== actual);
1686  
-    });
1687  
-
1688  
-    test('works with negative `start` and `end` arguments', function() {
1689  
-      var actual = suite.slice(-3, -1);
1690  
-      deepEqual(actual, [1, 2]);
1691  
-      ok(suite !== actual);
1692  
-    });
1693  
-
1694  
-    test('works with an extreme negative `end` value', function() {
1695  
-      var actual = suite.slice(1, -10);
1696  
-      deepEqual(actual, []);
1697  
-      equal('-1' in actual, false);
1698  
-      ok(suite !== actual);
1699  
-    });
1700  
-
1701  
-    test('supports slicing sparse arrays', function() {
1702  
-      var sparse = Benchmark.Suite();
1703  
-      sparse[1] = 1;
1704  
-      sparse[3] = 3;
1705  
-      sparse.length = 4;
1706  
-
1707  
-      var actual = sparse.slice(0, 2);
1708  
-      deepEqual(actual, [undefined, 1]);
1709  
-      equal('0' in actual, false);
1710  
-
1711  
-      actual = sparse.slice(1);
1712  
-      deepEqual(actual, [1, undefined, 3]);
1713  
-      equal('1' in actual, false);
1714  
-    });
1715 862
   }());
1716 863
 
1717 864
   /*--------------------------------------------------------------------------*/
@@ -1805,19 +952,6 @@
1805 952
       deepEqual(actual, []);
1806 953
       deepEqual(slice.call(suite), [1, 2, 0, 3]);
1807 954
     });
1808  
-
1809  
-    test('supports splicing sparse arrays', function() {
1810  
-      var suite = Benchmark.Suite();
1811  
-      suite[1] = 1;
1812  
-      suite[3] = 3;
1813  
-      suite.length = 4;
1814  
-
1815  
-      var actual = suite.splice(1, 2, 1, 2);
1816  
-      deepEqual(actual, [1, undefined]);
1817  
-      equal(actual.length, 2);
1818  
-      deepEqual(slice.call(suite), [undefined, 1, 2, 3]);
1819  
-      equal('0' in suite, false);
1820  
-    });
1821 955
   }());
1822 956
 
1823 957
   /*--------------------------------------------------------------------------*/
@@ -1844,17 +978,6 @@
1844 978
       equal(actual, 4);
1845 979
       deepEqual(slice.call(suite), [0, 1, 2, 3]);
1846 980
     });
1847  
-
1848  
-    test('supports unshifting sparse arrays', function() {
1849  
-      var suite = Benchmark.Suite();
1850  
-      suite[1] = 2;
1851  
-      suite.length = 2;
1852  
-
1853  
-      var actual = suite.unshift(0);
1854  
-      equal(actual, 3);
1855  
-      deepEqual(slice.call(suite), [0, undefined, 2]);
1856  
-      equal('1' in suite, false);
1857  
-    });
1858 981
   }());
1859 982
 
1860 983
   /*--------------------------------------------------------------------------*/
@@ -1880,7 +1003,7 @@
1880 1003
     asyncTest('should filter by fastest', function() {
1881 1004
       suite.on('complete', function() {
1882 1005
         suite.off();
1883  
-        deepEqual(this.filter('fastest').pluck('name'), ['a']);
  1006
+        deepEqual(_.pluck(this.filter('fastest'), 'name'), ['a']);
1884 1007
         QUnit.start();
1885 1008
       })
1886 1009
       .run({ 'async': true });
@@ -1889,7 +1012,7 @@
1889 1012
     asyncTest('should filter by slowest', function() {
1890 1013
       suite.on('complete', function() {
1891 1014
         suite.off();
1892  
-        deepEqual(this.filter('slowest').pluck('name'), ['b']);
  1015
+        deepEqual(_.pluck(this.filter('slowest'), 'name'), ['b']);
1893 1016
         QUnit.start();
1894 1017
       })
1895 1018
       .run({ 'async': true });
@@ -1898,7 +1021,7 @@
1898 1021
     asyncTest('should filter by successful', function() {
1899 1022
       suite.on('complete', function() {
1900 1023
         suite.off();
1901  
-        deepEqual(this.filter('successful').pluck('name'), ['a', 'b']);
  1024
+        deepEqual(_.pluck(this.filter('successful'), 'name'), ['a', 'b']);
1902 1025
         QUnit.start();
1903 1026
       })
1904 1027
       .run({ 'async': true });
@@ -2080,45 +1203,8 @@
2080 1203
 
2081 1204
   /*--------------------------------------------------------------------------*/
2082 1205
 
2083  
-  QUnit.module('Benchmark.deepClone');
2084  
-
2085  
-  (function() {
2086  
-    asyncTest('avoids call stack limits', function() {
2087  
-      var result,
2088  
-          count = 0,
2089  
-          object = {},
2090  
-          recurse = function() { count++; recurse(); };
2091  
-
2092  
-      setTimeout(function() {
2093  
-        ok(result, 'avoids call stack limits (stack limit is ' + (count - 1) + ')');
2094  
-        QUnit.start();
2095  
-      }, 15);
2096  
-
2097  
-      if (toString.call(window.java) == '[object JavaPackage]') {
2098  
-        // Java throws uncatchable errors on call stack overflows, so to avoid
2099  
-        // them I chose a number higher than Rhino's call stack limit without
2100  
-        // dynamically testing for the actual limit
2101  
-        count = 3e3;
2102  
-      } else {
2103  
-        try { recurse(); } catch(e) { }
2104  
-      }
2105  
-
2106  
-      // exceed limit
2107  
-      count++;
2108  
-      for (var i = 0, sub = object; i <= count; i++) {
2109  
-        sub = sub[i] = {};
2110  
-      }
2111  
-
2112  
-      try {
2113  
-        for (var i = 0, sub = Benchmark.deepClone(object); sub = sub[i]; i++) { }
2114  
-        result = --i == count;
2115  
-      } catch(e) { }
2116  
-    });