1(function(global, factory) {
2  /*jshint -W030 */
3  'use strict';
4  typeof exports === 'object' && typeof module !== 'undefined'
5    ? factory(exports)
6    : typeof define === 'function' && define.amd
7    ? define(['exports'], factory)
8    : global.async
9    ? factory((global.neo_async = global.neo_async || {}))
10    : factory((global.async = global.async || {}));
11})(this, function(exports) {
12  'use strict';
13
14  var noop = function noop() {};
15  var throwError = function throwError() {
16    throw new Error('Callback was already called.');
17  };
18
19  var DEFAULT_TIMES = 5;
20  var DEFAULT_INTERVAL = 0;
21
22  var obj = 'object';
23  var func = 'function';
24  var isArray = Array.isArray;
25  var nativeKeys = Object.keys;
26  var nativePush = Array.prototype.push;
27  var iteratorSymbol = typeof Symbol === func && Symbol.iterator;
28
29  var nextTick, asyncNextTick, asyncSetImmediate;
30  createImmediate();
31
32  /**
33   * @memberof async
34   * @namespace each
35   * @param {Array|Object} collection
36   * @param {Function} iterator
37   * @param {Function} callback
38   * @example
39   *
40   * // array
41   * var order = [];
42   * var array = [1, 3, 2];
43   * var iterator = function(num, done) {
44   *   setTimeout(function() {
45   *     order.push(num);
46   *     done();
47   *   }, num * 10);
48   * };
49   * async.each(array, iterator, function(err, res) {
50   *   console.log(res); // undefined
51   *   console.log(order); // [1, 2, 3]
52   * });
53   *
54   * @example
55   *
56   * // array with index
57   * var order = [];
58   * var array = [1, 3, 2];
59   * var iterator = function(num, index, done) {
60   *   setTimeout(function() {
61   *     order.push([num, index]);
62   *     done();
63   *   }, num * 10);
64   * };
65   * async.each(array, iterator, function(err, res) {
66   *   console.log(res); // undefined
67   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
68   * });
69   *
70   * @example
71   *
72   * // object
73   * var order = [];
74   * var object = { a: 1, b: 3, c: 2 };
75   * var iterator = function(num, done) {
76   *   setTimeout(function() {
77   *     order.push(num);
78   *     done();
79   *   }, num * 10);
80   * };
81   * async.each(object, iterator, function(err, res) {
82   *   console.log(res); // undefined
83   *   console.log(order); // [1, 2, 3]
84   * });
85   *
86   * @example
87   *
88   * // object with key
89   * var order = [];
90   * var object = { a: 1, b: 3, c: 2 };
91   * var iterator = function(num, key, done) {
92   *   setTimeout(function() {
93   *     order.push([num, key]);
94   *     done();
95   *   }, num * 10);
96   * };
97   * async.each(object, iterator, function(err, res) {
98   *   console.log(res); // undefined
99   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
100   * });
101   *
102   * @example
103   *
104   * // break
105   * var order = [];
106   * var array = [1, 3, 2];
107   * var iterator = function(num, done) {
108   *   setTimeout(function() {
109   *     order.push(num);
110   *     done(null, num !== 2);
111   *   }, num * 10);
112   * };
113   * async.each(array, iterator, function(err, res) {
114   *   console.log(res); // undefined
115   *   console.log(order); // [1, 2]
116   * });
117   *
118   */
119  var each = createEach(arrayEach, baseEach, symbolEach);
120
121  /**
122   * @memberof async
123   * @namespace map
124   * @param {Array|Object} collection
125   * @param {Function} iterator
126   * @param {Function} callback
127   * @example
128   *
129   * // array
130   * var order = [];
131   * var array = [1, 3, 2];
132   * var iterator = function(num, done) {
133   *   setTimeout(function() {
134   *     order.push(num);
135   *     done(null, num);
136   *   }, num * 10);
137   * };
138   * async.map(array, iterator, function(err, res) {
139   *   console.log(res); // [1, 3, 2];
140   *   console.log(order); // [1, 2, 3]
141   * });
142   *
143   * @example
144   *
145   * // array with index
146   * var order = [];
147   * var array = [1, 3, 2];
148   * var iterator = function(num, index, done) {
149   *   setTimeout(function() {
150   *     order.push([num, index]);
151   *     done(null, num);
152   *   }, num * 10);
153   * };
154   * async.map(array, iterator, function(err, res) {
155   *   console.log(res); // [1, 3, 2]
156   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
157   * });
158   *
159   * @example
160   *
161   * // object
162   * var order = [];
163   * var object = { a: 1, b: 3, c: 2 };
164   * var iterator = function(num, done) {
165   *   setTimeout(function() {
166   *     order.push(num);
167   *     done(null, num);
168   *   }, num * 10);
169   * };
170   * async.map(object, iterator, function(err, res) {
171   *   console.log(res); // [1, 3, 2]
172   *   console.log(order); // [1, 2, 3]
173   * });
174   *
175   * @example
176   *
177   * // object with key
178   * var order = [];
179   * var object = { a: 1, b: 3, c: 2 };
180   * var iterator = function(num, key, done) {
181   *   setTimeout(function() {
182   *     order.push([num, key]);
183   *     done(null, num);
184   *   }, num * 10);
185   * };
186   * async.map(object, iterator, function(err, res) {
187   *   console.log(res); // [1, 3, 2]
188   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
189   * });
190   *
191   */
192  var map = createMap(arrayEachIndex, baseEachIndex, symbolEachIndex, true);
193
194  /**
195   * @memberof async
196   * @namespace mapValues
197   * @param {Array|Object} collection
198   * @param {Function} iterator
199   * @param {Function} callback
200   * @example
201   *
202   * // array
203   * var order = [];
204   * var array = [1, 3, 2];
205   * var iterator = function(num, done) {
206   *   setTimeout(function() {
207   *     order.push(num);
208   *     done(null, num);
209   *   }, num * 10);
210   * };
211   * async.mapValues(array, iterator, function(err, res) {
212   *   console.log(res); // { '0': 1, '1': 3, '2': 2 }
213   *   console.log(order); // [1, 2, 3]
214   * });
215   *
216   * @example
217   *
218   * // array with index
219   * var order = [];
220   * var array = [1, 3, 2];
221   * var iterator = function(num, index, done) {
222   *   setTimeout(function() {
223   *     order.push([num, index]);
224   *     done(null, num);
225   *   }, num * 10);
226   * };
227   * async.mapValues(array, iterator, function(err, res) {
228   *   console.log(res); // { '0': 1, '1': 3, '2': 2 }
229   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
230   * });
231   *
232   * @example
233   *
234   * // object
235   * var order = [];
236   * var object = { a: 1, b: 3, c: 2 };
237   * var iterator = function(num, done) {
238   *   setTimeout(function() {
239   *     order.push(num);
240   *     done(null, num);
241   *   }, num * 10);
242   * };
243   * async.mapValues(object, iterator, function(err, res) {
244   *   console.log(res); // { a: 1, b: 3, c: 2 }
245   *   console.log(order); // [1, 2, 3]
246   * });
247   *
248   * @example
249   *
250   * // object with key
251   * var order = [];
252   * var object = { a: 1, b: 3, c: 2 };
253   * var iterator = function(num, key, done) {
254   *   setTimeout(function() {
255   *     order.push([num, key]);
256   *     done(null, num);
257   *   }, num * 10);
258   * };
259   * async.mapValues(object, iterator, function(err, res) {
260   *   console.log(res); // { a: 1, b: 3, c: 2 }
261   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
262   * });
263   *
264   */
265  var mapValues = createMap(arrayEachIndex, baseEachKey, symbolEachKey, false);
266
267  /**
268   * @memberof async
269   * @namespace filter
270   * @param {Array|Object} collection
271   * @param {Function} iterator
272   * @param {Function} callback
273   * @example
274   *
275   * // array
276   * var order = [];
277   * var array = [1, 3, 2];
278   * var iterator = function(num, done) {
279   *   setTimeout(function() {
280   *     order.push(num);
281   *     done(null, num % 2);
282   *   }, num * 10);
283   * };
284   * async.filter(array, iterator, function(err, res) {
285   *   console.log(res); // [1, 3];
286   *   console.log(order); // [1, 2, 3]
287   * });
288   *
289   * @example
290   *
291   * // array with index
292   * var order = [];
293   * var array = [1, 3, 2];
294   * var iterator = function(num, index, done) {
295   *   setTimeout(function() {
296   *     order.push([num, index]);
297   *     done(null, num % 2);
298   *   }, num * 10);
299   * };
300   * async.filter(array, iterator, function(err, res) {
301   *   console.log(res); // [1, 3];
302   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
303   * });
304   *
305   * @example
306   *
307   * // object
308   * var order = [];
309   * var object = { a: 1, b: 3, c: 2 };
310   * var iterator = function(num, done) {
311   *   setTimeout(function() {
312   *     order.push(num);
313   *     done(null, num % 2);
314   *   }, num * 10);
315   * };
316   * async.filter(object, iterator, function(err, res) {
317   *   console.log(res); // [1, 3];
318   *   console.log(order); // [1, 2, 3]
319   * });
320   *
321   * @example
322   *
323   * // object with key
324   * var order = [];
325   * var object = { a: 1, b: 3, c: 2 };
326   * var iterator = function(num, key, done) {
327   *   setTimeout(function() {
328   *     order.push([num, key]);
329   *     done(null, num % 2);
330   *   }, num * 10);
331   * };
332   * async.filter(object, iterator, function(err, res) {
333   *   console.log(res); // [1, 3];
334   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
335   * });
336   *
337   */
338  var filter = createFilter(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue, true);
339
340  /**
341   * @memberof async
342   * @namespace filterSeries
343   * @param {Array|Object} collection
344   * @param {Function} iterator
345   * @param {Function} callback
346   * @example
347   *
348   * // array
349   * var order = [];
350   * var array = [1, 3, 2];
351   * var iterator = function(num, done) {
352   *   setTimeout(function() {
353   *     order.push(num);
354   *     done(null, num % 2);
355   *   }, num * 10);
356   * };
357   * async.filterSeries(array, iterator, function(err, res) {
358   *   console.log(res); // [1, 3];
359   *   console.log(order); // [1, 3, 2]
360   * });
361   *
362   * @example
363   *
364   * // array with index
365   * var order = [];
366   * var array = [1, 3, 2];
367   * var iterator = function(num, index, done) {
368   *   setTimeout(function() {
369   *     order.push([num, index]);
370   *     done(null, num % 2);
371   *   }, num * 10);
372   * };
373   * async.filterSeries(array, iterator, function(err, res) {
374   *   console.log(res); // [1, 3]
375   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
376   * });
377   *
378   * @example
379   *
380   * // object
381   * var order = [];
382   * var object = { a: 1, b: 3, c: 2 };
383   * var iterator = function(num, done) {
384   *   setTimeout(function() {
385   *     order.push(num);
386   *     done(null, num % 2);
387   *   }, num * 10);
388   * };
389   * async.filterSeries(object, iterator, function(err, res) {
390   *   console.log(res); // [1, 3]
391   *   console.log(order); // [1, 3, 2]
392   * });
393   *
394   * @example
395   *
396   * // object with key
397   * var order = [];
398   * var object = { a: 1, b: 3, c: 2 };
399   * var iterator = function(num, key, done) {
400   *   setTimeout(function() {
401   *     order.push([num, key]);
402   *     done(null, num % 2);
403   *   }, num * 10);
404   * };
405   * async.filterSeries(object, iterator, function(err, res) {
406   *   console.log(res); // [1, 3]
407   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
408   * });
409   *
410   */
411  var filterSeries = createFilterSeries(true);
412
413  /**
414   * @memberof async
415   * @namespace filterLimit
416   * @param {Array|Object} collection
417   * @param {number} limit - limit >= 1
418   * @param {Function} iterator
419   * @param {Function} callback
420   * @example
421   *
422   * // array
423   * var order = [];
424   * var array = [1, 5, 3, 4, 2];
425   * var iterator = function(num, done) {
426   *   setTimeout(function() {
427   *     order.push(num);
428   *     done(null, num % 2);
429   *   }, num * 10);
430   * };
431   * async.filterLimit(array, 2, iterator, function(err, res) {
432   *   console.log(res); // [1, 5, 3]
433   *   console.log(order); // [1, 3, 5, 2, 4]
434   * });
435   *
436   * @example
437   *
438   * // array with index
439   * var order = [];
440   * var array = [1, 5, 3, 4, 2];
441   * var iterator = function(num, index, done) {
442   *   setTimeout(function() {
443   *     order.push([num, index]);
444   *     done(null, num % 2);
445   *   }, num * 10);
446   * };
447   * async.filterLimit(array, 2, iterator, function(err, res) {
448   *   console.log(res); // [1, 5, 3]
449   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
450   * });
451   *
452   * @example
453   *
454   * // object
455   * var order = [];
456   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
457   * var iterator = function(num, done) {
458   *   setTimeout(function() {
459   *     order.push(num);
460   *     done(null, num % 2);
461   *   }, num * 10);
462   * };
463   * async.filterLimit(object, 2, iterator, function(err, res) {
464   *   console.log(res); // [1, 5, 3]
465   *   console.log(order); // [1, 3, 5, 2, 4]
466   * });
467   *
468   * @example
469   *
470   * // object with key
471   * var order = [];
472   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
473   * var iterator = function(num, key, done) {
474   *   setTimeout(function() {
475   *     order.push([num, key]);
476   *     done(null, num % 2);
477   *   }, num * 10);
478   * };
479   * async.filterLimit(object, 2, iterator, function(err, res) {
480   *   console.log(res); // [1, 5, 3]
481   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
482   * });
483   *
484   */
485  var filterLimit = createFilterLimit(true);
486
487  /**
488   * @memberof async
489   * @namespace reject
490   * @param {Array|Object} collection
491   * @param {Function} iterator
492   * @param {Function} callback
493   * @example
494   *
495   * // array
496   * var order = [];
497   * var array = [1, 3, 2];
498   * var iterator = function(num, done) {
499   *   setTimeout(function() {
500   *     order.push(num);
501   *     done(null, num % 2);
502   *   }, num * 10);
503   * };
504   * async.reject(array, iterator, function(err, res) {
505   *   console.log(res); // [2];
506   *   console.log(order); // [1, 2, 3]
507   * });
508   *
509   * @example
510   *
511   * // array with index
512   * var order = [];
513   * var array = [1, 3, 2];
514   * var iterator = function(num, index, done) {
515   *   setTimeout(function() {
516   *     order.push([num, index]);
517   *     done(null, num % 2);
518   *   }, num * 10);
519   * };
520   * async.reject(array, iterator, function(err, res) {
521   *   console.log(res); // [2];
522   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
523   * });
524   *
525   * @example
526   *
527   * // object
528   * var order = [];
529   * var object = { a: 1, b: 3, c: 2 };
530   * var iterator = function(num, done) {
531   *   setTimeout(function() {
532   *     order.push(num);
533   *     done(null, num % 2);
534   *   }, num * 10);
535   * };
536   * async.reject(object, iterator, function(err, res) {
537   *   console.log(res); // [2];
538   *   console.log(order); // [1, 2, 3]
539   * });
540   *
541   * @example
542   *
543   * // object with key
544   * var order = [];
545   * var object = { a: 1, b: 3, c: 2 };
546   * var iterator = function(num, key, done) {
547   *   setTimeout(function() {
548   *     order.push([num, key]);
549   *     done(null, num % 2);
550   *   }, num * 10);
551   * };
552   * async.reject(object, iterator, function(err, res) {
553   *   console.log(res); // [2];
554   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
555   * });
556   *
557   */
558  var reject = createFilter(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue, false);
559
560  /**
561   * @memberof async
562   * @namespace rejectSeries
563   * @param {Array|Object} collection
564   * @param {Function} iterator
565   * @param {Function} callback
566   * @example
567   *
568   * // array
569   * var order = [];
570   * var array = [1, 3, 2];
571   * var iterator = function(num, done) {
572   *   setTimeout(function() {
573   *     order.push(num);
574   *     done(null, num % 2);
575   *   }, num * 10);
576   * };
577   * async.rejectSeries(array, iterator, function(err, res) {
578   *   console.log(res); // [2];
579   *   console.log(order); // [1, 3, 2]
580   * });
581   *
582   * @example
583   *
584   * // object
585   * var order = [];
586   * var object = { a: 1, b: 3, c: 2 };
587   * var iterator = function(num, done) {
588   *   setTimeout(function() {
589   *     order.push(num);
590   *     done(null, num % 2);
591   *   }, num * 10);
592   * };
593   * async.rejectSeries(object, iterator, function(err, res) {
594   *   console.log(res); // [2];
595   *   console.log(order); // [1, 3, 2]
596   * });
597   *
598   * @example
599   *
600   * // object with key
601   * var order = [];
602   * var object = { a: 1, b: 3, c: 2 };
603   * var iterator = function(num, key, done) {
604   *   setTimeout(function() {
605   *     order.push([num, key]);
606   *     done(null, num % 2);
607   *   }, num * 10);
608   * };
609   * async.rejectSeries(object, iterator, function(err, res) {
610   *   console.log(res); // [2];
611   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
612   * });
613   *
614   */
615  var rejectSeries = createFilterSeries(false);
616
617  /**
618   * @memberof async
619   * @namespace rejectLimit
620   * @param {Array|Object} collection
621   * @param {number} limit - limit >= 1
622   * @param {Function} iterator
623   * @param {Function} callback
624   * @example
625   *
626   * // array
627   * var order = [];
628   * var array = [1, 5, 3, 4, 2];
629   * var iterator = function(num, done) {
630   *   setTimeout(function() {
631   *     order.push(num);
632   *     done(null, num % 2);
633   *   }, num * 10);
634   * };
635   * async.rejectLimit(array, 2, iterator, function(err, res) {
636   *   console.log(res); // [4, 2]
637   *   console.log(order); // [1, 3, 5, 2, 4]
638   * });
639   *
640   * @example
641   *
642   * // array with index
643   * var order = [];
644   * var array = [1, 5, 3, 4, 2];
645   * var iterator = function(num, index, done) {
646   *   setTimeout(function() {
647   *     order.push([num, index]);
648   *     done(null, num % 2);
649   *   }, num * 10);
650   * };
651   * async.rejectLimit(array, 2, iterator, function(err, res) {
652   *   console.log(res); // [4, 2]
653   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
654   * });
655   *
656   * @example
657   *
658   * // object
659   * var order = [];
660   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
661   * var iterator = function(num, done) {
662   *   setTimeout(function() {
663   *     order.push(num);
664   *     done(null, num % 2);
665   *   }, num * 10);
666   * };
667   * async.rejectLimit(object, 2, iterator, function(err, res) {
668   *   console.log(res); // [4, 2]
669   *   console.log(order); // [1, 3, 5, 2, 4]
670   * });
671   *
672   * @example
673   *
674   * // object with key
675   * var order = [];
676   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
677   * var iterator = function(num, key, done) {
678   *   setTimeout(function() {
679   *     order.push([num, key]);
680   *     done(null, num % 2);
681   *   }, num * 10);
682   * };
683   * async.rejectLimit(object, 2, iterator, function(err, res) {
684   *   console.log(res); // [4, 2]
685   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
686   * });
687   *
688   */
689  var rejectLimit = createFilterLimit(false);
690
691  /**
692   * @memberof async
693   * @namespace detect
694   * @param {Array|Object} collection
695   * @param {Function} iterator
696   * @param {Function} callback
697   * @example
698   *
699   * // array
700   * var order = [];
701   * var array = [1, 3, 2];
702   * var iterator = function(num, done) {
703   *   setTimeout(function() {
704   *     order.push(num);
705   *     done(null, num % 2);
706   *   }, num * 10);
707   * };
708   * async.detect(array, iterator, function(err, res) {
709   *   console.log(res); // 1
710   *   console.log(order); // [1]
711   * });
712   *
713   * @example
714   *
715   * // array with index
716   * var order = [];
717   * var array = [1, 3, 2];
718   * var iterator = function(num, index, done) {
719   *   setTimeout(function() {
720   *     order.push([num, index]);
721   *     done(null, num % 2);
722   *   }, num * 10);
723   * };
724   * async.detect(array, iterator, function(err, res) {
725   *   console.log(res); // 1
726   *   console.log(order); // [[1, 0]]
727   * });
728   *
729   * @example
730   *
731   * // object
732   * var order = [];
733   * var object = { a: 1, b: 3, c: 2 };
734   * var iterator = function(num, done) {
735   *   setTimeout(function() {
736   *     order.push(num);
737   *     done(null, num % 2);
738   *   }, num * 10);
739   * };
740   * async.detect(object, iterator, function(err, res) {
741   *   console.log(res); // 1
742   *   console.log(order); // [1]
743   * });
744   *
745   * @example
746   *
747   * // object with key
748   * var order = [];
749   * var object = { a: 1, b: 3, c: 2 };
750   * var iterator = function(num, key, done) {
751   *   setTimeout(function() {
752   *     order.push([num, key]);
753   *     done(null, num % 2);
754   *   }, num * 10);
755   * };
756   * async.detect(object, iterator, function(err, res) {
757   *   console.log(res); // 1
758   *   console.log(order); // [[1, 'a']]
759   * });
760   *
761   */
762  var detect = createDetect(arrayEachValue, baseEachValue, symbolEachValue, true);
763
764  /**
765   * @memberof async
766   * @namespace detectSeries
767   * @param {Array|Object} collection
768   * @param {Function} iterator
769   * @param {Function} callback
770   * @example
771   *
772   * // array
773   * var order = [];
774   * var array = [1, 3, 2];
775   * var iterator = function(num, done) {
776   *   setTimeout(function() {
777   *     order.push(num);
778   *     done(null, num % 2);
779   *   }, num * 10);
780   * };
781   * async.detectSeries(array, iterator, function(err, res) {
782   *   console.log(res); // 1
783   *   console.log(order); // [1]
784   * });
785   *
786   * @example
787   *
788   * // array with index
789   * var order = [];
790   * var array = [1, 3, 2];
791   * var iterator = function(num, index, done) {
792   *   setTimeout(function() {
793   *     order.push([num, index]);
794   *     done(null, num % 2);
795   *   }, num * 10);
796   * };
797   * async.detectSeries(array, iterator, function(err, res) {
798   *   console.log(res); // 1
799   *   console.log(order); // [[1, 0]]
800   * });
801   *
802   * @example
803   *
804   * // object
805   * var order = [];
806   * var object = { a: 1, b: 3, c: 2 };
807   * var iterator = function(num, done) {
808   *   setTimeout(function() {
809   *     order.push(num);
810   *     done(null, num % 2);
811   *   }, num * 10);
812   * };
813   * async.detectSeries(object, iterator, function(err, res) {
814   *   console.log(res); // 1
815   *   console.log(order); // [1]
816   * });
817   *
818   * @example
819   *
820   * // object with key
821   * var order = [];
822   * var object = { a: 1, b: 3, c: 2 };
823   * var iterator = function(num, key, done) {
824   *   setTimeout(function() {
825   *     order.push([num, key]);
826   *     done(null, num % 2);
827   *   }, num * 10);
828   * };
829   * async.detectSeries(object, iterator, function(err, res) {
830   *   console.log(res); // 1
831   *   console.log(order); // [[1, 'a']]
832   * });
833   *
834   */
835  var detectSeries = createDetectSeries(true);
836
837  /**
838   * @memberof async
839   * @namespace detectLimit
840   * @param {Array|Object} collection
841   * @param {number} limit - limit >= 1
842   * @param {Function} iterator
843   * @param {Function} callback
844   * @example
845   *
846   * // array
847   * var order = [];
848   * var array = [1, 5, 3, 4, 2];
849   * var iterator = function(num, done) {
850   *   setTimeout(function() {
851   *     order.push(num);
852   *     done(null, num % 2);
853   *   }, num * 10);
854   * };
855   * async.detectLimit(array, 2, iterator, function(err, res) {
856   *   console.log(res); // 1
857   *   console.log(order); // [1]
858   * });
859   *
860   * @example
861   *
862   * // array with index
863   * var order = [];
864   * var array = [1, 5, 3, 4, 2];
865   * var iterator = function(num, index, done) {
866   *   setTimeout(function() {
867   *     order.push([num, index]);
868   *     done(null, num % 2);
869   *   }, num * 10);
870   * };
871   * async.detectLimit(array, 2, iterator, function(err, res) {
872   *   console.log(res); // 1
873   *   console.log(order); // [[1, 0]]
874   * });
875   *
876   * @example
877   *
878   * // object
879   * var order = [];
880   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
881   * var iterator = function(num, done) {
882   *   setTimeout(function() {
883   *     order.push(num);
884   *     done(null, num % 2);
885   *   }, num * 10);
886   * };
887   * async.detectLimit(object, 2, iterator, function(err, res) {
888   *   console.log(res); // 1
889   *   console.log(order); // [1]
890   * });
891   *
892   * @example
893   *
894   * // object with key
895   * var order = [];
896   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
897   * var iterator = function(num, key, done) {
898   *   setTimeout(function() {
899   *     order.push([num, key]);
900   *     done(null, num % 2);
901   *   }, num * 10);
902   * };
903   * async.detectLimit(object, 2, iterator, function(err, res) {
904   *   console.log(res); // 1
905   *   console.log(order); // [[1, 'a']]
906   * });
907   *
908   */
909  var detectLimit = createDetectLimit(true);
910
911  /**
912   * @memberof async
913   * @namespace every
914   * @param {Array|Object} collection
915   * @param {Function} iterator
916   * @param {Function} callback
917   * @example
918   *
919   * // array
920   * var order = [];
921   * var array = [1, 3, 2];
922   * var iterator = function(num, done) {
923   *   setTimeout(function() {
924   *     order.push(num);
925   *     done(null, num % 2);
926   *   }, num * 10);
927   * };
928   * async.every(array, iterator, function(err, res) {
929   *   console.log(res); // false
930   *   console.log(order); // [1, 2]
931   * });
932   *
933   * @example
934   *
935   * // array with index
936   * var order = [];
937   * var array = [1, 3, 2];
938   * var iterator = function(num, index, done) {
939   *   setTimeout(function() {
940   *     order.push([num, index]);
941   *     done(null, num % 2);
942   *   }, num * 10);
943   * };
944   * async.every(array, iterator, function(err, res) {
945   *   console.log(res); // false
946   *   console.log(order); // [[1, 0], [2, 2]]
947   * });
948   *
949   * @example
950   *
951   * // object
952   * var order = [];
953   * var object = { a: 1, b: 3, c: 2 };
954   * var iterator = function(num, done) {
955   *   setTimeout(function() {
956   *     order.push(num);
957   *     done(null, num % 2);
958   *   }, num * 10);
959   * };
960   * async.every(object, iterator, function(err, res) {
961   *   console.log(res); // false
962   *   console.log(order); // [1, 2]
963   * });
964   *
965   * @example
966   *
967   * // object with key
968   * var order = [];
969   * var object = { a: 1, b: 3, c: 2 };
970   * var iterator = function(num, key, done) {
971   *   setTimeout(function() {
972   *     order.push([num, key]);
973   *     done(null, num % 2);
974   *   }, num * 10);
975   * };
976   * async.every(object, iterator, function(err, res) {
977   *   console.log(res); // false
978   *   console.log(order); // [[1, 'a'], [2, 'c']]
979   * });
980   *
981   */
982  var every = createEvery(arrayEachValue, baseEachValue, symbolEachValue);
983
984  /**
985   * @memberof async
986   * @namespace everySeries
987   * @param {Array|Object} collection
988   * @param {Function} iterator
989   * @param {Function} callback
990   * @example
991   *
992   * // array
993   * var order = [];
994   * var array = [1, 3, 2];
995   * var iterator = function(num, done) {
996   *   setTimeout(function() {
997   *     order.push(num);
998   *     done(null, num % 2);
999   *   }, num * 10);
1000   * };
1001   * async.everySeries(array, iterator, function(err, res) {
1002   *   console.log(res); // false
1003   *   console.log(order); // [1, 3, 2]
1004   * });
1005   *
1006   * @example
1007   *
1008   * // array with index
1009   * var order = [];
1010   * var array = [1, 3, 2];
1011   * var iterator = function(num, index, done) {
1012   *   setTimeout(function() {
1013   *     order.push([num, index]);
1014   *     done(null, num % 2);
1015   *   }, num * 10);
1016   * };
1017   * async.everySeries(array, iterator, function(err, res) {
1018   *   console.log(res); // false
1019   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
1020   * });
1021   *
1022   * @example
1023   *
1024   * // object
1025   * var order = [];
1026   * var object = { a: 1, b: 3, c: 2 };
1027   * var iterator = function(num, done) {
1028   *   setTimeout(function() {
1029   *     order.push(num);
1030   *     done(null, num % 2);
1031   *   }, num * 10);
1032   * };
1033   * async.everySeries(object, iterator, function(err, res) {
1034   *   console.log(res); // false
1035   *   console.log(order); // [1, 3, 2]
1036   * });
1037   *
1038   * @example
1039   *
1040   * // object with key
1041   * var order = [];
1042   * var object = { a: 1, b: 3, c: 2 };
1043   * var iterator = function(num, key, done) {
1044   *   setTimeout(function() {
1045   *     order.push([num, key]);
1046   *     done(null, num % 2);
1047   *   }, num * 10);
1048   * };
1049   * async.everySeries(object, iterator, function(err, res) {
1050   *   console.log(res); // false
1051   *   console.log(order); // [[1, 'a'], [3, 'b'] [2, 'c']]
1052   * });
1053   *
1054   */
1055  var everySeries = createEverySeries();
1056
1057  /**
1058   * @memberof async
1059   * @namespace everyLimit
1060   * @param {Array|Object} collection
1061   * @param {number} limit - limit >= 1
1062   * @param {Function} iterator
1063   * @param {Function} callback
1064   * @example
1065   *
1066   * // array
1067   * var order = [];
1068   * var array = [1, 5, 3, 4, 2];
1069   * var iterator = function(num, done) {
1070   *   setTimeout(function() {
1071   *     order.push(num);
1072   *     done(null, num % 2);
1073   *   }, num * 10);
1074   * };
1075   * async.everyLimit(array, 2, iterator, function(err, res) {
1076   *   console.log(res); // false
1077   *   console.log(order); // [1, 3, 5, 2]
1078   * });
1079   *
1080   * @example
1081   *
1082   * // array with index
1083   * var order = [];
1084   * var array = [1, 5, 3, 4, 2];
1085   * var iterator = function(num, index, done) {
1086   *   setTimeout(function() {
1087   *     order.push([num, index]);
1088   *     done(null, num % 2);
1089   *   }, num * 10);
1090   * };
1091   * async.everyLimit(array, 2, iterator, function(err, res) {
1092   *   console.log(res); // false
1093   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4]]
1094   * });
1095   *
1096   * @example
1097   *
1098   * // object
1099   * var order = [];
1100   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1101   * var iterator = function(num, done) {
1102   *   setTimeout(function() {
1103   *     order.push(num);
1104   *     done(null, num % 2);
1105   *   }, num * 10);
1106   * };
1107   * async.everyLimit(object, 2, iterator, function(err, res) {
1108   *   console.log(res); // false
1109   *   console.log(order); // [1, 3, 5, 2]
1110   * });
1111   *
1112   * @example
1113   *
1114   * // object with key
1115   * var order = [];
1116   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1117   * var iterator = function(num, key, done) {
1118   *   setTimeout(function() {
1119   *     order.push([num, key]);
1120   *     done(null, num % 2);
1121   *   }, num * 10);
1122   * };
1123   * async.everyLimit(object, 2, iterator, function(err, res) {
1124   *   console.log(res); // false
1125   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e']]
1126   * });
1127   *
1128   */
1129  var everyLimit = createEveryLimit();
1130
1131  /**
1132   * @memberof async
1133   * @namespace pick
1134   * @param {Array|Object} collection
1135   * @param {Function} iterator
1136   * @param {Function} callback
1137   * @example
1138   *
1139   * // array
1140   * var order = [];
1141   * var array = [1, 3, 2, 4];
1142   * var iterator = function(num, done) {
1143   *   setTimeout(function() {
1144   *     order.push(num);
1145   *     done(null, num % 2);
1146   *   }, num * 10);
1147   * };
1148   * async.pick(array, iterator, function(err, res) {
1149   *   console.log(res); // { '0': 1, '1': 3 }
1150   *   console.log(order); // [1, 2, 3, 4]
1151   * });
1152   *
1153   * @example
1154   *
1155   * // array with index
1156   * var order = [];
1157   * var array = [1, 3, 2, 4];
1158   * var iterator = function(num, index, done) {
1159   *   setTimeout(function() {
1160   *     order.push([num, index]);
1161   *     done(null, num % 2);
1162   *   }, num * 10);
1163   * };
1164   * async.pick(array, iterator, function(err, res) {
1165   *   console.log(res); // { '0': 1, '1': 3 }
1166   *   console.log(order); // [[0, 1], [2, 2], [3, 1], [4, 3]]
1167   * });
1168   *
1169   * @example
1170   *
1171   * // object
1172   * var order = [];
1173   * var object = { a: 1, b: 3, c: 2, d: 4 };
1174   * var iterator = function(num, done) {
1175   *   setTimeout(function() {
1176   *     order.push(num);
1177   *     done(null, num % 2);
1178   *   }, num * 10);
1179   * };
1180   * async.pick(object, iterator, function(err, res) {
1181   *   console.log(res); // { a: 1, b: 3 }
1182   *   console.log(order); // [1, 2, 3, 4]
1183   * });
1184   *
1185   * @example
1186   *
1187   * // object with key
1188   * var order = [];
1189   * var object = { a: 1, b: 3, c: 2, d: 4 };
1190   * var iterator = function(num, key, done) {
1191   *   setTimeout(function() {
1192   *     order.push([num, key]);
1193   *     done(null, num % 2);
1194   *   }, num * 10);
1195   * };
1196   * async.pick(object, iterator, function(err, res) {
1197   *   console.log(res); // { a: 1, b: 3 }
1198   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']]
1199   * });
1200   *
1201   */
1202  var pick = createPick(arrayEachIndexValue, baseEachKeyValue, symbolEachKeyValue, true);
1203
1204  /**
1205   * @memberof async
1206   * @namespace pickSeries
1207   * @param {Array|Object} collection
1208   * @param {Function} iterator
1209   * @param {Function} callback
1210   * @example
1211   *
1212   * // array
1213   * var order = [];
1214   * var array = [1, 3, 2, 4];
1215   * var iterator = function(num, done) {
1216   *   setTimeout(function() {
1217   *     order.push(num);
1218   *     done(null, num % 2);
1219   *   }, num * 10);
1220   * };
1221   * async.pickSeries(array, iterator, function(err, res) {
1222   *   console.log(res); // { '0': 1, '1': 3 }
1223   *   console.log(order); // [1, 3, 2, 4]
1224   * });
1225   *
1226   * @example
1227   *
1228   * // array with index
1229   * var order = [];
1230   * var array = [1, 3, 2, 4];
1231   * var iterator = function(num, index, done) {
1232   *   setTimeout(function() {
1233   *     order.push([num, index]);
1234   *     done(null, num % 2);
1235   *   }, num * 10);
1236   * };
1237   * async.pickSeries(array, iterator, function(err, res) {
1238   *   console.log(res); // { '0': 1, '1': 3 }
1239   *   console.log(order); // [[0, 1], [3, 1], [2, 2], [4, 3]]
1240   * });
1241   *
1242   * @example
1243   *
1244   * // object
1245   * var order = [];
1246   * var object = { a: 1, b: 3, c: 2, d: 4 };
1247   * var iterator = function(num, done) {
1248   *   setTimeout(function() {
1249   *     order.push(num);
1250   *     done(null, num % 2);
1251   *   }, num * 10);
1252   * };
1253   * async.pickSeries(object, iterator, function(err, res) {
1254   *   console.log(res); // { a: 1, b: 3 }
1255   *   console.log(order); // [1, 3, 2, 4]
1256   * });
1257   *
1258   * @example
1259   *
1260   * // object with key
1261   * var order = [];
1262   * var object = { a: 1, b: 3, c: 2, d: 4 };
1263   * var iterator = function(num, key, done) {
1264   *   setTimeout(function() {
1265   *     order.push([num, key]);
1266   *     done(null, num % 2);
1267   *   }, num * 10);
1268   * };
1269   * async.pickSeries(object, iterator, function(err, res) {
1270   *   console.log(res); // { a: 1, b: 3 }
1271   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c'], [4, 'd']]
1272   * });
1273   *
1274   */
1275  var pickSeries = createPickSeries(true);
1276
1277  /**
1278   * @memberof async
1279   * @namespace pickLimit
1280   * @param {Array|Object} collection
1281   * @param {number} limit - limit >= 1
1282   * @param {Function} iterator
1283   * @param {Function} callback
1284   * @example
1285   *
1286   * // array
1287   * var order = [];
1288   * var array = [1, 5, 3, 4, 2];
1289   * var iterator = function(num, done) {
1290   *   setTimeout(function() {
1291   *     order.push(num);
1292   *     done(null, num % 2);
1293   *   }, num * 10);
1294   * };
1295   * async.pickLimit(array, 2, iterator, function(err, res) {
1296   *   console.log(res); // { '0': 1, '1': 5, '2': 3 }
1297   *   console.log(order); // [1, 3, 5, 2, 4]
1298   * });
1299   *
1300   * @example
1301   *
1302   * // array with index
1303   * var order = [];
1304   * var array = [1, 5, 3, 4, 2];
1305   * var iterator = function(num, index, done) {
1306   *   setTimeout(function() {
1307   *     order.push([num, index]);
1308   *     done(null, num % 2);
1309   *   }, num * 10);
1310   * };
1311   * async.pickLimit(array, 2, iterator, function(err, res) {
1312   *   console.log(res); // { '0': 1, '1': 5, '2': 3 }
1313   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
1314   * });
1315   *
1316   * @example
1317   *
1318   * // object
1319   * var order = [];
1320   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1321   * var iterator = function(num, done) {
1322   *   setTimeout(function() {
1323   *     order.push(num);
1324   *     done(null, num % 2);
1325   *   }, num * 10);
1326   * };
1327   * async.pickLimit(object, 2, iterator, function(err, res) {
1328   *   console.log(res); // { a: 1, b: 5, c: 3 }
1329   *   console.log(order); // [1, 3, 5, 2, 4]
1330   * });
1331   *
1332   * @example
1333   *
1334   * // object with key
1335   * var order = [];
1336   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1337   * var iterator = function(num, key, done) {
1338   *   setTimeout(function() {
1339   *     order.push([num, key]);
1340   *     done(null, num % 2);
1341   *   }, num * 10);
1342   * };
1343   * async.pickLimit(object, 2, iterator, function(err, res) {
1344   *   console.log(res); // { a: 1, b: 5, c: 3 }
1345   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
1346   * });
1347   *
1348   */
1349  var pickLimit = createPickLimit(true);
1350
1351  /**
1352   * @memberof async
1353   * @namespace omit
1354   * @param {Array|Object} collection
1355   * @param {Function} iterator
1356   * @param {Function} callback
1357   * @example
1358   *
1359   * // array
1360   * var order = [];
1361   * var array = [1, 3, 2, 4];
1362   * var iterator = function(num, done) {
1363   *   setTimeout(function() {
1364   *     order.push(num);
1365   *     done(null, num % 2);
1366   *   }, num * 10);
1367   * };
1368   * async.omit(array, iterator, function(err, res) {
1369   *   console.log(res); // { '2': 2, '3': 4 }
1370   *   console.log(order); // [1, 2, 3, 4]
1371   * });
1372   *
1373   * @example
1374   *
1375   * // array with index
1376   * var order = [];
1377   * var array = [1, 3, 2, 4];
1378   * var iterator = function(num, index, done) {
1379   *   setTimeout(function() {
1380   *     order.push([num, index]);
1381   *     done(null, num % 2);
1382   *   }, num * 10);
1383   * };
1384   * async.omit(array, iterator, function(err, res) {
1385   *   console.log(res); // { '2': 2, '3': 4 }
1386   *   console.log(order); // [[0, 1], [2, 2], [3, 1], [4, 3]]
1387   * });
1388   *
1389   * @example
1390   *
1391   * // object
1392   * var order = [];
1393   * var object = { a: 1, b: 3, c: 2, d: 4 };
1394   * var iterator = function(num, done) {
1395   *   setTimeout(function() {
1396   *     order.push(num);
1397   *     done(null, num % 2);
1398   *   }, num * 10);
1399   * };
1400   * async.omit(object, iterator, function(err, res) {
1401   *   console.log(res); // { c: 2, d: 4 }
1402   *   console.log(order); // [1, 2, 3, 4]
1403   * });
1404   *
1405   * @example
1406   *
1407   * // object with key
1408   * var order = [];
1409   * var object = { a: 1, b: 3, c: 2, d: 4 };
1410   * var iterator = function(num, key, done) {
1411   *   setTimeout(function() {
1412   *     order.push([num, key]);
1413   *     done(null, num % 2);
1414   *   }, num * 10);
1415   * };
1416   * async.omit(object, iterator, function(err, res) {
1417   *   console.log(res); // { c: 2, d: 4 }
1418   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']]
1419   * });
1420   *
1421   */
1422  var omit = createPick(arrayEachIndexValue, baseEachKeyValue, symbolEachKeyValue, false);
1423
1424  /**
1425   * @memberof async
1426   * @namespace omitSeries
1427   * @param {Array|Object} collection
1428   * @param {Function} iterator
1429   * @param {Function} callback
1430   * @example
1431   *
1432   * // array
1433   * var order = [];
1434   * var array = [1, 3, 2, 4];
1435   * var iterator = function(num, done) {
1436   *   setTimeout(function() {
1437   *     order.push(num);
1438   *     done(null, num % 2);
1439   *   }, num * 10);
1440   * };
1441   * async.omitSeries(array, iterator, function(err, res) {
1442   *   console.log(res); // { '2': 2, '3': 4 }
1443   *   console.log(order); // [1, 3, 2, 4]
1444   * });
1445   *
1446   * @example
1447   *
1448   * // array with index
1449   * var order = [];
1450   * var array = [1, 3, 2, 4];
1451   * var iterator = function(num, index, done) {
1452   *   setTimeout(function() {
1453   *     order.push([num, index]);
1454   *     done(null, num % 2);
1455   *   }, num * 10);
1456   * };
1457   * async.omitSeries(array, iterator, function(err, res) {
1458   *   console.log(res); // { '2': 2, '3': 4 }
1459   *   console.log(order); // [[0, 1], [3, 1], [2, 2], [4, 3]]
1460   * });
1461   *
1462   * @example
1463   *
1464   * // object
1465   * var order = [];
1466   * var object = { a: 1, b: 3, c: 2, d: 4 };
1467   * var iterator = function(num, done) {
1468   *   setTimeout(function() {
1469   *     order.push(num);
1470   *     done(null, num % 2);
1471   *   }, num * 10);
1472   * };
1473   * async.omitSeries(object, iterator, function(err, res) {
1474   *   console.log(res); // { c: 2, d: 4 }
1475   *   console.log(order); // [1, 3, 2, 4]
1476   * });
1477   *
1478   * @example
1479   *
1480   * // object with key
1481   * var order = [];
1482   * var object = { a: 1, b: 3, c: 2, d: 4 };
1483   * var iterator = function(num, key, done) {
1484   *   setTimeout(function() {
1485   *     order.push([num, key]);
1486   *     done(null, num % 2);
1487   *   }, num * 10);
1488   * };
1489   * async.omitSeries(object, iterator, function(err, res) {
1490   *   console.log(res); // { c: 2, d: 4 }
1491   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c'], [4, 'd']]
1492   * });
1493   *
1494   */
1495  var omitSeries = createPickSeries(false);
1496
1497  /**
1498   * @memberof async
1499   * @namespace omitLimit
1500   * @param {Array|Object} collection
1501   * @param {number} limit - limit >= 1
1502   * @param {Function} iterator
1503   * @param {Function} callback
1504   * @example
1505   *
1506   * // array
1507   * var order = [];
1508   * var array = [1, 5, 3, 4, 2];
1509   * var iterator = function(num, done) {
1510   *   setTimeout(function() {
1511   *     order.push(num);
1512   *     done(null, num % 2);
1513   *   }, num * 10);
1514   * };
1515   * async.omitLimit(array, 2, iterator, function(err, res) {
1516   *   console.log(res); // { '3': 4, '4': 2 }
1517   *   console.log(order); // [1, 3, 5, 2, 4]
1518   * });
1519   *
1520   * @example
1521   *
1522   * // array with index
1523   * var order = [];
1524   * var array = [1, 5, 3, 4, 2];
1525   * var iterator = function(num, index, done) {
1526   *   setTimeout(function() {
1527   *     order.push([num, index]);
1528   *     done(null, num % 2);
1529   *   }, num * 10);
1530   * };
1531   * async.omitLimit(array, 2, iterator, function(err, res) {
1532   *   console.log(res); // { '3': 4, '4': 2 }
1533   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
1534   * });
1535   *
1536   * @example
1537   *
1538   * // object
1539   * var order = [];
1540   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1541   * var iterator = function(num, done) {
1542   *   setTimeout(function() {
1543   *     order.push(num);
1544   *     done(null, num % 2);
1545   *   }, num * 10);
1546   * };
1547   * async.omitLimit(object, 2, iterator, function(err, res) {
1548   *   console.log(res); // { d: 4, e: 2 }
1549   *   console.log(order); // [1, 3, 5, 2, 4]
1550   * });
1551   *
1552   * @example
1553   *
1554   * // object with key
1555   * var order = [];
1556   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
1557   * var iterator = function(num, key, done) {
1558   *   setTimeout(function() {
1559   *     order.push([num, key]);
1560   *     done(null, num % 2);
1561   *   }, num * 10);
1562   * };
1563   * async.omitLimit(object, 2, iterator, function(err, res) {
1564   *   console.log(res); // { d: 4, e: 2 }
1565   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
1566   * });
1567   *
1568   */
1569  var omitLimit = createPickLimit(false);
1570
1571  /**
1572   * @memberof async
1573   * @namespace transform
1574   * @param {Array|Object} collection
1575   * @param {Array|Object|Function} [accumulator]
1576   * @param {Function} [iterator]
1577   * @param {Function} [callback]
1578   * @example
1579   *
1580   * // array
1581   * var order = [];
1582   * var collection = [1, 3, 2, 4];
1583   * var iterator = function(result, num, done) {
1584   *   setTimeout(function() {
1585   *     order.push(num);
1586   *     result.push(num)
1587   *     done();
1588   *   }, num * 10);
1589   * };
1590   * async.transform(collection, iterator, function(err, res) {
1591   *   console.log(res); // [1, 2, 3, 4]
1592   *   console.log(order); // [1, 2, 3, 4]
1593   * });
1594   *
1595   * @example
1596   *
1597   * // array with index and accumulator
1598   * var order = [];
1599   * var collection = [1, 3, 2, 4];
1600   * var iterator = function(result, num, index, done) {
1601   *   setTimeout(function() {
1602   *     order.push([num, index]);
1603   *     result[index] = num;
1604   *     done();
1605   *   }, num * 10);
1606   * };
1607   * async.transform(collection, {}, iterator, function(err, res) {
1608   *   console.log(res); // { '0': 1, '1': 3, '2': 2, '3': 4 }
1609   *   console.log(order); // [[1, 0], [2, 2], [3, 1], [4, 3]]
1610   * });
1611   *
1612   * @example
1613   *
1614   * // object with accumulator
1615   * var order = [];
1616   * var object = { a: 1, b: 3, c: 2, d: 4 };
1617   * var iterator = function(result, num, done) {
1618   *   setTimeout(function() {
1619   *     order.push(num);
1620   *     result.push(num);
1621   *     done();
1622   *   }, num * 10);
1623   * };
1624   * async.transform(collection, [], iterator, function(err, res) {
1625   *   console.log(res); // [1, 2, 3, 4]
1626   *   console.log(order); // [1, 2, 3, 4]
1627   * });
1628   *
1629   * @example
1630   *
1631   * // object with key
1632   * var order = [];
1633   * var object = { a: 1, b: 3, c: 2, d: 4 };
1634   * var iterator = function(result, num, key, done) {
1635   *   setTimeout(function() {
1636   *     order.push([num, key]);
1637   *     result[key] = num;
1638   *     done();
1639   *   }, num * 10);
1640   * };
1641   * async.transform(collection, iterator, function(err, res) {
1642   *   console.log(res); //  { a: 1, b: 3, c: 2, d: 4 }
1643   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b'], [4, 'd']]
1644   * });
1645   *
1646   */
1647  var transform = createTransform(arrayEachResult, baseEachResult, symbolEachResult);
1648
1649  /**
1650   * @memberof async
1651   * @namespace sortBy
1652   * @param {Array|Object} collection
1653   * @param {Function} iterator
1654   * @param {Function} callback
1655   * @example
1656   *
1657   * // array
1658   * var order = [];
1659   * var array = [1, 3, 2];
1660   * var iterator = function(num, done) {
1661   *   setTimeout(function() {
1662   *     order.push(num);
1663   *     done(null, num);
1664   *   }, num * 10);
1665   * };
1666   * async.sortBy(array, iterator, function(err, res) {
1667   *   console.log(res); // [1, 2, 3];
1668   *   console.log(order); // [1, 2, 3]
1669   * });
1670   *
1671   * @example
1672   *
1673   * // array with index
1674   * var order = [];
1675   * var array = [1, 3, 2];
1676   * var iterator = function(num, index, done) {
1677   *   setTimeout(function() {
1678   *     order.push([num, index]);
1679   *     done(null, num);
1680   *   }, num * 10);
1681   * };
1682   * async.sortBy(array, iterator, function(err, res) {
1683   *   console.log(res); // [1, 2, 3]
1684   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
1685   * });
1686   *
1687   * @example
1688   *
1689   * // object
1690   * var order = [];
1691   * var object = { a: 1, b: 3, c: 2 };
1692   * var iterator = function(num, done) {
1693   *   setTimeout(function() {
1694   *     order.push(num);
1695   *     done(null, num);
1696   *   }, num * 10);
1697   * };
1698   * async.sortBy(object, iterator, function(err, res) {
1699   *   console.log(res); // [1, 2, 3]
1700   *   console.log(order); // [1, 2, 3]
1701   * });
1702   *
1703   * @example
1704   *
1705   * // object with key
1706   * var order = [];
1707   * var object = { a: 1, b: 3, c: 2 };
1708   * var iterator = function(num, key, done) {
1709   *   setTimeout(function() {
1710   *     order.push([num, key]);
1711   *     done(null, num);
1712   *   }, num * 10);
1713   * };
1714   * async.sortBy(object, iterator, function(err, res) {
1715   *   console.log(res); // [1, 2, 3]
1716   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
1717   * });
1718   *
1719   */
1720  var sortBy = createSortBy(arrayEachIndexValue, baseEachIndexValue, symbolEachIndexValue);
1721
1722  /**
1723   * @memberof async
1724   * @namespace concat
1725   * @param {Array|Object} collection
1726   * @param {Function} iterator
1727   * @param {Function} callback
1728   * @example
1729   *
1730   * // array
1731   * var order = [];
1732   * var array = [1, 3, 2];
1733   * var iterator = function(num, done) {
1734   *   setTimeout(function() {
1735   *     order.push(num);
1736   *     done(null, [num]);
1737   *   }, num * 10);
1738   * };
1739   * async.concat(array, iterator, function(err, res) {
1740   *   console.log(res); // [1, 2, 3];
1741   *   console.log(order); // [1, 2, 3]
1742   * });
1743   *
1744   * @example
1745   *
1746   * // array with index
1747   * var order = [];
1748   * var array = [1, 3, 2];
1749   * var iterator = function(num, index, done) {
1750   *   setTimeout(function() {
1751   *     order.push([num, index]);
1752   *     done(null, [num]);
1753   *   }, num * 10);
1754   * };
1755   * async.concat(array, iterator, function(err, res) {
1756   *   console.log(res); // [1, 2, 3]
1757   *   console.log(order); // [[1, 0], [2, 2], [3, 1]]
1758   * });
1759   *
1760   * @example
1761   *
1762   * // object
1763   * var order = [];
1764   * var object = { a: 1, b: 3, c: 2 };
1765   * var iterator = function(num, done) {
1766   *   setTimeout(function() {
1767   *     order.push(num);
1768   *     done(null, [num]);
1769   *   }, num * 10);
1770   * };
1771   * async.concat(object, iterator, function(err, res) {
1772   *   console.log(res); // [1, 2, 3]
1773   *   console.log(order); // [1, 2, 3]
1774   * });
1775   *
1776   * @example
1777   *
1778   * // object with key
1779   * var order = [];
1780   * var object = { a: 1, b: 3, c: 2 };
1781   * var iterator = function(num, key, done) {
1782   *   setTimeout(function() {
1783   *     order.push([num, key]);
1784   *     done(null, [num]);
1785   *   }, num * 10);
1786   * };
1787   * async.concat(object, iterator, function(err, res) {
1788   *   console.log(res); // [1, 2, 3]
1789   *   console.log(order); // [[1, 'a'], [2, 'c'], [3, 'b']]
1790   * });
1791   *
1792   */
1793  var concat = createConcat(arrayEachIndex, baseEachIndex, symbolEachIndex);
1794
1795  /**
1796   * @memberof async
1797   * @namespace groupBy
1798   * @param {Array|Object} collection
1799   * @param {Function} iterator
1800   * @param {Function} callback
1801   * @example
1802   *
1803   * // array
1804   * var order = [];
1805   * var array = [4.2, 6.4, 6.1];
1806   * var iterator = function(num, done) {
1807   *   setTimeout(function() {
1808   *     order.push(num);
1809   *     done(null, Math.floor(num));
1810   *   }, num * 10);
1811   * };
1812   * async.groupBy(array, iterator, function(err, res) {
1813   *   console.log(res); // { '4': [4.2], '6': [6.1, 6.4] }
1814   *   console.log(order); // [4.2, 6.1, 6.4]
1815   * });
1816   *
1817   * @example
1818   *
1819   * // array with index
1820   * var order = [];
1821   * var array = [4.2, 6.4, 6.1];
1822   * var iterator = function(num, index, done) {
1823   *   setTimeout(function() {
1824   *     order.push([num, index]);
1825   *     done(null, Math.floor(num));
1826   *   }, num * 10);
1827   * };
1828   * async.groupBy(array, iterator, function(err, res) {
1829   *   console.log(res); // { '4': [4.2], '6': [6.1, 6.4] }
1830   *   console.log(order); // [[4.2, 0], [6.1, 2], [6.4, 1]]
1831   * });
1832   *
1833   * @example
1834   *
1835   * // object
1836   * var order = [];
1837   * var object = { a: 4.2, b: 6.4, c: 6.1 };
1838   * var iterator = function(num, done) {
1839   *   setTimeout(function() {
1840   *     order.push(num);
1841   *     done(null, Math.floor(num));
1842   *   }, num * 10);
1843   * };
1844   * async.groupBy(object, iterator, function(err, res) {
1845   *   console.log(res); // { '4': [4.2], '6': [6.1, 6.4] }
1846   *   console.log(order); // [4.2, 6.1, 6.4]
1847   * });
1848   *
1849   * @example
1850   *
1851   * // object with key
1852   * var order = [];
1853   * var object = { a: 4.2, b: 6.4, c: 6.1 };
1854   * var iterator = function(num, key, done) {
1855   *   setTimeout(function() {
1856   *     order.push([num, key]);
1857   *     done(null, Math.floor(num));
1858   *   }, num * 10);
1859   * };
1860   * async.groupBy(object, iterator, function(err, res) {
1861   *   console.log(res); // { '4': [4.2], '6': [6.1, 6.4] }
1862   *   console.log(order); // [[4.2, 'a'], [6.1, 'c'], [6.4, 'b']]
1863   * });
1864   *
1865   */
1866  var groupBy = createGroupBy(arrayEachValue, baseEachValue, symbolEachValue);
1867
1868  /**
1869   * @memberof async
1870   * @namespace parallel
1871   * @param {Array|Object} tasks - functions
1872   * @param {Function} callback
1873   * @example
1874   *
1875   * var order = [];
1876   * var tasks = [
1877   *  function(done) {
1878   *    setTimeout(function() {
1879   *      order.push(1);
1880   *      done(null, 1);
1881   *    }, 10);
1882   *  },
1883   *  function(done) {
1884   *    setTimeout(function() {
1885   *      order.push(2);
1886   *      done(null, 2);
1887   *    }, 30);
1888   *  },
1889   *  function(done) {
1890   *    setTimeout(function() {
1891   *      order.push(3);
1892   *      done(null, 3);
1893   *    }, 40);
1894   *  },
1895   *  function(done) {
1896   *    setTimeout(function() {
1897   *      order.push(4);
1898   *      done(null, 4);
1899   *    }, 20);
1900   *  }
1901   * ];
1902   * async.parallel(tasks, function(err, res) {
1903   *   console.log(res); // [1, 2, 3, 4];
1904   *   console.log(order); // [1, 4, 2, 3]
1905   * });
1906   *
1907   * @example
1908   *
1909   * var order = [];
1910   * var tasks = {
1911   *   'a': function(done) {
1912   *     setTimeout(function() {
1913   *       order.push(1);
1914   *       done(null, 1);
1915   *     }, 10);
1916   *   },
1917   *   'b': function(done) {
1918   *     setTimeout(function() {
1919   *       order.push(2);
1920   *       done(null, 2);
1921   *     }, 30);
1922   *   },
1923   *   'c': function(done) {
1924   *     setTimeout(function() {
1925   *       order.push(3);
1926   *       done(null, 3);
1927   *     }, 40);
1928   *   },
1929   *   'd': function(done) {
1930   *     setTimeout(function() {
1931   *       order.push(4);
1932   *       done(null, 4);
1933   *     }, 20);
1934   *   }
1935   * };
1936   * async.parallel(tasks, function(err, res) {
1937   *   console.log(res); // { a: 1, b: 2, c: 3, d:4 }
1938   *   console.log(order); // [1, 4, 2, 3]
1939   * });
1940   *
1941   */
1942  var parallel = createParallel(arrayEachFunc, baseEachFunc);
1943
1944  /**
1945   * @memberof async
1946   * @namespace applyEach
1947   */
1948  var applyEach = createApplyEach(map);
1949
1950  /**
1951   * @memberof async
1952   * @namespace applyEachSeries
1953   */
1954  var applyEachSeries = createApplyEach(mapSeries);
1955
1956  /**
1957   * @memberof async
1958   * @namespace log
1959   */
1960  var log = createLogger('log');
1961
1962  /**
1963   * @memberof async
1964   * @namespace dir
1965   */
1966  var dir = createLogger('dir');
1967
1968  /**
1969   * @version 2.6.2
1970   * @namespace async
1971   */
1972  var index = {
1973    VERSION: '2.6.2',
1974
1975    // Collections
1976    each: each,
1977    eachSeries: eachSeries,
1978    eachLimit: eachLimit,
1979    forEach: each,
1980    forEachSeries: eachSeries,
1981    forEachLimit: eachLimit,
1982    eachOf: each,
1983    eachOfSeries: eachSeries,
1984    eachOfLimit: eachLimit,
1985    forEachOf: each,
1986    forEachOfSeries: eachSeries,
1987    forEachOfLimit: eachLimit,
1988    map: map,
1989    mapSeries: mapSeries,
1990    mapLimit: mapLimit,
1991    mapValues: mapValues,
1992    mapValuesSeries: mapValuesSeries,
1993    mapValuesLimit: mapValuesLimit,
1994    filter: filter,
1995    filterSeries: filterSeries,
1996    filterLimit: filterLimit,
1997    select: filter,
1998    selectSeries: filterSeries,
1999    selectLimit: filterLimit,
2000    reject: reject,
2001    rejectSeries: rejectSeries,
2002    rejectLimit: rejectLimit,
2003    detect: detect,
2004    detectSeries: detectSeries,
2005    detectLimit: detectLimit,
2006    find: detect,
2007    findSeries: detectSeries,
2008    findLimit: detectLimit,
2009    pick: pick,
2010    pickSeries: pickSeries,
2011    pickLimit: pickLimit,
2012    omit: omit,
2013    omitSeries: omitSeries,
2014    omitLimit: omitLimit,
2015    reduce: reduce,
2016    inject: reduce,
2017    foldl: reduce,
2018    reduceRight: reduceRight,
2019    foldr: reduceRight,
2020    transform: transform,
2021    transformSeries: transformSeries,
2022    transformLimit: transformLimit,
2023    sortBy: sortBy,
2024    sortBySeries: sortBySeries,
2025    sortByLimit: sortByLimit,
2026    some: some,
2027    someSeries: someSeries,
2028    someLimit: someLimit,
2029    any: some,
2030    anySeries: someSeries,
2031    anyLimit: someLimit,
2032    every: every,
2033    everySeries: everySeries,
2034    everyLimit: everyLimit,
2035    all: every,
2036    allSeries: everySeries,
2037    allLimit: everyLimit,
2038    concat: concat,
2039    concatSeries: concatSeries,
2040    concatLimit: concatLimit,
2041    groupBy: groupBy,
2042    groupBySeries: groupBySeries,
2043    groupByLimit: groupByLimit,
2044
2045    // Control Flow
2046    parallel: parallel,
2047    series: series,
2048    parallelLimit: parallelLimit,
2049    tryEach: tryEach,
2050    waterfall: waterfall,
2051    angelFall: angelFall,
2052    angelfall: angelFall,
2053    whilst: whilst,
2054    doWhilst: doWhilst,
2055    until: until,
2056    doUntil: doUntil,
2057    during: during,
2058    doDuring: doDuring,
2059    forever: forever,
2060    compose: compose,
2061    seq: seq,
2062    applyEach: applyEach,
2063    applyEachSeries: applyEachSeries,
2064    queue: queue,
2065    priorityQueue: priorityQueue,
2066    cargo: cargo,
2067    auto: auto,
2068    autoInject: autoInject,
2069    retry: retry,
2070    retryable: retryable,
2071    iterator: iterator,
2072    times: times,
2073    timesSeries: timesSeries,
2074    timesLimit: timesLimit,
2075    race: race,
2076
2077    // Utils
2078    apply: apply,
2079    nextTick: asyncNextTick,
2080    setImmediate: asyncSetImmediate,
2081    memoize: memoize,
2082    unmemoize: unmemoize,
2083    ensureAsync: ensureAsync,
2084    constant: constant,
2085    asyncify: asyncify,
2086    wrapSync: asyncify,
2087    log: log,
2088    dir: dir,
2089    reflect: reflect,
2090    reflectAll: reflectAll,
2091    timeout: timeout,
2092    createLogger: createLogger,
2093
2094    // Mode
2095    safe: safe,
2096    fast: fast
2097  };
2098
2099  exports['default'] = index;
2100  baseEachSync(
2101    index,
2102    function(func, key) {
2103      exports[key] = func;
2104    },
2105    nativeKeys(index)
2106  );
2107
2108  /**
2109   * @private
2110   */
2111  function createImmediate(safeMode) {
2112    var delay = function delay(fn) {
2113      var args = slice(arguments, 1);
2114      setTimeout(function() {
2115        fn.apply(null, args);
2116      });
2117    };
2118    asyncSetImmediate = typeof setImmediate === func ? setImmediate : delay;
2119    if (typeof process === obj && typeof process.nextTick === func) {
2120      nextTick = /^v0.10/.test(process.version) ? asyncSetImmediate : process.nextTick;
2121      asyncNextTick = /^v0/.test(process.version) ? asyncSetImmediate : process.nextTick;
2122    } else {
2123      asyncNextTick = nextTick = asyncSetImmediate;
2124    }
2125    if (safeMode === false) {
2126      nextTick = function(cb) {
2127        cb();
2128      };
2129    }
2130  }
2131
2132  /* sync functions based on lodash */
2133
2134  /**
2135   * Converts `arguments` to an array.
2136   *
2137   * @private
2138   * @param {Array} array = The array to slice.
2139   */
2140  function createArray(array) {
2141    var index = -1;
2142    var size = array.length;
2143    var result = Array(size);
2144
2145    while (++index < size) {
2146      result[index] = array[index];
2147    }
2148    return result;
2149  }
2150
2151  /**
2152   * Create an array from `start`
2153   *
2154   * @private
2155   * @param {Array} array - The array to slice.
2156   * @param {number} start - The start position.
2157   */
2158  function slice(array, start) {
2159    var end = array.length;
2160    var index = -1;
2161    var size = end - start;
2162    if (size <= 0) {
2163      return [];
2164    }
2165    var result = Array(size);
2166
2167    while (++index < size) {
2168      result[index] = array[index + start];
2169    }
2170    return result;
2171  }
2172
2173  /**
2174   * @private
2175   * @param {Object} object
2176   */
2177  function objectClone(object) {
2178    var keys = nativeKeys(object);
2179    var size = keys.length;
2180    var index = -1;
2181    var result = {};
2182
2183    while (++index < size) {
2184      var key = keys[index];
2185      result[key] = object[key];
2186    }
2187    return result;
2188  }
2189
2190  /**
2191   * Create an array with all falsey values removed.
2192   *
2193   * @private
2194   * @param {Array} array - The array to compact.
2195   */
2196  function compact(array) {
2197    var index = -1;
2198    var size = array.length;
2199    var result = [];
2200
2201    while (++index < size) {
2202      var value = array[index];
2203      if (value) {
2204        result[result.length] = value;
2205      }
2206    }
2207    return result;
2208  }
2209
2210  /**
2211   * Create an array of reverse sequence.
2212   *
2213   * @private
2214   * @param {Array} array - The array to reverse.
2215   */
2216  function reverse(array) {
2217    var index = -1;
2218    var size = array.length;
2219    var result = Array(size);
2220    var resIndex = size;
2221
2222    while (++index < size) {
2223      result[--resIndex] = array[index];
2224    }
2225    return result;
2226  }
2227
2228  /**
2229   * Checks if key exists in object property.
2230   *
2231   * @private
2232   * @param {Object} object - The object to inspect.
2233   * @param {string} key - The key to check.
2234   */
2235  function has(object, key) {
2236    return object.hasOwnProperty(key);
2237  }
2238
2239  /**
2240   * Check if target exists in array.
2241   * @private
2242   * @param {Array} array
2243   * @param {*} target
2244   */
2245  function notInclude(array, target) {
2246    var index = -1;
2247    var size = array.length;
2248
2249    while (++index < size) {
2250      if (array[index] === target) {
2251        return false;
2252      }
2253    }
2254    return true;
2255  }
2256
2257  /**
2258   * @private
2259   * @param {Array} array - The array to iterate over.
2260   * @param {Function} iterator - The function invoked per iteration.
2261   */
2262  function arrayEachSync(array, iterator) {
2263    var index = -1;
2264    var size = array.length;
2265
2266    while (++index < size) {
2267      iterator(array[index], index);
2268    }
2269    return array;
2270  }
2271
2272  /**
2273   * @private
2274   * @param {Object} object - The object to iterate over.
2275   * @param {Function} iterator - The function invoked per iteration.
2276   * @param {Array} keys
2277   */
2278  function baseEachSync(object, iterator, keys) {
2279    var index = -1;
2280    var size = keys.length;
2281
2282    while (++index < size) {
2283      var key = keys[index];
2284      iterator(object[key], key);
2285    }
2286    return object;
2287  }
2288
2289  /**
2290   * @private
2291   * @param {number} n
2292   * @param {Function} iterator
2293   */
2294  function timesSync(n, iterator) {
2295    var index = -1;
2296    while (++index < n) {
2297      iterator(index);
2298    }
2299  }
2300
2301  /**
2302   * @private
2303   * @param {Array} array
2304   * @param {number[]} criteria
2305   */
2306  function sortByCriteria(array, criteria) {
2307    var l = array.length;
2308    var indices = Array(l);
2309    var i;
2310    for (i = 0; i < l; i++) {
2311      indices[i] = i;
2312    }
2313    quickSort(criteria, 0, l - 1, indices);
2314    var result = Array(l);
2315    for (var n = 0; n < l; n++) {
2316      i = indices[n];
2317      result[n] = i === undefined ? array[n] : array[i];
2318    }
2319    return result;
2320  }
2321
2322  function partition(array, i, j, mid, indices) {
2323    var l = i;
2324    var r = j;
2325    while (l <= r) {
2326      i = l;
2327      while (l < r && array[l] < mid) {
2328        l++;
2329      }
2330      while (r >= i && array[r] >= mid) {
2331        r--;
2332      }
2333      if (l > r) {
2334        break;
2335      }
2336      swap(array, indices, l++, r--);
2337    }
2338    return l;
2339  }
2340
2341  function swap(array, indices, l, r) {
2342    var n = array[l];
2343    array[l] = array[r];
2344    array[r] = n;
2345    var i = indices[l];
2346    indices[l] = indices[r];
2347    indices[r] = i;
2348  }
2349
2350  function quickSort(array, i, j, indices) {
2351    if (i === j) {
2352      return;
2353    }
2354    var k = i;
2355    while (++k <= j && array[i] === array[k]) {
2356      var l = k - 1;
2357      if (indices[l] > indices[k]) {
2358        var index = indices[l];
2359        indices[l] = indices[k];
2360        indices[k] = index;
2361      }
2362    }
2363    if (k > j) {
2364      return;
2365    }
2366    var p = array[i] > array[k] ? i : k;
2367    k = partition(array, i, j, array[p], indices);
2368    quickSort(array, i, k - 1, indices);
2369    quickSort(array, k, j, indices);
2370  }
2371
2372  /**
2373   * @Private
2374   */
2375  function makeConcatResult(array) {
2376    var result = [];
2377    arrayEachSync(array, function(value) {
2378      if (value === noop) {
2379        return;
2380      }
2381      if (isArray(value)) {
2382        nativePush.apply(result, value);
2383      } else {
2384        result.push(value);
2385      }
2386    });
2387    return result;
2388  }
2389
2390  /* async functions */
2391
2392  /**
2393   * @private
2394   */
2395  function arrayEach(array, iterator, callback) {
2396    var index = -1;
2397    var size = array.length;
2398
2399    if (iterator.length === 3) {
2400      while (++index < size) {
2401        iterator(array[index], index, onlyOnce(callback));
2402      }
2403    } else {
2404      while (++index < size) {
2405        iterator(array[index], onlyOnce(callback));
2406      }
2407    }
2408  }
2409
2410  /**
2411   * @private
2412   */
2413  function baseEach(object, iterator, callback, keys) {
2414    var key;
2415    var index = -1;
2416    var size = keys.length;
2417
2418    if (iterator.length === 3) {
2419      while (++index < size) {
2420        key = keys[index];
2421        iterator(object[key], key, onlyOnce(callback));
2422      }
2423    } else {
2424      while (++index < size) {
2425        iterator(object[keys[index]], onlyOnce(callback));
2426      }
2427    }
2428  }
2429
2430  /**
2431   * @private
2432   */
2433  function symbolEach(collection, iterator, callback) {
2434    var iter = collection[iteratorSymbol]();
2435    var index = 0;
2436    var item;
2437    if (iterator.length === 3) {
2438      while ((item = iter.next()).done === false) {
2439        iterator(item.value, index++, onlyOnce(callback));
2440      }
2441    } else {
2442      while ((item = iter.next()).done === false) {
2443        index++;
2444        iterator(item.value, onlyOnce(callback));
2445      }
2446    }
2447    return index;
2448  }
2449
2450  /**
2451   * @private
2452   */
2453  function arrayEachResult(array, result, iterator, callback) {
2454    var index = -1;
2455    var size = array.length;
2456
2457    if (iterator.length === 4) {
2458      while (++index < size) {
2459        iterator(result, array[index], index, onlyOnce(callback));
2460      }
2461    } else {
2462      while (++index < size) {
2463        iterator(result, array[index], onlyOnce(callback));
2464      }
2465    }
2466  }
2467
2468  /**
2469   * @private
2470   */
2471  function baseEachResult(object, result, iterator, callback, keys) {
2472    var key;
2473    var index = -1;
2474    var size = keys.length;
2475
2476    if (iterator.length === 4) {
2477      while (++index < size) {
2478        key = keys[index];
2479        iterator(result, object[key], key, onlyOnce(callback));
2480      }
2481    } else {
2482      while (++index < size) {
2483        iterator(result, object[keys[index]], onlyOnce(callback));
2484      }
2485    }
2486  }
2487
2488  /**
2489   * @private
2490   */
2491  function symbolEachResult(collection, result, iterator, callback) {
2492    var item;
2493    var index = 0;
2494    var iter = collection[iteratorSymbol]();
2495
2496    if (iterator.length === 4) {
2497      while ((item = iter.next()).done === false) {
2498        iterator(result, item.value, index++, onlyOnce(callback));
2499      }
2500    } else {
2501      while ((item = iter.next()).done === false) {
2502        index++;
2503        iterator(result, item.value, onlyOnce(callback));
2504      }
2505    }
2506    return index;
2507  }
2508
2509  /**
2510   * @private
2511   */
2512  function arrayEachFunc(array, createCallback) {
2513    var index = -1;
2514    var size = array.length;
2515
2516    while (++index < size) {
2517      array[index](createCallback(index));
2518    }
2519  }
2520
2521  /**
2522   * @private
2523   */
2524  function baseEachFunc(object, createCallback, keys) {
2525    var key;
2526    var index = -1;
2527    var size = keys.length;
2528
2529    while (++index < size) {
2530      key = keys[index];
2531      object[key](createCallback(key));
2532    }
2533  }
2534
2535  /**
2536   * @private
2537   */
2538  function arrayEachIndex(array, iterator, createCallback) {
2539    var index = -1;
2540    var size = array.length;
2541
2542    if (iterator.length === 3) {
2543      while (++index < size) {
2544        iterator(array[index], index, createCallback(index));
2545      }
2546    } else {
2547      while (++index < size) {
2548        iterator(array[index], createCallback(index));
2549      }
2550    }
2551  }
2552
2553  /**
2554   * @private
2555   */
2556  function baseEachIndex(object, iterator, createCallback, keys) {
2557    var key;
2558    var index = -1;
2559    var size = keys.length;
2560
2561    if (iterator.length === 3) {
2562      while (++index < size) {
2563        key = keys[index];
2564        iterator(object[key], key, createCallback(index));
2565      }
2566    } else {
2567      while (++index < size) {
2568        iterator(object[keys[index]], createCallback(index));
2569      }
2570    }
2571  }
2572
2573  /**
2574   * @private
2575   */
2576  function symbolEachIndex(collection, iterator, createCallback) {
2577    var item;
2578    var index = 0;
2579    var iter = collection[iteratorSymbol]();
2580
2581    if (iterator.length === 3) {
2582      while ((item = iter.next()).done === false) {
2583        iterator(item.value, index, createCallback(index++));
2584      }
2585    } else {
2586      while ((item = iter.next()).done === false) {
2587        iterator(item.value, createCallback(index++));
2588      }
2589    }
2590    return index;
2591  }
2592
2593  /**
2594   * @private
2595   */
2596  function baseEachKey(object, iterator, createCallback, keys) {
2597    var key;
2598    var index = -1;
2599    var size = keys.length;
2600
2601    if (iterator.length === 3) {
2602      while (++index < size) {
2603        key = keys[index];
2604        iterator(object[key], key, createCallback(key));
2605      }
2606    } else {
2607      while (++index < size) {
2608        key = keys[index];
2609        iterator(object[key], createCallback(key));
2610      }
2611    }
2612  }
2613
2614  /**
2615   * @private
2616   */
2617  function symbolEachKey(collection, iterator, createCallback) {
2618    var item;
2619    var index = 0;
2620    var iter = collection[iteratorSymbol]();
2621
2622    if (iterator.length === 3) {
2623      while ((item = iter.next()).done === false) {
2624        iterator(item.value, index, createCallback(index++));
2625      }
2626    } else {
2627      while ((item = iter.next()).done === false) {
2628        iterator(item.value, createCallback(index++));
2629      }
2630    }
2631    return index;
2632  }
2633
2634  /**
2635   * @private
2636   */
2637  function arrayEachValue(array, iterator, createCallback) {
2638    var value;
2639    var index = -1;
2640    var size = array.length;
2641
2642    if (iterator.length === 3) {
2643      while (++index < size) {
2644        value = array[index];
2645        iterator(value, index, createCallback(value));
2646      }
2647    } else {
2648      while (++index < size) {
2649        value = array[index];
2650        iterator(value, createCallback(value));
2651      }
2652    }
2653  }
2654
2655  /**
2656   * @private
2657   */
2658  function baseEachValue(object, iterator, createCallback, keys) {
2659    var key, value;
2660    var index = -1;
2661    var size = keys.length;
2662
2663    if (iterator.length === 3) {
2664      while (++index < size) {
2665        key = keys[index];
2666        value = object[key];
2667        iterator(value, key, createCallback(value));
2668      }
2669    } else {
2670      while (++index < size) {
2671        value = object[keys[index]];
2672        iterator(value, createCallback(value));
2673      }
2674    }
2675  }
2676
2677  /**
2678   * @private
2679   */
2680  function symbolEachValue(collection, iterator, createCallback) {
2681    var value, item;
2682    var index = 0;
2683    var iter = collection[iteratorSymbol]();
2684
2685    if (iterator.length === 3) {
2686      while ((item = iter.next()).done === false) {
2687        value = item.value;
2688        iterator(value, index++, createCallback(value));
2689      }
2690    } else {
2691      while ((item = iter.next()).done === false) {
2692        index++;
2693        value = item.value;
2694        iterator(value, createCallback(value));
2695      }
2696    }
2697    return index;
2698  }
2699
2700  /**
2701   * @private
2702   */
2703  function arrayEachIndexValue(array, iterator, createCallback) {
2704    var value;
2705    var index = -1;
2706    var size = array.length;
2707
2708    if (iterator.length === 3) {
2709      while (++index < size) {
2710        value = array[index];
2711        iterator(value, index, createCallback(index, value));
2712      }
2713    } else {
2714      while (++index < size) {
2715        value = array[index];
2716        iterator(value, createCallback(index, value));
2717      }
2718    }
2719  }
2720
2721  /**
2722   * @private
2723   */
2724  function baseEachIndexValue(object, iterator, createCallback, keys) {
2725    var key, value;
2726    var index = -1;
2727    var size = keys.length;
2728
2729    if (iterator.length === 3) {
2730      while (++index < size) {
2731        key = keys[index];
2732        value = object[key];
2733        iterator(value, key, createCallback(index, value));
2734      }
2735    } else {
2736      while (++index < size) {
2737        value = object[keys[index]];
2738        iterator(value, createCallback(index, value));
2739      }
2740    }
2741  }
2742
2743  /**
2744   * @private
2745   */
2746  function symbolEachIndexValue(collection, iterator, createCallback) {
2747    var value, item;
2748    var index = 0;
2749    var iter = collection[iteratorSymbol]();
2750
2751    if (iterator.length === 3) {
2752      while ((item = iter.next()).done === false) {
2753        value = item.value;
2754        iterator(value, index, createCallback(index++, value));
2755      }
2756    } else {
2757      while ((item = iter.next()).done === false) {
2758        value = item.value;
2759        iterator(value, createCallback(index++, value));
2760      }
2761    }
2762    return index;
2763  }
2764
2765  /**
2766   * @private
2767   */
2768  function baseEachKeyValue(object, iterator, createCallback, keys) {
2769    var key, value;
2770    var index = -1;
2771    var size = keys.length;
2772
2773    if (iterator.length === 3) {
2774      while (++index < size) {
2775        key = keys[index];
2776        value = object[key];
2777        iterator(value, key, createCallback(key, value));
2778      }
2779    } else {
2780      while (++index < size) {
2781        key = keys[index];
2782        value = object[key];
2783        iterator(value, createCallback(key, value));
2784      }
2785    }
2786  }
2787
2788  /**
2789   * @private
2790   */
2791  function symbolEachKeyValue(collection, iterator, createCallback) {
2792    var value, item;
2793    var index = 0;
2794    var iter = collection[iteratorSymbol]();
2795
2796    if (iterator.length === 3) {
2797      while ((item = iter.next()).done === false) {
2798        value = item.value;
2799        iterator(value, index, createCallback(index++, value));
2800      }
2801    } else {
2802      while ((item = iter.next()).done === false) {
2803        value = item.value;
2804        iterator(value, createCallback(index++, value));
2805      }
2806    }
2807    return index;
2808  }
2809
2810  /**
2811   * @private
2812   * @param {Function} func
2813   */
2814  function onlyOnce(func) {
2815    return function(err, res) {
2816      var fn = func;
2817      func = throwError;
2818      fn(err, res);
2819    };
2820  }
2821
2822  /**
2823   * @private
2824   * @param {Function} func
2825   */
2826  function once(func) {
2827    return function(err, res) {
2828      var fn = func;
2829      func = noop;
2830      fn(err, res);
2831    };
2832  }
2833
2834  /**
2835   * @private
2836   * @param {Function} arrayEach
2837   * @param {Function} baseEach
2838   */
2839  function createEach(arrayEach, baseEach, symbolEach) {
2840    return function each(collection, iterator, callback) {
2841      callback = once(callback || noop);
2842      var size, keys;
2843      var completed = 0;
2844      if (isArray(collection)) {
2845        size = collection.length;
2846        arrayEach(collection, iterator, done);
2847      } else if (!collection) {
2848      } else if (iteratorSymbol && collection[iteratorSymbol]) {
2849        size = symbolEach(collection, iterator, done);
2850        size && size === completed && callback(null);
2851      } else if (typeof collection === obj) {
2852        keys = nativeKeys(collection);
2853        size = keys.length;
2854        baseEach(collection, iterator, done, keys);
2855      }
2856      if (!size) {
2857        callback(null);
2858      }
2859
2860      function done(err, bool) {
2861        if (err) {
2862          callback = once(callback);
2863          callback(err);
2864        } else if (++completed === size) {
2865          callback(null);
2866        } else if (bool === false) {
2867          callback = once(callback);
2868          callback(null);
2869        }
2870      }
2871    };
2872  }
2873
2874  /**
2875   * @private
2876   * @param {Function} arrayEach
2877   * @param {Function} baseEach
2878   * @param {Function} symbolEach
2879   */
2880  function createMap(arrayEach, baseEach, symbolEach, useArray) {
2881    var init, clone;
2882    if (useArray) {
2883      init = Array;
2884      clone = createArray;
2885    } else {
2886      init = function() {
2887        return {};
2888      };
2889      clone = objectClone;
2890    }
2891
2892    return function(collection, iterator, callback) {
2893      callback = callback || noop;
2894      var size, keys, result;
2895      var completed = 0;
2896
2897      if (isArray(collection)) {
2898        size = collection.length;
2899        result = init(size);
2900        arrayEach(collection, iterator, createCallback);
2901      } else if (!collection) {
2902      } else if (iteratorSymbol && collection[iteratorSymbol]) {
2903        // TODO: size could be changed
2904        result = init(0);
2905        size = symbolEach(collection, iterator, createCallback);
2906        size && size === completed && callback(null, result);
2907      } else if (typeof collection === obj) {
2908        keys = nativeKeys(collection);
2909        size = keys.length;
2910        result = init(size);
2911        baseEach(collection, iterator, createCallback, keys);
2912      }
2913      if (!size) {
2914        callback(null, init());
2915      }
2916
2917      function createCallback(key) {
2918        return function done(err, res) {
2919          if (key === null) {
2920            throwError();
2921          }
2922          if (err) {
2923            key = null;
2924            callback = once(callback);
2925            callback(err, clone(result));
2926            return;
2927          }
2928          result[key] = res;
2929          key = null;
2930          if (++completed === size) {
2931            callback(null, result);
2932          }
2933        };
2934      }
2935    };
2936  }
2937
2938  /**
2939   * @private
2940   * @param {Function} arrayEach
2941   * @param {Function} baseEach
2942   * @param {Function} symbolEach
2943   * @param {boolean} bool
2944   */
2945  function createFilter(arrayEach, baseEach, symbolEach, bool) {
2946    return function(collection, iterator, callback) {
2947      callback = callback || noop;
2948      var size, keys, result;
2949      var completed = 0;
2950
2951      if (isArray(collection)) {
2952        size = collection.length;
2953        result = Array(size);
2954        arrayEach(collection, iterator, createCallback);
2955      } else if (!collection) {
2956      } else if (iteratorSymbol && collection[iteratorSymbol]) {
2957        result = [];
2958        size = symbolEach(collection, iterator, createCallback);
2959        size && size === completed && callback(null, compact(result));
2960      } else if (typeof collection === obj) {
2961        keys = nativeKeys(collection);
2962        size = keys.length;
2963        result = Array(size);
2964        baseEach(collection, iterator, createCallback, keys);
2965      }
2966      if (!size) {
2967        return callback(null, []);
2968      }
2969
2970      function createCallback(index, value) {
2971        return function done(err, res) {
2972          if (index === null) {
2973            throwError();
2974          }
2975          if (err) {
2976            index = null;
2977            callback = once(callback);
2978            callback(err);
2979            return;
2980          }
2981          if (!!res === bool) {
2982            result[index] = value;
2983          }
2984          index = null;
2985          if (++completed === size) {
2986            callback(null, compact(result));
2987          }
2988        };
2989      }
2990    };
2991  }
2992
2993  /**
2994   * @private
2995   * @param {boolean} bool
2996   */
2997  function createFilterSeries(bool) {
2998    return function(collection, iterator, callback) {
2999      callback = onlyOnce(callback || noop);
3000      var size, key, value, keys, iter, item, iterate;
3001      var sync = false;
3002      var completed = 0;
3003      var result = [];
3004
3005      if (isArray(collection)) {
3006        size = collection.length;
3007        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3008      } else if (!collection) {
3009      } else if (iteratorSymbol && collection[iteratorSymbol]) {
3010        size = Infinity;
3011        iter = collection[iteratorSymbol]();
3012        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3013      } else if (typeof collection === obj) {
3014        keys = nativeKeys(collection);
3015        size = keys.length;
3016        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3017      }
3018      if (!size) {
3019        return callback(null, []);
3020      }
3021      iterate();
3022
3023      function arrayIterator() {
3024        value = collection[completed];
3025        iterator(value, done);
3026      }
3027
3028      function arrayIteratorWithIndex() {
3029        value = collection[completed];
3030        iterator(value, completed, done);
3031      }
3032
3033      function symbolIterator() {
3034        item = iter.next();
3035        value = item.value;
3036        item.done ? callback(null, result) : iterator(value, done);
3037      }
3038
3039      function symbolIteratorWithKey() {
3040        item = iter.next();
3041        value = item.value;
3042        item.done ? callback(null, result) : iterator(value, completed, done);
3043      }
3044
3045      function objectIterator() {
3046        key = keys[completed];
3047        value = collection[key];
3048        iterator(value, done);
3049      }
3050
3051      function objectIteratorWithKey() {
3052        key = keys[completed];
3053        value = collection[key];
3054        iterator(value, key, done);
3055      }
3056
3057      function done(err, res) {
3058        if (err) {
3059          callback(err);
3060          return;
3061        }
3062        if (!!res === bool) {
3063          result[result.length] = value;
3064        }
3065        if (++completed === size) {
3066          iterate = throwError;
3067          callback(null, result);
3068        } else if (sync) {
3069          nextTick(iterate);
3070        } else {
3071          sync = true;
3072          iterate();
3073        }
3074        sync = false;
3075      }
3076    };
3077  }
3078
3079  /**
3080   * @private
3081   * @param {boolean} bool
3082   */
3083  function createFilterLimit(bool) {
3084    return function(collection, limit, iterator, callback) {
3085      callback = callback || noop;
3086      var size, index, key, value, keys, iter, item, iterate, result;
3087      var sync = false;
3088      var started = 0;
3089      var completed = 0;
3090
3091      if (isArray(collection)) {
3092        size = collection.length;
3093        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3094      } else if (!collection) {
3095      } else if (iteratorSymbol && collection[iteratorSymbol]) {
3096        size = Infinity;
3097        result = [];
3098        iter = collection[iteratorSymbol]();
3099        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3100      } else if (typeof collection === obj) {
3101        keys = nativeKeys(collection);
3102        size = keys.length;
3103        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3104      }
3105      if (!size || isNaN(limit) || limit < 1) {
3106        return callback(null, []);
3107      }
3108      result = result || Array(size);
3109      timesSync(limit > size ? size : limit, iterate);
3110
3111      function arrayIterator() {
3112        index = started++;
3113        if (index < size) {
3114          value = collection[index];
3115          iterator(value, createCallback(value, index));
3116        }
3117      }
3118
3119      function arrayIteratorWithIndex() {
3120        index = started++;
3121        if (index < size) {
3122          value = collection[index];
3123          iterator(value, index, createCallback(value, index));
3124        }
3125      }
3126
3127      function symbolIterator() {
3128        item = iter.next();
3129        if (item.done === false) {
3130          value = item.value;
3131          iterator(value, createCallback(value, started++));
3132        } else if (completed === started && iterator !== noop) {
3133          iterator = noop;
3134          callback(null, compact(result));
3135        }
3136      }
3137
3138      function symbolIteratorWithKey() {
3139        item = iter.next();
3140        if (item.done === false) {
3141          value = item.value;
3142          iterator(value, started, createCallback(value, started++));
3143        } else if (completed === started && iterator !== noop) {
3144          iterator = noop;
3145          callback(null, compact(result));
3146        }
3147      }
3148
3149      function objectIterator() {
3150        index = started++;
3151        if (index < size) {
3152          value = collection[keys[index]];
3153          iterator(value, createCallback(value, index));
3154        }
3155      }
3156
3157      function objectIteratorWithKey() {
3158        index = started++;
3159        if (index < size) {
3160          key = keys[index];
3161          value = collection[key];
3162          iterator(value, key, createCallback(value, index));
3163        }
3164      }
3165
3166      function createCallback(value, index) {
3167        return function(err, res) {
3168          if (index === null) {
3169            throwError();
3170          }
3171          if (err) {
3172            index = null;
3173            iterate = noop;
3174            callback = once(callback);
3175            callback(err);
3176            return;
3177          }
3178          if (!!res === bool) {
3179            result[index] = value;
3180          }
3181          index = null;
3182          if (++completed === size) {
3183            callback = onlyOnce(callback);
3184            callback(null, compact(result));
3185          } else if (sync) {
3186            nextTick(iterate);
3187          } else {
3188            sync = true;
3189            iterate();
3190          }
3191          sync = false;
3192        };
3193      }
3194    };
3195  }
3196
3197  /**
3198   * @memberof async
3199   * @namespace eachSeries
3200   * @param {Array|Object} collection
3201   * @param {Function} iterator
3202   * @param {Function} callback
3203   * @example
3204   *
3205   * // array
3206   * var order = [];
3207   * var array = [1, 3, 2];
3208   * var iterator = function(num, done) {
3209   *   setTimeout(function() {
3210   *     order.push(num);
3211   *     done();
3212   *   }, num * 10);
3213   * };
3214   * async.eachSeries(array, iterator, function(err, res) {
3215   *   console.log(res); // undefined
3216   *   console.log(order); // [1, 3, 2]
3217   * });
3218   *
3219   * @example
3220   *
3221   * // array with index
3222   * var order = [];
3223   * var array = [1, 3, 2];
3224   * var iterator = function(num, index, done) {
3225   *   setTimeout(function() {
3226   *     order.push([num, index]);
3227   *     done();
3228   *   }, num * 10);
3229   * };
3230   * async.eachSeries(array, iterator, function(err, res) {
3231   *   console.log(res); // undefined
3232   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
3233   * });
3234   *
3235   * @example
3236   *
3237   * // object
3238   * var order = [];
3239   * var object = { a: 1, b: 3, c: 2 };
3240   * var iterator = function(num, done) {
3241   *   setTimeout(function() {
3242   *     order.push(num);
3243   *     done();
3244   *   }, num * 10);
3245   * };
3246   * async.eachSeries(object, iterator, function(err, res) {
3247   *   console.log(res); // undefined
3248   *   console.log(order); // [1, 3, 2]
3249   * });
3250   *
3251   * @example
3252   *
3253   * // object with key
3254   * var order = [];
3255   * var object = { a: 1, b: 3, c: 2 };
3256   * var iterator = function(num, key, done) {
3257   *   setTimeout(function() {
3258   *     order.push([num, key]);
3259   *     done();
3260   *   }, num * 10);
3261   * };
3262   * async.eachSeries(object, iterator, function(err, res) {
3263   *   console.log(res); // undefined
3264   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b']]
3265   * });
3266   *
3267   * @example
3268   *
3269   * // break
3270   * var order = [];
3271   * var array = [1, 3, 2];
3272   * var iterator = function(num, done) {
3273   *   setTimeout(function() {
3274   *     order.push(num);
3275   *     done(null, num !== 3);
3276   *   }, num * 10);
3277   * };
3278   * async.eachSeries(array, iterator, function(err, res) {
3279   *   console.log(res); // undefined
3280   *   console.log(order); // [1, 3]
3281   * });
3282   */
3283  function eachSeries(collection, iterator, callback) {
3284    callback = onlyOnce(callback || noop);
3285    var size, key, keys, iter, item, iterate;
3286    var sync = false;
3287    var completed = 0;
3288
3289    if (isArray(collection)) {
3290      size = collection.length;
3291      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3292    } else if (!collection) {
3293    } else if (iteratorSymbol && collection[iteratorSymbol]) {
3294      size = Infinity;
3295      iter = collection[iteratorSymbol]();
3296      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3297    } else if (typeof collection === obj) {
3298      keys = nativeKeys(collection);
3299      size = keys.length;
3300      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3301    }
3302    if (!size) {
3303      return callback(null);
3304    }
3305    iterate();
3306
3307    function arrayIterator() {
3308      iterator(collection[completed], done);
3309    }
3310
3311    function arrayIteratorWithIndex() {
3312      iterator(collection[completed], completed, done);
3313    }
3314
3315    function symbolIterator() {
3316      item = iter.next();
3317      item.done ? callback(null) : iterator(item.value, done);
3318    }
3319
3320    function symbolIteratorWithKey() {
3321      item = iter.next();
3322      item.done ? callback(null) : iterator(item.value, completed, done);
3323    }
3324
3325    function objectIterator() {
3326      iterator(collection[keys[completed]], done);
3327    }
3328
3329    function objectIteratorWithKey() {
3330      key = keys[completed];
3331      iterator(collection[key], key, done);
3332    }
3333
3334    function done(err, bool) {
3335      if (err) {
3336        callback(err);
3337      } else if (++completed === size || bool === false) {
3338        iterate = throwError;
3339        callback(null);
3340      } else if (sync) {
3341        nextTick(iterate);
3342      } else {
3343        sync = true;
3344        iterate();
3345      }
3346      sync = false;
3347    }
3348  }
3349
3350  /**
3351   * @memberof async
3352   * @namespace eachLimit
3353   * @param {Array|Object} collection
3354   * @param {number} limit - limit >= 1
3355   * @param {Function} iterator
3356   * @param {Function} callback
3357   * @example
3358   *
3359   * // array
3360   * var order = [];
3361   * var array = [1, 5, 3, 4, 2];
3362   * var iterator = function(num, done) {
3363   *   setTimeout(function() {
3364   *     order.push(num);
3365   *     done();
3366   *   }, num * 10);
3367   * };
3368   * async.eachLimit(array, 2, iterator, function(err, res) {
3369   *   console.log(res); // undefined
3370   *   console.log(order); // [1, 3, 5, 2, 4]
3371   * });
3372   *
3373   * @example
3374   *
3375   * // array with index
3376   * var order = [];
3377   * var array = [1, 5, 3, 4, 2];
3378   * var iterator = function(num, index, done) {
3379   *   setTimeout(function() {
3380   *     order.push([num, index]);
3381   *     done();
3382   *   }, num * 10);
3383   * };
3384   * async.eachLimit(array, 2, iterator, function(err, res) {
3385   *   console.log(res); // undefined
3386   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
3387   * });
3388   *
3389   * @example
3390   *
3391   * // object
3392   * var order = [];
3393   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
3394   * var iterator = function(num, done) {
3395   *   setTimeout(function() {
3396   *     order.push(num);
3397   *     done();
3398   *   }, num * 10);
3399   * };
3400   * async.eachLimit(object, 2, iterator, function(err, res) {
3401   *   console.log(res); // undefined
3402   *   console.log(order); // [1, 3, 5, 2, 4]
3403   * });
3404   *
3405   * @example
3406   *
3407   * // object with key
3408   * var order = [];
3409   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
3410   * var iterator = function(num, key, done) {
3411   *   setTimeout(function() {
3412   *     order.push([num, key]);
3413   *     done();
3414   *   }, num * 10);
3415   * };
3416   * async.eachLimit(object, 2, iterator, function(err, res) {
3417   *   console.log(res); // undefined
3418   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
3419   * });
3420   *
3421   * @example
3422   *
3423   * // break
3424   * var order = [];
3425   * var array = [1, 5, 3, 4, 2];
3426   * var iterator = function(num, done) {
3427   *   setTimeout(function() {
3428   *     order.push(num);
3429   *     done(null, num !== 5);
3430   *   }, num * 10);
3431   * };
3432   * async.eachLimit(array, 2, iterator, function(err, res) {
3433   *   console.log(res); // undefined
3434   *   console.log(order); // [1, 3, 5]
3435   * });
3436   *
3437   */
3438  function eachLimit(collection, limit, iterator, callback) {
3439    callback = callback || noop;
3440    var size, index, key, keys, iter, item, iterate;
3441    var sync = false;
3442    var started = 0;
3443    var completed = 0;
3444
3445    if (isArray(collection)) {
3446      size = collection.length;
3447      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3448    } else if (!collection) {
3449    } else if (iteratorSymbol && collection[iteratorSymbol]) {
3450      size = Infinity;
3451      iter = collection[iteratorSymbol]();
3452      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3453    } else if (typeof collection === obj) {
3454      keys = nativeKeys(collection);
3455      size = keys.length;
3456      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3457    } else {
3458      return callback(null);
3459    }
3460    if (!size || isNaN(limit) || limit < 1) {
3461      return callback(null);
3462    }
3463    timesSync(limit > size ? size : limit, iterate);
3464
3465    function arrayIterator() {
3466      if (started < size) {
3467        iterator(collection[started++], done);
3468      }
3469    }
3470
3471    function arrayIteratorWithIndex() {
3472      index = started++;
3473      if (index < size) {
3474        iterator(collection[index], index, done);
3475      }
3476    }
3477
3478    function symbolIterator() {
3479      item = iter.next();
3480      if (item.done === false) {
3481        started++;
3482        iterator(item.value, done);
3483      } else if (completed === started && iterator !== noop) {
3484        iterator = noop;
3485        callback(null);
3486      }
3487    }
3488
3489    function symbolIteratorWithKey() {
3490      item = iter.next();
3491      if (item.done === false) {
3492        iterator(item.value, started++, done);
3493      } else if (completed === started && iterator !== noop) {
3494        iterator = noop;
3495        callback(null);
3496      }
3497    }
3498
3499    function objectIterator() {
3500      if (started < size) {
3501        iterator(collection[keys[started++]], done);
3502      }
3503    }
3504
3505    function objectIteratorWithKey() {
3506      index = started++;
3507      if (index < size) {
3508        key = keys[index];
3509        iterator(collection[key], key, done);
3510      }
3511    }
3512
3513    function done(err, bool) {
3514      if (err || bool === false) {
3515        iterate = noop;
3516        callback = once(callback);
3517        callback(err);
3518      } else if (++completed === size) {
3519        iterator = noop;
3520        iterate = throwError;
3521        callback = onlyOnce(callback);
3522        callback(null);
3523      } else if (sync) {
3524        nextTick(iterate);
3525      } else {
3526        sync = true;
3527        iterate();
3528      }
3529      sync = false;
3530    }
3531  }
3532
3533  /**
3534   * @memberof async
3535   * @namespace mapSeries
3536   * @param {Array|Object} collection
3537   * @param {Function} iterator
3538   * @param {Function} callback
3539   * @example
3540   *
3541   * // array
3542   * var order = [];
3543   * var array = [1, 3, 2];
3544   * var iterator = function(num, done) {
3545   *   setTimeout(function() {
3546   *     order.push(num);
3547   *     done(null, num);
3548   *   }, num * 10);
3549   * };
3550   * async.mapSeries(array, iterator, function(err, res) {
3551   *   console.log(res); // [1, 3, 2];
3552   *   console.log(order); // [1, 3, 2]
3553   * });
3554   *
3555   * @example
3556   *
3557   * // array with index
3558   * var order = [];
3559   * var array = [1, 3, 2];
3560   * var iterator = function(num, index, done) {
3561   *   setTimeout(function() {
3562   *     order.push([num, index]);
3563   *     done(null, num);
3564   *   }, num * 10);
3565   * };
3566   * async.mapSeries(array, iterator, function(err, res) {
3567   *   console.log(res); // [1, 3, 2]
3568   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
3569   * });
3570   *
3571   * @example
3572   *
3573   * // object
3574   * var order = [];
3575   * var object = { a: 1, b: 3, c: 2 };
3576   * var iterator = function(num, done) {
3577   *   setTimeout(function() {
3578   *     order.push(num);
3579   *     done(null, num);
3580   *   }, num * 10);
3581   * };
3582   * async.mapSeries(object, iterator, function(err, res) {
3583   *   console.log(res); // [1, 3, 2]
3584   *   console.log(order); // [1, 3, 2]
3585   * });
3586   *
3587   * @example
3588   *
3589   * // object with key
3590   * var order = [];
3591   * var object = { a: 1, b: 3, c: 2 };
3592   * var iterator = function(num, key, done) {
3593   *   setTimeout(function() {
3594   *     order.push([num, key]);
3595   *     done(null, num);
3596   *   }, num * 10);
3597   * };
3598   * async.mapSeries(object, iterator, function(err, res) {
3599   *   console.log(res); // [1, 3, 2]
3600   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
3601   * });
3602   *
3603   */
3604  function mapSeries(collection, iterator, callback) {
3605    callback = callback || noop;
3606    var size, key, keys, iter, item, result, iterate;
3607    var sync = false;
3608    var completed = 0;
3609
3610    if (isArray(collection)) {
3611      size = collection.length;
3612      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3613    } else if (!collection) {
3614    } else if (iteratorSymbol && collection[iteratorSymbol]) {
3615      size = Infinity;
3616      result = [];
3617      iter = collection[iteratorSymbol]();
3618      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3619    } else if (typeof collection === obj) {
3620      keys = nativeKeys(collection);
3621      size = keys.length;
3622      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3623    }
3624    if (!size) {
3625      return callback(null, []);
3626    }
3627    result = result || Array(size);
3628    iterate();
3629
3630    function arrayIterator() {
3631      iterator(collection[completed], done);
3632    }
3633
3634    function arrayIteratorWithIndex() {
3635      iterator(collection[completed], completed, done);
3636    }
3637
3638    function symbolIterator() {
3639      item = iter.next();
3640      item.done ? callback(null, result) : iterator(item.value, done);
3641    }
3642
3643    function symbolIteratorWithKey() {
3644      item = iter.next();
3645      item.done ? callback(null, result) : iterator(item.value, completed, done);
3646    }
3647
3648    function objectIterator() {
3649      iterator(collection[keys[completed]], done);
3650    }
3651
3652    function objectIteratorWithKey() {
3653      key = keys[completed];
3654      iterator(collection[key], key, done);
3655    }
3656
3657    function done(err, res) {
3658      if (err) {
3659        iterate = throwError;
3660        callback = onlyOnce(callback);
3661        callback(err, createArray(result));
3662        return;
3663      }
3664      result[completed] = res;
3665      if (++completed === size) {
3666        iterate = throwError;
3667        callback(null, result);
3668        callback = throwError;
3669      } else if (sync) {
3670        nextTick(iterate);
3671      } else {
3672        sync = true;
3673        iterate();
3674      }
3675      sync = false;
3676    }
3677  }
3678
3679  /**
3680   * @memberof async
3681   * @namespace mapLimit
3682   * @param {Array|Object} collection
3683   * @param {number} limit - limit >= 1
3684   * @param {Function} iterator
3685   * @param {Function} callback
3686   * @example
3687   *
3688   * // array
3689   * var order = [];
3690   * var array = [1, 5, 3, 4, 2];
3691   * var iterator = function(num, done) {
3692   *   setTimeout(function() {
3693   *     order.push(num);
3694   *     done(null, num);
3695   *   }, num * 10);
3696   * };
3697   * async.mapLimit(array, 2, iterator, function(err, res) {
3698   *   console.log(res); // [1, 5, 3, 4, 2]
3699   *   console.log(order); // [1, 3, 5, 2, 4]
3700   * });
3701   *
3702   * @example
3703   *
3704   * // array with index
3705   * var order = [];
3706   * var array = [1, 5, 3, 4, 2];
3707   * var iterator = function(num, index, done) {
3708   *   setTimeout(function() {
3709   *     order.push([num, index]);
3710   *     done(null, num);
3711   *   }, num * 10);
3712   * };
3713   * async.mapLimit(array, 2, iterator, function(err, res) {
3714   *   console.log(res); // [1, 5, 3, 4, 2]
3715   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
3716   * });
3717   *
3718   * @example
3719   *
3720   * // object
3721   * var order = [];
3722   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
3723   * var iterator = function(num, done) {
3724   *   setTimeout(function() {
3725   *     order.push(num);
3726   *     done(null, num);
3727   *   }, num * 10);
3728   * };
3729   * async.mapLimit(object, 2, iterator, function(err, res) {
3730   *   console.log(res); // [1, 5, 3, 4, 2]
3731   *   console.log(order); // [1, 3, 5, 2, 4]
3732   * });
3733   *
3734   * @example
3735   *
3736   * // object with key
3737   * var order = [];
3738   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
3739   * var iterator = function(num, key, done) {
3740   *   setTimeout(function() {
3741   *     order.push([num, key]);
3742   *     done(null, num);
3743   *   }, num * 10);
3744   * };
3745   * async.mapLimit(object, 2, iterator, function(err, res) {
3746   *   console.log(res); // [1, 5, 3, 4, 2]
3747   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
3748   * });
3749   *
3750   */
3751  function mapLimit(collection, limit, iterator, callback) {
3752    callback = callback || noop;
3753    var size, index, key, keys, iter, item, result, iterate;
3754    var sync = false;
3755    var started = 0;
3756    var completed = 0;
3757
3758    if (isArray(collection)) {
3759      size = collection.length;
3760      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3761    } else if (!collection) {
3762    } else if (iteratorSymbol && collection[iteratorSymbol]) {
3763      size = Infinity;
3764      result = [];
3765      iter = collection[iteratorSymbol]();
3766      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3767    } else if (typeof collection === obj) {
3768      keys = nativeKeys(collection);
3769      size = keys.length;
3770      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3771    }
3772    if (!size || isNaN(limit) || limit < 1) {
3773      return callback(null, []);
3774    }
3775    result = result || Array(size);
3776    timesSync(limit > size ? size : limit, iterate);
3777
3778    function arrayIterator() {
3779      index = started++;
3780      if (index < size) {
3781        iterator(collection[index], createCallback(index));
3782      }
3783    }
3784
3785    function arrayIteratorWithIndex() {
3786      index = started++;
3787      if (index < size) {
3788        iterator(collection[index], index, createCallback(index));
3789      }
3790    }
3791
3792    function symbolIterator() {
3793      item = iter.next();
3794      if (item.done === false) {
3795        iterator(item.value, createCallback(started++));
3796      } else if (completed === started && iterator !== noop) {
3797        iterator = noop;
3798        callback(null, result);
3799      }
3800    }
3801
3802    function symbolIteratorWithKey() {
3803      item = iter.next();
3804      if (item.done === false) {
3805        iterator(item.value, started, createCallback(started++));
3806      } else if (completed === started && iterator !== noop) {
3807        iterator = noop;
3808        callback(null, result);
3809      }
3810    }
3811
3812    function objectIterator() {
3813      index = started++;
3814      if (index < size) {
3815        iterator(collection[keys[index]], createCallback(index));
3816      }
3817    }
3818
3819    function objectIteratorWithKey() {
3820      index = started++;
3821      if (index < size) {
3822        key = keys[index];
3823        iterator(collection[key], key, createCallback(index));
3824      }
3825    }
3826
3827    function createCallback(index) {
3828      return function(err, res) {
3829        if (index === null) {
3830          throwError();
3831        }
3832        if (err) {
3833          index = null;
3834          iterate = noop;
3835          callback = once(callback);
3836          callback(err, createArray(result));
3837          return;
3838        }
3839        result[index] = res;
3840        index = null;
3841        if (++completed === size) {
3842          iterate = throwError;
3843          callback(null, result);
3844          callback = throwError;
3845        } else if (sync) {
3846          nextTick(iterate);
3847        } else {
3848          sync = true;
3849          iterate();
3850        }
3851        sync = false;
3852      };
3853    }
3854  }
3855
3856  /**
3857   * @memberof async
3858   * @namespace mapValuesSeries
3859   * @param {Array|Object} collection
3860   * @param {Function} iterator
3861   * @param {Function} callback
3862   * @example
3863   *
3864   * // array
3865   * var order = [];
3866   * var array = [1, 3, 2];
3867   * var iterator = function(num, done) {
3868   *   setTimeout(function() {
3869   *     order.push(num);
3870   *     done(null, num);
3871   *   }, num * 10);
3872   * };
3873   * async.mapValuesSeries(array, iterator, function(err, res) {
3874   *   console.log(res); // { '0': 1, '1': 3, '2': 2 }
3875   *   console.log(order); // [1, 3, 2]
3876   * });
3877   *
3878   * @example
3879   *
3880   * // array with index
3881   * var order = [];
3882   * var array = [1, 3, 2];
3883   * var iterator = function(num, index, done) {
3884   *   setTimeout(function() {
3885   *     order.push([num, index]);
3886   *     done(null, num);
3887   *   }, num * 10);
3888   * };
3889   * async.mapValuesSeries(array, iterator, function(err, res) {
3890   *   console.log(res); // { '0': 1, '1': 3, '2': 2 }
3891   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
3892   * });
3893   *
3894   * @example
3895   *
3896   * // object
3897   * var order = [];
3898   * var object = { a: 1, b: 3, c: 2 };
3899   * var iterator = function(num, done) {
3900   *   setTimeout(function() {
3901   *     order.push(num);
3902   *     done(null, num);
3903   *   }, num * 10);
3904   * };
3905   * async.mapValuesSeries(object, iterator, function(err, res) {
3906   *   console.log(res); // { a: 1, b: 3, c: 2 }
3907   *   console.log(order); // [1, 3, 2]
3908   * });
3909   *
3910   * @example
3911   *
3912   * // object with key
3913   * var order = [];
3914   * var object = { a: 1, b: 3, c: 2 };
3915   * var iterator = function(num, key, done) {
3916   *   setTimeout(function() {
3917   *     order.push([num, key]);
3918   *     done(null, num);
3919   *   }, num * 10);
3920   * };
3921   * async.mapValuesSeries(object, iterator, function(err, res) {
3922   *   console.log(res); // { a: 1, b: 3, c: 2 }
3923   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
3924   * });
3925   *
3926   */
3927  function mapValuesSeries(collection, iterator, callback) {
3928    callback = callback || noop;
3929    var size, key, keys, iter, item, iterate;
3930    var sync = false;
3931    var result = {};
3932    var completed = 0;
3933
3934    if (isArray(collection)) {
3935      size = collection.length;
3936      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
3937    } else if (!collection) {
3938    } else if (iteratorSymbol && collection[iteratorSymbol]) {
3939      size = Infinity;
3940      iter = collection[iteratorSymbol]();
3941      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
3942    } else if (typeof collection === obj) {
3943      keys = nativeKeys(collection);
3944      size = keys.length;
3945      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
3946    }
3947    if (!size) {
3948      return callback(null, result);
3949    }
3950    iterate();
3951
3952    function arrayIterator() {
3953      key = completed;
3954      iterator(collection[completed], done);
3955    }
3956
3957    function arrayIteratorWithIndex() {
3958      key = completed;
3959      iterator(collection[completed], completed, done);
3960    }
3961
3962    function symbolIterator() {
3963      key = completed;
3964      item = iter.next();
3965      item.done ? callback(null, result) : iterator(item.value, done);
3966    }
3967
3968    function symbolIteratorWithKey() {
3969      key = completed;
3970      item = iter.next();
3971      item.done ? callback(null, result) : iterator(item.value, completed, done);
3972    }
3973
3974    function objectIterator() {
3975      key = keys[completed];
3976      iterator(collection[key], done);
3977    }
3978
3979    function objectIteratorWithKey() {
3980      key = keys[completed];
3981      iterator(collection[key], key, done);
3982    }
3983
3984    function done(err, res) {
3985      if (err) {
3986        iterate = throwError;
3987        callback = onlyOnce(callback);
3988        callback(err, objectClone(result));
3989        return;
3990      }
3991      result[key] = res;
3992      if (++completed === size) {
3993        iterate = throwError;
3994        callback(null, result);
3995        callback = throwError;
3996      } else if (sync) {
3997        nextTick(iterate);
3998      } else {
3999        sync = true;
4000        iterate();
4001      }
4002      sync = false;
4003    }
4004  }
4005
4006  /**
4007   * @memberof async
4008   * @namespace mapValuesLimit
4009   * @param {Array|Object} collection
4010   * @param {number} limit - limit >= 1
4011   * @param {Function} iterator
4012   * @param {Function} callback
4013   * @example
4014   *
4015   * // array
4016   * var order = [];
4017   * var array = [1, 5, 3, 4, 2];
4018   * var iterator = function(num, done) {
4019   *   setTimeout(function() {
4020   *     order.push(num);
4021   *     done(null, num);
4022   *   }, num * 10);
4023   * };
4024   * async.mapValuesLimit(array, 2, iterator, function(err, res) {
4025   *   console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 }
4026   *   console.log(order); // [1, 3, 5, 2, 4]
4027   * });
4028   *
4029   * @example
4030   *
4031   * // array with index
4032   * var order = [];
4033   * var array = [1, 5, 3, 4, 2];
4034   * var iterator = function(num, index, done) {
4035   *   setTimeout(function() {
4036   *     order.push([num, index]);
4037   *     done(null, num);
4038   *   }, num * 10);
4039   * };
4040   * async.mapValuesLimit(array, 2, iterator, function(err, res) {
4041   *   console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 }
4042   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
4043   * });
4044   *
4045   * @example
4046   *
4047   * // object
4048   * var order = [];
4049   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
4050   * var iterator = function(num, done) {
4051   *   setTimeout(function() {
4052   *     order.push(num);
4053   *     done(null, num);
4054   *   }, num * 10);
4055   * };
4056   * async.mapValuesLimit(object, 2, iterator, function(err, res) {
4057   *   console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 }
4058   *   console.log(order); // [1, 3, 5, 2, 4]
4059   * });
4060   *
4061   * @example
4062   *
4063   * // object with key
4064   * var order = [];
4065   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
4066   * var iterator = function(num, key, done) {
4067   *   setTimeout(function() {
4068   *     order.push([num, key]);
4069   *     done(null, num);
4070   *   }, num * 10);
4071   * };
4072   * async.mapValuesLimit(object, 2, iterator, function(err, res) {
4073   *   console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 }
4074   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
4075   * });
4076   *
4077   */
4078  function mapValuesLimit(collection, limit, iterator, callback) {
4079    callback = callback || noop;
4080    var size, index, key, keys, iter, item, iterate;
4081    var sync = false;
4082    var result = {};
4083    var started = 0;
4084    var completed = 0;
4085
4086    if (isArray(collection)) {
4087      size = collection.length;
4088      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
4089    } else if (!collection) {
4090    } else if (iteratorSymbol && collection[iteratorSymbol]) {
4091      size = Infinity;
4092      iter = collection[iteratorSymbol]();
4093      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
4094    } else if (typeof collection === obj) {
4095      keys = nativeKeys(collection);
4096      size = keys.length;
4097      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
4098    }
4099    if (!size || isNaN(limit) || limit < 1) {
4100      return callback(null, result);
4101    }
4102    timesSync(limit > size ? size : limit, iterate);
4103
4104    function arrayIterator() {
4105      index = started++;
4106      if (index < size) {
4107        iterator(collection[index], createCallback(index));
4108      }
4109    }
4110
4111    function arrayIteratorWithIndex() {
4112      index = started++;
4113      if (index < size) {
4114        iterator(collection[index], index, createCallback(index));
4115      }
4116    }
4117
4118    function symbolIterator() {
4119      item = iter.next();
4120      if (item.done === false) {
4121        iterator(item.value, createCallback(started++));
4122      } else if (completed === started && iterator !== noop) {
4123        iterator = noop;
4124        callback(null, result);
4125      }
4126    }
4127
4128    function symbolIteratorWithKey() {
4129      item = iter.next();
4130      if (item.done === false) {
4131        iterator(item.value, started, createCallback(started++));
4132      } else if (completed === started && iterator !== noop) {
4133        iterator = noop;
4134        callback(null, result);
4135      }
4136    }
4137
4138    function objectIterator() {
4139      index = started++;
4140      if (index < size) {
4141        key = keys[index];
4142        iterator(collection[key], createCallback(key));
4143      }
4144    }
4145
4146    function objectIteratorWithKey() {
4147      index = started++;
4148      if (index < size) {
4149        key = keys[index];
4150        iterator(collection[key], key, createCallback(key));
4151      }
4152    }
4153
4154    function createCallback(key) {
4155      return function(err, res) {
4156        if (key === null) {
4157          throwError();
4158        }
4159        if (err) {
4160          key = null;
4161          iterate = noop;
4162          callback = once(callback);
4163          callback(err, objectClone(result));
4164          return;
4165        }
4166        result[key] = res;
4167        key = null;
4168        if (++completed === size) {
4169          callback(null, result);
4170        } else if (sync) {
4171          nextTick(iterate);
4172        } else {
4173          sync = true;
4174          iterate();
4175        }
4176        sync = false;
4177      };
4178    }
4179  }
4180
4181  /**
4182   * @private
4183   * @param {Function} arrayEach
4184   * @param {Function} baseEach
4185   * @param {Function} symbolEach
4186   * @param {boolean} bool
4187   */
4188  function createDetect(arrayEach, baseEach, symbolEach, bool) {
4189    return function(collection, iterator, callback) {
4190      callback = callback || noop;
4191      var size, keys;
4192      var completed = 0;
4193
4194      if (isArray(collection)) {
4195        size = collection.length;
4196        arrayEach(collection, iterator, createCallback);
4197      } else if (!collection) {
4198      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4199        size = symbolEach(collection, iterator, createCallback);
4200        size && size === completed && callback(null);
4201      } else if (typeof collection === obj) {
4202        keys = nativeKeys(collection);
4203        size = keys.length;
4204        baseEach(collection, iterator, createCallback, keys);
4205      }
4206      if (!size) {
4207        callback(null);
4208      }
4209
4210      function createCallback(value) {
4211        var called = false;
4212        return function done(err, res) {
4213          if (called) {
4214            throwError();
4215          }
4216          called = true;
4217          if (err) {
4218            callback = once(callback);
4219            callback(err);
4220          } else if (!!res === bool) {
4221            callback = once(callback);
4222            callback(null, value);
4223          } else if (++completed === size) {
4224            callback(null);
4225          }
4226        };
4227      }
4228    };
4229  }
4230
4231  /**
4232   * @private
4233   * @param {boolean} bool
4234   */
4235  function createDetectSeries(bool) {
4236    return function(collection, iterator, callback) {
4237      callback = onlyOnce(callback || noop);
4238      var size, key, value, keys, iter, item, iterate;
4239      var sync = false;
4240      var completed = 0;
4241
4242      if (isArray(collection)) {
4243        size = collection.length;
4244        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
4245      } else if (!collection) {
4246      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4247        size = Infinity;
4248        iter = collection[iteratorSymbol]();
4249        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
4250      } else if (typeof collection === obj) {
4251        keys = nativeKeys(collection);
4252        size = keys.length;
4253        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
4254      }
4255      if (!size) {
4256        return callback(null);
4257      }
4258      iterate();
4259
4260      function arrayIterator() {
4261        value = collection[completed];
4262        iterator(value, done);
4263      }
4264
4265      function arrayIteratorWithIndex() {
4266        value = collection[completed];
4267        iterator(value, completed, done);
4268      }
4269
4270      function symbolIterator() {
4271        item = iter.next();
4272        value = item.value;
4273        item.done ? callback(null) : iterator(value, done);
4274      }
4275
4276      function symbolIteratorWithKey() {
4277        item = iter.next();
4278        value = item.value;
4279        item.done ? callback(null) : iterator(value, completed, done);
4280      }
4281
4282      function objectIterator() {
4283        value = collection[keys[completed]];
4284        iterator(value, done);
4285      }
4286
4287      function objectIteratorWithKey() {
4288        key = keys[completed];
4289        value = collection[key];
4290        iterator(value, key, done);
4291      }
4292
4293      function done(err, res) {
4294        if (err) {
4295          callback(err);
4296        } else if (!!res === bool) {
4297          iterate = throwError;
4298          callback(null, value);
4299        } else if (++completed === size) {
4300          iterate = throwError;
4301          callback(null);
4302        } else if (sync) {
4303          nextTick(iterate);
4304        } else {
4305          sync = true;
4306          iterate();
4307        }
4308        sync = false;
4309      }
4310    };
4311  }
4312
4313  /**
4314   * @private
4315   * @param {boolean} bool
4316   */
4317  function createDetectLimit(bool) {
4318    return function(collection, limit, iterator, callback) {
4319      callback = callback || noop;
4320      var size, index, key, value, keys, iter, item, iterate;
4321      var sync = false;
4322      var started = 0;
4323      var completed = 0;
4324
4325      if (isArray(collection)) {
4326        size = collection.length;
4327        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
4328      } else if (!collection) {
4329      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4330        size = Infinity;
4331        iter = collection[iteratorSymbol]();
4332        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
4333      } else if (typeof collection === obj) {
4334        keys = nativeKeys(collection);
4335        size = keys.length;
4336        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
4337      }
4338      if (!size || isNaN(limit) || limit < 1) {
4339        return callback(null);
4340      }
4341      timesSync(limit > size ? size : limit, iterate);
4342
4343      function arrayIterator() {
4344        index = started++;
4345        if (index < size) {
4346          value = collection[index];
4347          iterator(value, createCallback(value));
4348        }
4349      }
4350
4351      function arrayIteratorWithIndex() {
4352        index = started++;
4353        if (index < size) {
4354          value = collection[index];
4355          iterator(value, index, createCallback(value));
4356        }
4357      }
4358
4359      function symbolIterator() {
4360        item = iter.next();
4361        if (item.done === false) {
4362          started++;
4363          value = item.value;
4364          iterator(value, createCallback(value));
4365        } else if (completed === started && iterator !== noop) {
4366          iterator = noop;
4367          callback(null);
4368        }
4369      }
4370
4371      function symbolIteratorWithKey() {
4372        item = iter.next();
4373        if (item.done === false) {
4374          value = item.value;
4375          iterator(value, started++, createCallback(value));
4376        } else if (completed === started && iterator !== noop) {
4377          iterator = noop;
4378          callback(null);
4379        }
4380      }
4381
4382      function objectIterator() {
4383        index = started++;
4384        if (index < size) {
4385          value = collection[keys[index]];
4386          iterator(value, createCallback(value));
4387        }
4388      }
4389
4390      function objectIteratorWithKey() {
4391        if (started < size) {
4392          key = keys[started++];
4393          value = collection[key];
4394          iterator(value, key, createCallback(value));
4395        }
4396      }
4397
4398      function createCallback(value) {
4399        var called = false;
4400        return function(err, res) {
4401          if (called) {
4402            throwError();
4403          }
4404          called = true;
4405          if (err) {
4406            iterate = noop;
4407            callback = once(callback);
4408            callback(err);
4409          } else if (!!res === bool) {
4410            iterate = noop;
4411            callback = once(callback);
4412            callback(null, value);
4413          } else if (++completed === size) {
4414            callback(null);
4415          } else if (sync) {
4416            nextTick(iterate);
4417          } else {
4418            sync = true;
4419            iterate();
4420          }
4421          sync = false;
4422        };
4423      }
4424    };
4425  }
4426
4427  /**
4428   * @private
4429   * @param {Function} arrayEach
4430   * @param {Function} baseEach
4431   * @param {Function} symbolEach
4432   * @param {boolean} bool
4433   */
4434  function createPick(arrayEach, baseEach, symbolEach, bool) {
4435    return function(collection, iterator, callback) {
4436      callback = callback || noop;
4437      var size, keys;
4438      var completed = 0;
4439      var result = {};
4440
4441      if (isArray(collection)) {
4442        size = collection.length;
4443        arrayEach(collection, iterator, createCallback);
4444      } else if (!collection) {
4445      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4446        size = symbolEach(collection, iterator, createCallback);
4447        size && size === completed && callback(null, result);
4448      } else if (typeof collection === obj) {
4449        keys = nativeKeys(collection);
4450        size = keys.length;
4451        baseEach(collection, iterator, createCallback, keys);
4452      }
4453      if (!size) {
4454        return callback(null, {});
4455      }
4456
4457      function createCallback(key, value) {
4458        return function done(err, res) {
4459          if (key === null) {
4460            throwError();
4461          }
4462          if (err) {
4463            key = null;
4464            callback = once(callback);
4465            callback(err, objectClone(result));
4466            return;
4467          }
4468          if (!!res === bool) {
4469            result[key] = value;
4470          }
4471          key = null;
4472          if (++completed === size) {
4473            callback(null, result);
4474          }
4475        };
4476      }
4477    };
4478  }
4479
4480  /**
4481   * @private
4482   * @param {boolean} bool
4483   */
4484  function createPickSeries(bool) {
4485    return function(collection, iterator, callback) {
4486      callback = onlyOnce(callback || noop);
4487      var size, key, value, keys, iter, item, iterate;
4488      var sync = false;
4489      var result = {};
4490      var completed = 0;
4491
4492      if (isArray(collection)) {
4493        size = collection.length;
4494        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
4495      } else if (!collection) {
4496      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4497        size = Infinity;
4498        iter = collection[iteratorSymbol]();
4499        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
4500      } else if (typeof collection === obj) {
4501        keys = nativeKeys(collection);
4502        size = keys.length;
4503        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
4504      }
4505      if (!size) {
4506        return callback(null, {});
4507      }
4508      iterate();
4509
4510      function arrayIterator() {
4511        key = completed;
4512        value = collection[completed];
4513        iterator(value, done);
4514      }
4515
4516      function arrayIteratorWithIndex() {
4517        key = completed;
4518        value = collection[completed];
4519        iterator(value, completed, done);
4520      }
4521
4522      function symbolIterator() {
4523        key = completed;
4524        item = iter.next();
4525        value = item.value;
4526        item.done ? callback(null, result) : iterator(value, done);
4527      }
4528
4529      function symbolIteratorWithKey() {
4530        key = completed;
4531        item = iter.next();
4532        value = item.value;
4533        item.done ? callback(null, result) : iterator(value, key, done);
4534      }
4535
4536      function objectIterator() {
4537        key = keys[completed];
4538        value = collection[key];
4539        iterator(value, done);
4540      }
4541
4542      function objectIteratorWithKey() {
4543        key = keys[completed];
4544        value = collection[key];
4545        iterator(value, key, done);
4546      }
4547
4548      function done(err, res) {
4549        if (err) {
4550          callback(err, result);
4551          return;
4552        }
4553        if (!!res === bool) {
4554          result[key] = value;
4555        }
4556        if (++completed === size) {
4557          iterate = throwError;
4558          callback(null, result);
4559        } else if (sync) {
4560          nextTick(iterate);
4561        } else {
4562          sync = true;
4563          iterate();
4564        }
4565        sync = false;
4566      }
4567    };
4568  }
4569
4570  /**
4571   * @private
4572   * @param {boolean} bool
4573   */
4574  function createPickLimit(bool) {
4575    return function(collection, limit, iterator, callback) {
4576      callback = callback || noop;
4577      var size, index, key, value, keys, iter, item, iterate;
4578      var sync = false;
4579      var result = {};
4580      var started = 0;
4581      var completed = 0;
4582
4583      if (isArray(collection)) {
4584        size = collection.length;
4585        iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
4586      } else if (!collection) {
4587      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4588        size = Infinity;
4589        iter = collection[iteratorSymbol]();
4590        iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
4591      } else if (typeof collection === obj) {
4592        keys = nativeKeys(collection);
4593        size = keys.length;
4594        iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
4595      }
4596      if (!size || isNaN(limit) || limit < 1) {
4597        return callback(null, {});
4598      }
4599      timesSync(limit > size ? size : limit, iterate);
4600
4601      function arrayIterator() {
4602        index = started++;
4603        if (index < size) {
4604          value = collection[index];
4605          iterator(value, createCallback(value, index));
4606        }
4607      }
4608
4609      function arrayIteratorWithIndex() {
4610        index = started++;
4611        if (index < size) {
4612          value = collection[index];
4613          iterator(value, index, createCallback(value, index));
4614        }
4615      }
4616
4617      function symbolIterator() {
4618        item = iter.next();
4619        if (item.done === false) {
4620          value = item.value;
4621          iterator(value, createCallback(value, started++));
4622        } else if (completed === started && iterator !== noop) {
4623          iterator = noop;
4624          callback(null, result);
4625        }
4626      }
4627
4628      function symbolIteratorWithKey() {
4629        item = iter.next();
4630        if (item.done === false) {
4631          value = item.value;
4632          iterator(value, started, createCallback(value, started++));
4633        } else if (completed === started && iterator !== noop) {
4634          iterator = noop;
4635          callback(null, result);
4636        }
4637      }
4638
4639      function objectIterator() {
4640        if (started < size) {
4641          key = keys[started++];
4642          value = collection[key];
4643          iterator(value, createCallback(value, key));
4644        }
4645      }
4646
4647      function objectIteratorWithKey() {
4648        if (started < size) {
4649          key = keys[started++];
4650          value = collection[key];
4651          iterator(value, key, createCallback(value, key));
4652        }
4653      }
4654
4655      function createCallback(value, key) {
4656        return function(err, res) {
4657          if (key === null) {
4658            throwError();
4659          }
4660          if (err) {
4661            key = null;
4662            iterate = noop;
4663            callback = once(callback);
4664            callback(err, objectClone(result));
4665            return;
4666          }
4667          if (!!res === bool) {
4668            result[key] = value;
4669          }
4670          key = null;
4671          if (++completed === size) {
4672            iterate = throwError;
4673            callback = onlyOnce(callback);
4674            callback(null, result);
4675          } else if (sync) {
4676            nextTick(iterate);
4677          } else {
4678            sync = true;
4679            iterate();
4680          }
4681          sync = false;
4682        };
4683      }
4684    };
4685  }
4686
4687  /**
4688   * @memberof async
4689   * @namespace reduce
4690   * @param {Array|Object} collection
4691   * @param {*} result
4692   * @param {Function} iterator
4693   * @param {Function} callback
4694   * @example
4695   *
4696   * // array
4697   * var order = [];
4698   * var collection = [1, 3, 2, 4];
4699   * var iterator = function(result, num, done) {
4700   *   setTimeout(function() {
4701   *     order.push(num);
4702   *     done(null, result + num);
4703   *   }, num * 10);
4704   * };
4705   * async.reduce(collection, 0, iterator, function(err, res) {
4706   *   console.log(res); // 10
4707   *   console.log(order); // [1, 3, 2, 4]
4708   * });
4709   *
4710   * @example
4711   *
4712   * // array with index
4713   * var order = [];
4714   * var collection = [1, 3, 2, 4];
4715   * var iterator = function(result, num, index, done) {
4716   *   setTimeout(function() {
4717   *     order.push([num, index]);
4718   *     done(null, result + num);
4719   *   }, num * 10);
4720   * };
4721   * async.reduce(collection, '', iterator, function(err, res) {
4722   *   console.log(res); // '1324'
4723   *   console.log(order); // [[1, 0], [3, 1], [2, 2], [4, 3]]
4724   * });
4725   *
4726   * @example
4727   *
4728   * // object
4729   * var order = [];
4730   * var object = { a: 1, b: 3, c: 2, d: 4 };
4731   * var iterator = function(result, num, done) {
4732   *   setTimeout(function() {
4733   *     order.push(num);
4734   *     done(null, result + num);
4735   *   }, num * 10);
4736   * };
4737   * async.reduce(collection, '', iterator, function(err, res) {
4738   *   console.log(res); // '1324'
4739   *   console.log(order); // [1, 3, 2, 4]
4740   * });
4741   *
4742   * @example
4743   *
4744   * // object with key
4745   * var order = [];
4746   * var object = { a: 1, b: 3, c: 2, d: 4 };
4747   * var iterator = function(result, num, key, done) {
4748   *   setTimeout(function() {
4749   *     order.push([num, key]);
4750   *     done(null, result + num);
4751   *   }, num * 10);
4752   * };
4753   * async.reduce(collection, 0, iterator, function(err, res) {
4754   *   console.log(res); // 10
4755   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b'], [4, 'd']]
4756   * });
4757   *
4758   */
4759  function reduce(collection, result, iterator, callback) {
4760    callback = onlyOnce(callback || noop);
4761    var size, key, keys, iter, item, iterate;
4762    var sync = false;
4763    var completed = 0;
4764
4765    if (isArray(collection)) {
4766      size = collection.length;
4767      iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
4768    } else if (!collection) {
4769    } else if (iteratorSymbol && collection[iteratorSymbol]) {
4770      size = Infinity;
4771      iter = collection[iteratorSymbol]();
4772      iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator;
4773    } else if (typeof collection === obj) {
4774      keys = nativeKeys(collection);
4775      size = keys.length;
4776      iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
4777    }
4778    if (!size) {
4779      return callback(null, result);
4780    }
4781    iterate(result);
4782
4783    function arrayIterator(result) {
4784      iterator(result, collection[completed], done);
4785    }
4786
4787    function arrayIteratorWithIndex(result) {
4788      iterator(result, collection[completed], completed, done);
4789    }
4790
4791    function symbolIterator(result) {
4792      item = iter.next();
4793      item.done ? callback(null, result) : iterator(result, item.value, done);
4794    }
4795
4796    function symbolIteratorWithKey(result) {
4797      item = iter.next();
4798      item.done ? callback(null, result) : iterator(result, item.value, completed, done);
4799    }
4800
4801    function objectIterator(result) {
4802      iterator(result, collection[keys[completed]], done);
4803    }
4804
4805    function objectIteratorWithKey(result) {
4806      key = keys[completed];
4807      iterator(result, collection[key], key, done);
4808    }
4809
4810    function done(err, result) {
4811      if (err) {
4812        callback(err, result);
4813      } else if (++completed === size) {
4814        iterator = throwError;
4815        callback(null, result);
4816      } else if (sync) {
4817        nextTick(function() {
4818          iterate(result);
4819        });
4820      } else {
4821        sync = true;
4822        iterate(result);
4823      }
4824      sync = false;
4825    }
4826  }
4827
4828  /**
4829   * @memberof async
4830   * @namespace reduceRight
4831   * @param {Array|Object} collection
4832   * @param {*} result
4833   * @param {Function} iterator
4834   * @param {Function} callback
4835   * @example
4836   *
4837   * // array
4838   * var order = [];
4839   * var collection = [1, 3, 2, 4];
4840   * var iterator = function(result, num, done) {
4841   *   setTimeout(function() {
4842   *     order.push(num);
4843   *     done(null, result + num);
4844   *   }, num * 10);
4845   * };
4846   * async.reduceRight(collection, 0, iterator, function(err, res) {
4847   *   console.log(res); // 10
4848   *   console.log(order); // [4, 2, 3, 1]
4849   * });
4850   *
4851   * @example
4852   *
4853   * // array with index
4854   * var order = [];
4855   * var collection = [1, 3, 2, 4];
4856   * var iterator = function(result, num, index, done) {
4857   *   setTimeout(function() {
4858   *     order.push([num, index]);
4859   *     done(null, result + num);
4860   *   }, num * 10);
4861   * };
4862   * async.reduceRight(collection, '', iterator, function(err, res) {
4863   *   console.log(res); // '4231'
4864   *   console.log(order); // [[4, 3], [2, 2], [3, 1], [1, 0]]
4865   * });
4866   *
4867   * @example
4868   *
4869   * // object
4870   * var order = [];
4871   * var object = { a: 1, b: 3, c: 2, d: 4 };
4872   * var iterator = function(result, num, done) {
4873   *   setTimeout(function() {
4874   *     order.push(num);
4875   *     done(null, result + num);
4876   *   }, num * 10);
4877   * };
4878   * async.reduceRight(collection, '', iterator, function(err, res) {
4879   *   console.log(res); // '4231'
4880   *   console.log(order); // [4, 2, 3, 1]
4881   * });
4882   *
4883   * @example
4884   *
4885   * // object with key
4886   * var order = [];
4887   * var object = { a: 1, b: 3, c: 2, d: 4 };
4888   * var iterator = function(result, num, key, done) {
4889   *   setTimeout(function() {
4890   *     order.push([num, key]);
4891   *     done(null, result + num);
4892   *   }, num * 10);
4893   * };
4894   * async.reduceRight(collection, 0, iterator, function(err, res) {
4895   *   console.log(res); // 10
4896   *   console.log(order); // [[4, 3], [2, 2], [3, 1], [1, 0]]
4897   * });
4898   *
4899   */
4900  function reduceRight(collection, result, iterator, callback) {
4901    callback = onlyOnce(callback || noop);
4902    var resIndex, index, key, keys, iter, item, col, iterate;
4903    var sync = false;
4904
4905    if (isArray(collection)) {
4906      resIndex = collection.length;
4907      iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
4908    } else if (!collection) {
4909    } else if (iteratorSymbol && collection[iteratorSymbol]) {
4910      col = [];
4911      iter = collection[iteratorSymbol]();
4912      index = -1;
4913      while ((item = iter.next()).done === false) {
4914        col[++index] = item.value;
4915      }
4916      collection = col;
4917      resIndex = col.length;
4918      iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
4919    } else if (typeof collection === obj) {
4920      keys = nativeKeys(collection);
4921      resIndex = keys.length;
4922      iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
4923    }
4924    if (!resIndex) {
4925      return callback(null, result);
4926    }
4927    iterate(result);
4928
4929    function arrayIterator(result) {
4930      iterator(result, collection[--resIndex], done);
4931    }
4932
4933    function arrayIteratorWithIndex(result) {
4934      iterator(result, collection[--resIndex], resIndex, done);
4935    }
4936
4937    function objectIterator(result) {
4938      iterator(result, collection[keys[--resIndex]], done);
4939    }
4940
4941    function objectIteratorWithKey(result) {
4942      key = keys[--resIndex];
4943      iterator(result, collection[key], key, done);
4944    }
4945
4946    function done(err, result) {
4947      if (err) {
4948        callback(err, result);
4949      } else if (resIndex === 0) {
4950        iterate = throwError;
4951        callback(null, result);
4952      } else if (sync) {
4953        nextTick(function() {
4954          iterate(result);
4955        });
4956      } else {
4957        sync = true;
4958        iterate(result);
4959      }
4960      sync = false;
4961    }
4962  }
4963
4964  /**
4965   * @private
4966   * @param {Function} arrayEach
4967   * @param {Function} baseEach
4968   * @param {Function} symbolEach
4969   */
4970  function createTransform(arrayEach, baseEach, symbolEach) {
4971    return function transform(collection, accumulator, iterator, callback) {
4972      if (arguments.length === 3) {
4973        callback = iterator;
4974        iterator = accumulator;
4975        accumulator = undefined;
4976      }
4977      callback = callback || noop;
4978      var size, keys, result;
4979      var completed = 0;
4980
4981      if (isArray(collection)) {
4982        size = collection.length;
4983        result = accumulator !== undefined ? accumulator : [];
4984        arrayEach(collection, result, iterator, done);
4985      } else if (!collection) {
4986      } else if (iteratorSymbol && collection[iteratorSymbol]) {
4987        result = accumulator !== undefined ? accumulator : {};
4988        size = symbolEach(collection, result, iterator, done);
4989        size && size === completed && callback(null, result);
4990      } else if (typeof collection === obj) {
4991        keys = nativeKeys(collection);
4992        size = keys.length;
4993        result = accumulator !== undefined ? accumulator : {};
4994        baseEach(collection, result, iterator, done, keys);
4995      }
4996      if (!size) {
4997        callback(null, accumulator !== undefined ? accumulator : result || {});
4998      }
4999
5000      function done(err, bool) {
5001        if (err) {
5002          callback = once(callback);
5003          callback(err, isArray(result) ? createArray(result) : objectClone(result));
5004        } else if (++completed === size) {
5005          callback(null, result);
5006        } else if (bool === false) {
5007          callback = once(callback);
5008          callback(null, isArray(result) ? createArray(result) : objectClone(result));
5009        }
5010      }
5011    };
5012  }
5013
5014  /**
5015   * @memberof async
5016   * @namespace transformSeries
5017   * @param {Array|Object} collection
5018   * @param {Array|Object|Function} [accumulator]
5019   * @param {Function} [iterator]
5020   * @param {Function} [callback]
5021   * @example
5022   *
5023   * // array
5024   * var order = [];
5025   * var collection = [1, 3, 2, 4];
5026   * var iterator = function(result, num, done) {
5027   *   setTimeout(function() {
5028   *     order.push(num);
5029   *     result.push(num)
5030   *     done();
5031   *   }, num * 10);
5032   * };
5033   * async.transformSeries(collection, iterator, function(err, res) {
5034   *   console.log(res); // [1, 3, 2, 4]
5035   *   console.log(order); // [1, 3, 2, 4]
5036   * });
5037   *
5038   * @example
5039   *
5040   * // array with index and accumulator
5041   * var order = [];
5042   * var collection = [1, 3, 2, 4];
5043   * var iterator = function(result, num, index, done) {
5044   *   setTimeout(function() {
5045   *     order.push([num, index]);
5046   *     result[index] = num;
5047   *     done();
5048   *   }, num * 10);
5049   * };
5050   * async.transformSeries(collection, {}, iterator, function(err, res) {
5051   *   console.log(res); // { '0': 1, '1': 3, '2': 2, '3': 4 }
5052   *   console.log(order); // [[1, 0], [3, 1], [2, 2], [4, 3]]
5053   * });
5054   *
5055   * @example
5056   *
5057   * // object with accumulator
5058   * var order = [];
5059   * var object = { a: 1, b: 3, c: 2, d: 4 };
5060   * var iterator = function(result, num, done) {
5061   *   setTimeout(function() {
5062   *     order.push(num);
5063   *     result.push(num);
5064   *     done();
5065   *   }, num * 10);
5066   * };
5067   * async.transformSeries(collection, [], iterator, function(err, res) {
5068   *   console.log(res); // [1, 3, 2, 4]
5069   *   console.log(order); // [1, 3, 2, 4]
5070   * });
5071   *
5072   * @example
5073   *
5074   * // object with key
5075   * var order = [];
5076   * var object = { a: 1, b: 3, c: 2, d: 4 };
5077   * var iterator = function(result, num, key, done) {
5078   *   setTimeout(function() {
5079   *     order.push([num, key]);
5080   *     result[key] = num;
5081   *     done();
5082   *   }, num * 10);
5083   * };
5084   * async.transformSeries(collection, iterator, function(err, res) {
5085   *   console.log(res); //  { a: 1, b: 3, c: 2, d: 4 }
5086   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'b'], [4, 'd']]
5087   * });
5088   *
5089   */
5090  function transformSeries(collection, accumulator, iterator, callback) {
5091    if (arguments.length === 3) {
5092      callback = iterator;
5093      iterator = accumulator;
5094      accumulator = undefined;
5095    }
5096    callback = onlyOnce(callback || noop);
5097    var size, key, keys, iter, item, iterate, result;
5098    var sync = false;
5099    var completed = 0;
5100
5101    if (isArray(collection)) {
5102      size = collection.length;
5103      result = accumulator !== undefined ? accumulator : [];
5104      iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
5105    } else if (!collection) {
5106    } else if (iteratorSymbol && collection[iteratorSymbol]) {
5107      size = Infinity;
5108      iter = collection[iteratorSymbol]();
5109      result = accumulator !== undefined ? accumulator : {};
5110      iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator;
5111    } else if (typeof collection === obj) {
5112      keys = nativeKeys(collection);
5113      size = keys.length;
5114      result = accumulator !== undefined ? accumulator : {};
5115      iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
5116    }
5117    if (!size) {
5118      return callback(null, accumulator !== undefined ? accumulator : result || {});
5119    }
5120    iterate();
5121
5122    function arrayIterator() {
5123      iterator(result, collection[completed], done);
5124    }
5125
5126    function arrayIteratorWithIndex() {
5127      iterator(result, collection[completed], completed, done);
5128    }
5129
5130    function symbolIterator() {
5131      item = iter.next();
5132      item.done ? callback(null, result) : iterator(result, item.value, done);
5133    }
5134
5135    function symbolIteratorWithKey() {
5136      item = iter.next();
5137      item.done ? callback(null, result) : iterator(result, item.value, completed, done);
5138    }
5139
5140    function objectIterator() {
5141      iterator(result, collection[keys[completed]], done);
5142    }
5143
5144    function objectIteratorWithKey() {
5145      key = keys[completed];
5146      iterator(result, collection[key], key, done);
5147    }
5148
5149    function done(err, bool) {
5150      if (err) {
5151        callback(err, result);
5152      } else if (++completed === size || bool === false) {
5153        iterate = throwError;
5154        callback(null, result);
5155      } else if (sync) {
5156        nextTick(iterate);
5157      } else {
5158        sync = true;
5159        iterate();
5160      }
5161      sync = false;
5162    }
5163  }
5164
5165  /**
5166   * @memberof async
5167   * @namespace transformLimit
5168   * @param {Array|Object} collection
5169   * @param {number} limit - limit >= 1
5170   * @param {Array|Object|Function} [accumulator]
5171   * @param {Function} [iterator]
5172   * @param {Function} [callback]
5173   * @example
5174   *
5175   * // array
5176   * var order = [];
5177   * var array = [1, 5, 3, 4, 2];
5178   * var iterator = function(result, num, done) {
5179   *   setTimeout(function() {
5180   *     order.push(num);
5181   *     result.push(num);
5182   *     done();
5183   *   }, num * 10);
5184   * };
5185   * async.transformLimit(array, 2, iterator, function(err, res) {
5186   *   console.log(res); // [1, 3, 5, 2, 4]
5187   *   console.log(order); // [1, 3, 5, 2, 4]
5188   * });
5189   *
5190   * @example
5191   *
5192   * // array with index and accumulator
5193   * var order = [];
5194   * var array = [1, 5, 3, 4, 2];
5195   * var iterator = function(result, num, index, done) {
5196   *   setTimeout(function() {
5197   *     order.push([num, index]);
5198   *     result[index] = key;
5199   *     done();
5200   *   }, num * 10);
5201   * };
5202   * async.transformLimit(array, 2, {}, iterator, function(err, res) {
5203   *   console.log(res); // { '0': 1, '1': 5, '2': 3, '3': 4, '4': 2 }
5204   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
5205   * });
5206   *
5207   * @example
5208   *
5209   * // object with accumulator
5210   * var order = [];
5211   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5212   * var iterator = function(result, num, done) {
5213   *   setTimeout(function() {
5214   *     order.push(num);
5215   *     result.push(num);
5216   *     done();
5217   *   }, num * 10);
5218   * };
5219   * async.transformLimit(object, 2, [], iterator, function(err, res) {
5220   *   console.log(res); // [1, 3, 5, 2, 4]
5221   *   console.log(order); // [1, 3, 5, 2, 4]
5222   * });
5223   *
5224   * @example
5225   *
5226   * // object with key
5227   * var order = [];
5228   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5229   * var iterator = function(result, num, key, done) {
5230   *   setTimeout(function() {
5231   *     order.push([num, key]);
5232   *     result[key] = num;
5233   *     done();
5234   *   }, num * 10);
5235   * };
5236   * async.transformLimit(object, 2, iterator, function(err, res) {
5237   *   console.log(res); // { a: 1, b: 5, c: 3, d: 4, e: 2 };
5238   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
5239   * });
5240   *
5241   */
5242  function transformLimit(collection, limit, accumulator, iterator, callback) {
5243    if (arguments.length === 4) {
5244      callback = iterator;
5245      iterator = accumulator;
5246      accumulator = undefined;
5247    }
5248    callback = callback || noop;
5249    var size, index, key, keys, iter, item, iterate, result;
5250    var sync = false;
5251    var started = 0;
5252    var completed = 0;
5253
5254    if (isArray(collection)) {
5255      size = collection.length;
5256      result = accumulator !== undefined ? accumulator : [];
5257      iterate = iterator.length === 4 ? arrayIteratorWithIndex : arrayIterator;
5258    } else if (!collection) {
5259    } else if (iteratorSymbol && collection[iteratorSymbol]) {
5260      size = Infinity;
5261      iter = collection[iteratorSymbol]();
5262      result = accumulator !== undefined ? accumulator : {};
5263      iterate = iterator.length === 4 ? symbolIteratorWithKey : symbolIterator;
5264    } else if (typeof collection === obj) {
5265      keys = nativeKeys(collection);
5266      size = keys.length;
5267      result = accumulator !== undefined ? accumulator : {};
5268      iterate = iterator.length === 4 ? objectIteratorWithKey : objectIterator;
5269    }
5270    if (!size || isNaN(limit) || limit < 1) {
5271      return callback(null, accumulator !== undefined ? accumulator : result || {});
5272    }
5273    timesSync(limit > size ? size : limit, iterate);
5274
5275    function arrayIterator() {
5276      index = started++;
5277      if (index < size) {
5278        iterator(result, collection[index], onlyOnce(done));
5279      }
5280    }
5281
5282    function arrayIteratorWithIndex() {
5283      index = started++;
5284      if (index < size) {
5285        iterator(result, collection[index], index, onlyOnce(done));
5286      }
5287    }
5288
5289    function symbolIterator() {
5290      item = iter.next();
5291      if (item.done === false) {
5292        started++;
5293        iterator(result, item.value, onlyOnce(done));
5294      } else if (completed === started && iterator !== noop) {
5295        iterator = noop;
5296        callback(null, result);
5297      }
5298    }
5299
5300    function symbolIteratorWithKey() {
5301      item = iter.next();
5302      if (item.done === false) {
5303        iterator(result, item.value, started++, onlyOnce(done));
5304      } else if (completed === started && iterator !== noop) {
5305        iterator = noop;
5306        callback(null, result);
5307      }
5308    }
5309
5310    function objectIterator() {
5311      index = started++;
5312      if (index < size) {
5313        iterator(result, collection[keys[index]], onlyOnce(done));
5314      }
5315    }
5316
5317    function objectIteratorWithKey() {
5318      index = started++;
5319      if (index < size) {
5320        key = keys[index];
5321        iterator(result, collection[key], key, onlyOnce(done));
5322      }
5323    }
5324
5325    function done(err, bool) {
5326      if (err || bool === false) {
5327        iterate = noop;
5328        callback(err || null, isArray(result) ? createArray(result) : objectClone(result));
5329        callback = noop;
5330      } else if (++completed === size) {
5331        iterator = noop;
5332        callback(null, result);
5333      } else if (sync) {
5334        nextTick(iterate);
5335      } else {
5336        sync = true;
5337        iterate();
5338      }
5339      sync = false;
5340    }
5341  }
5342
5343  /**
5344   * @private
5345   * @param {function} arrayEach
5346   * @param {function} baseEach
5347   * @param {function} symbolEach
5348   */
5349  function createSortBy(arrayEach, baseEach, symbolEach) {
5350    return function sortBy(collection, iterator, callback) {
5351      callback = callback || noop;
5352      var size, array, criteria;
5353      var completed = 0;
5354
5355      if (isArray(collection)) {
5356        size = collection.length;
5357        array = Array(size);
5358        criteria = Array(size);
5359        arrayEach(collection, iterator, createCallback);
5360      } else if (!collection) {
5361      } else if (iteratorSymbol && collection[iteratorSymbol]) {
5362        array = [];
5363        criteria = [];
5364        size = symbolEach(collection, iterator, createCallback);
5365        size && size === completed && callback(null, sortByCriteria(array, criteria));
5366      } else if (typeof collection === obj) {
5367        var keys = nativeKeys(collection);
5368        size = keys.length;
5369        array = Array(size);
5370        criteria = Array(size);
5371        baseEach(collection, iterator, createCallback, keys);
5372      }
5373      if (!size) {
5374        callback(null, []);
5375      }
5376
5377      function createCallback(index, value) {
5378        var called = false;
5379        array[index] = value;
5380        return function done(err, criterion) {
5381          if (called) {
5382            throwError();
5383          }
5384          called = true;
5385          criteria[index] = criterion;
5386          if (err) {
5387            callback = once(callback);
5388            callback(err);
5389          } else if (++completed === size) {
5390            callback(null, sortByCriteria(array, criteria));
5391          }
5392        };
5393      }
5394    };
5395  }
5396
5397  /**
5398   * @memberof async
5399   * @namespace sortBySeries
5400   * @param {Array|Object} collection
5401   * @param {Function} iterator
5402   * @param {Function} callback
5403   * @example
5404   *
5405   * // array
5406   * var order = [];
5407   * var array = [1, 3, 2];
5408   * var iterator = function(num, done) {
5409   *   setTimeout(function() {
5410   *     order.push(num);
5411   *     done(null, num);
5412   *   }, num * 10);
5413   * };
5414   * async.sortBySeries(array, iterator, function(err, res) {
5415   *   console.log(res); // [1, 2, 3];
5416   *   console.log(order); // [1, 3, 2]
5417   * });
5418   *
5419   * @example
5420   *
5421   * // array with index
5422   * var order = [];
5423   * var array = [1, 3, 2];
5424   * var iterator = function(num, index, done) {
5425   *   setTimeout(function() {
5426   *     order.push([num, index]);
5427   *     done(null, num);
5428   *   }, num * 10);
5429   * };
5430   * async.sortBySeries(array, iterator, function(err, res) {
5431   *   console.log(res); // [1, 2, 3]
5432   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
5433   * });
5434   *
5435   * @example
5436   *
5437   * // object
5438   * var order = [];
5439   * var object = { a: 1, b: 3, c: 2 };
5440   * var iterator = function(num, done) {
5441   *   setTimeout(function() {
5442   *     order.push(num);
5443   *     done(null, num);
5444   *   }, num * 10);
5445   * };
5446   * async.sortBySeries(object, iterator, function(err, res) {
5447   *   console.log(res); // [1, 2, 3]
5448   *   console.log(order); // [1, 3, 2]
5449   * });
5450   *
5451   * @example
5452   *
5453   * // object with key
5454   * var order = [];
5455   * var object = { a: 1, b: 3, c: 2 };
5456   * var iterator = function(num, key, done) {
5457   *   setTimeout(function() {
5458   *     order.push([num, key]);
5459   *     done(null, num);
5460   *   }, num * 10);
5461   * };
5462   * async.sortBySeries(object, iterator, function(err, res) {
5463   *   console.log(res); // [1, 2, 3]
5464   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
5465   * });
5466   *
5467   */
5468  function sortBySeries(collection, iterator, callback) {
5469    callback = onlyOnce(callback || noop);
5470    var size, key, value, keys, iter, item, array, criteria, iterate;
5471    var sync = false;
5472    var completed = 0;
5473
5474    if (isArray(collection)) {
5475      size = collection.length;
5476      array = collection;
5477      criteria = Array(size);
5478      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
5479    } else if (!collection) {
5480    } else if (iteratorSymbol && collection[iteratorSymbol]) {
5481      size = Infinity;
5482      array = [];
5483      criteria = [];
5484      iter = collection[iteratorSymbol]();
5485      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
5486    } else if (typeof collection === obj) {
5487      keys = nativeKeys(collection);
5488      size = keys.length;
5489      array = Array(size);
5490      criteria = Array(size);
5491      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
5492    }
5493    if (!size) {
5494      return callback(null, []);
5495    }
5496    iterate();
5497
5498    function arrayIterator() {
5499      value = collection[completed];
5500      iterator(value, done);
5501    }
5502
5503    function arrayIteratorWithIndex() {
5504      value = collection[completed];
5505      iterator(value, completed, done);
5506    }
5507
5508    function symbolIterator() {
5509      item = iter.next();
5510      if (item.done) {
5511        return callback(null, sortByCriteria(array, criteria));
5512      }
5513      value = item.value;
5514      array[completed] = value;
5515      iterator(value, done);
5516    }
5517
5518    function symbolIteratorWithKey() {
5519      item = iter.next();
5520      if (item.done) {
5521        return callback(null, sortByCriteria(array, criteria));
5522      }
5523      value = item.value;
5524      array[completed] = value;
5525      iterator(value, completed, done);
5526    }
5527
5528    function objectIterator() {
5529      value = collection[keys[completed]];
5530      array[completed] = value;
5531      iterator(value, done);
5532    }
5533
5534    function objectIteratorWithKey() {
5535      key = keys[completed];
5536      value = collection[key];
5537      array[completed] = value;
5538      iterator(value, key, done);
5539    }
5540
5541    function done(err, criterion) {
5542      criteria[completed] = criterion;
5543      if (err) {
5544        callback(err);
5545      } else if (++completed === size) {
5546        iterate = throwError;
5547        callback(null, sortByCriteria(array, criteria));
5548      } else if (sync) {
5549        nextTick(iterate);
5550      } else {
5551        sync = true;
5552        iterate();
5553      }
5554      sync = false;
5555    }
5556  }
5557
5558  /**
5559   * @memberof async
5560   * @namespace sortByLimit
5561   * @param {Array|Object} collection
5562   * @param {number} limit - limit >= 1
5563   * @param {Function} iterator
5564   * @param {Function} callback
5565   * @example
5566   *
5567   * // array
5568   * var order = [];
5569   * var array = [1, 5, 3, 4, 2];
5570   * var iterator = function(num, done) {
5571   *   setTimeout(function() {
5572   *     order.push(num);
5573   *     done(null, num);
5574   *   }, num * 10);
5575   * };
5576   * async.sortByLimit(array, 2, iterator, function(err, res) {
5577   *   console.log(res); // [1, 2, 3, 4, 5]
5578   *   console.log(order); // [1, 3, 5, 2, 4]
5579   * });
5580   *
5581   * @example
5582   *
5583   * // array with index
5584   * var order = [];
5585   * var array = [1, 5, 3, 4, 2];
5586   * var iterator = function(num, index, done) {
5587   *   setTimeout(function() {
5588   *     order.push([num, index]);
5589   *     done(null, num);
5590   *   }, num * 10);
5591   * };
5592   * async.sortByLimit(array, 2, iterator, function(err, res) {
5593   *   console.log(res); // [1, 2, 3, 4, 5]
5594   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
5595   * });
5596   *
5597   * @example
5598   *
5599   * // object
5600   * var order = [];
5601   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5602   * var iterator = function(num, done) {
5603   *   setTimeout(function() {
5604   *     order.push(num);
5605   *     done(null, num);
5606   *   }, num * 10);
5607   * };
5608   * async.sortByLimit(object, 2, iterator, function(err, res) {
5609   *   console.log(res); // [1, 2, 3, 4, 5]
5610   *   console.log(order); // [1, 3, 5, 2, 4]
5611   * });
5612   *
5613   * @example
5614   *
5615   * // object with key
5616   * var order = [];
5617   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5618   * var iterator = function(num, key, done) {
5619   *   setTimeout(function() {
5620   *     order.push([num, key]);
5621   *     done(null, num);
5622   *   }, num * 10);
5623   * };
5624   * async.sortByLimit(object, 2, iterator, function(err, res) {
5625   *   console.log(res); // [1, 2, 3, 4, 5]
5626   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
5627   * });
5628   *
5629   */
5630  function sortByLimit(collection, limit, iterator, callback) {
5631    callback = callback || noop;
5632    var size, index, key, value, array, keys, iter, item, criteria, iterate;
5633    var sync = false;
5634    var started = 0;
5635    var completed = 0;
5636
5637    if (isArray(collection)) {
5638      size = collection.length;
5639      array = collection;
5640      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
5641    } else if (!collection) {
5642    } else if (iteratorSymbol && collection[iteratorSymbol]) {
5643      size = Infinity;
5644      iter = collection[iteratorSymbol]();
5645      array = [];
5646      criteria = [];
5647      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
5648    } else if (typeof collection === obj) {
5649      keys = nativeKeys(collection);
5650      size = keys.length;
5651      array = Array(size);
5652      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
5653    }
5654    if (!size || isNaN(limit) || limit < 1) {
5655      return callback(null, []);
5656    }
5657    criteria = criteria || Array(size);
5658    timesSync(limit > size ? size : limit, iterate);
5659
5660    function arrayIterator() {
5661      if (started < size) {
5662        value = collection[started];
5663        iterator(value, createCallback(value, started++));
5664      }
5665    }
5666
5667    function arrayIteratorWithIndex() {
5668      index = started++;
5669      if (index < size) {
5670        value = collection[index];
5671        iterator(value, index, createCallback(value, index));
5672      }
5673    }
5674
5675    function symbolIterator() {
5676      item = iter.next();
5677      if (item.done === false) {
5678        value = item.value;
5679        array[started] = value;
5680        iterator(value, createCallback(value, started++));
5681      } else if (completed === started && iterator !== noop) {
5682        iterator = noop;
5683        callback(null, sortByCriteria(array, criteria));
5684      }
5685    }
5686
5687    function symbolIteratorWithKey() {
5688      item = iter.next();
5689      if (item.done === false) {
5690        value = item.value;
5691        array[started] = value;
5692        iterator(value, started, createCallback(value, started++));
5693      } else if (completed === started && iterator !== noop) {
5694        iterator = noop;
5695        callback(null, sortByCriteria(array, criteria));
5696      }
5697    }
5698
5699    function objectIterator() {
5700      if (started < size) {
5701        value = collection[keys[started]];
5702        array[started] = value;
5703        iterator(value, createCallback(value, started++));
5704      }
5705    }
5706
5707    function objectIteratorWithKey() {
5708      if (started < size) {
5709        key = keys[started];
5710        value = collection[key];
5711        array[started] = value;
5712        iterator(value, key, createCallback(value, started++));
5713      }
5714    }
5715
5716    function createCallback(value, index) {
5717      var called = false;
5718      return function(err, criterion) {
5719        if (called) {
5720          throwError();
5721        }
5722        called = true;
5723        criteria[index] = criterion;
5724        if (err) {
5725          iterate = noop;
5726          callback(err);
5727          callback = noop;
5728        } else if (++completed === size) {
5729          callback(null, sortByCriteria(array, criteria));
5730        } else if (sync) {
5731          nextTick(iterate);
5732        } else {
5733          sync = true;
5734          iterate();
5735        }
5736        sync = false;
5737      };
5738    }
5739  }
5740
5741  /**
5742   * @memberof async
5743   * @namespace some
5744   * @param {Array|Object} collection
5745   * @param {Function} iterator
5746   * @param {Function} callback
5747   * @example
5748   *
5749   * // array
5750   * var order = [];
5751   * var array = [1, 3, 2];
5752   * var iterator = function(num, done) {
5753   *   setTimeout(function() {
5754   *     order.push(num);
5755   *     done(null, num % 2);
5756   *   }, num * 10);
5757   * };
5758   * async.some(array, iterator, function(err, res) {
5759   *   console.log(res); // true
5760   *   console.log(order); // [1]
5761   * });
5762   *
5763   * @example
5764   *
5765   * // array with index
5766   * var order = [];
5767   * var array = [1, 3, 2];
5768   * var iterator = function(num, index, done) {
5769   *   setTimeout(function() {
5770   *     order.push([num, index]);
5771   *     done(null, num % 2);
5772   *   }, num * 10);
5773   * };
5774   * async.some(array, iterator, function(err, res) {
5775   *   console.log(res); // true
5776   *   console.log(order); // [[1, 0]]
5777   * });
5778   *
5779   * @example
5780   *
5781   * // object
5782   * var order = [];
5783   * var object = { a: 1, b: 3, c: 2 };
5784   * var iterator = function(num, done) {
5785   *   setTimeout(function() {
5786   *     order.push(num);
5787   *     done(null, num % 2);
5788   *   }, num * 10);
5789   * };
5790   * async.some(object, iterator, function(err, res) {
5791   *   console.log(res); // true
5792   *   console.log(order); // [1]
5793   * });
5794   *
5795   * @example
5796   *
5797   * // object with key
5798   * var order = [];
5799   * var object = { a: 1, b: 3, c: 2 };
5800   * var iterator = function(num, key, done) {
5801   *   setTimeout(function() {
5802   *     order.push([num, key]);
5803   *     done(null, num % 2);
5804   *   }, num * 10);
5805   * };
5806   * async.some(object, iterator, function(err, res) {
5807   *   console.log(res); // true
5808   *   console.log(order); // [[1, 'a']]
5809   * });
5810   *
5811   */
5812  function some(collection, iterator, callback) {
5813    callback = callback || noop;
5814    detect(collection, iterator, done);
5815
5816    function done(err, res) {
5817      if (err) {
5818        return callback(err);
5819      }
5820      callback(null, !!res);
5821    }
5822  }
5823
5824  /**
5825   * @memberof async
5826   * @namespace someSeries
5827   * @param {Array|Object} collection
5828   * @param {Function} iterator
5829   * @param {Function} callback
5830   * @example
5831   *
5832   * // array
5833   * var order = [];
5834   * var array = [1, 3, 2];
5835   * var iterator = function(num, done) {
5836   *   setTimeout(function() {
5837   *     order.push(num);
5838   *     done(null, num % 2);
5839   *   }, num * 10);
5840   * };
5841   * async.someSeries(array, iterator, function(err, res) {
5842   *   console.log(res); // true
5843   *   console.log(order); // [1]
5844   * });
5845   *
5846   * @example
5847   *
5848   * // array with index
5849   * var order = [];
5850   * var array = [1, 3, 2];
5851   * var iterator = function(num, index, done) {
5852   *   setTimeout(function() {
5853   *     order.push([num, index]);
5854   *     done(null, num % 2);
5855   *   }, num * 10);
5856   * };
5857   * async.someSeries(array, iterator, function(err, res) {
5858   *   console.log(res); // true
5859   *   console.log(order); // [[1, 0]]
5860   * });
5861   *
5862   * @example
5863   *
5864   * // object
5865   * var order = [];
5866   * var object = { a: 1, b: 3, c: 2 };
5867   * var iterator = function(num, done) {
5868   *   setTimeout(function() {
5869   *     order.push(num);
5870   *     done(null, num % 2);
5871   *   }, num * 10);
5872   * };
5873   * async.someSeries(object, iterator, function(err, res) {
5874   *   console.log(res); // true
5875   *   console.log(order); // [1]
5876   * });
5877   *
5878   * @example
5879   *
5880   * // object with key
5881   * var order = [];
5882   * var object = { a: 1, b: 3, c: 2 };
5883   * var iterator = function(num, key, done) {
5884   *   setTimeout(function() {
5885   *     order.push([num, key]);
5886   *     done(null, num % 2);
5887   *   }, num * 10);
5888   * };
5889   * async.someSeries(object, iterator, function(err, res) {
5890   *   console.log(res); // true
5891   *   console.log(order); // [[1, 'a']]
5892   * });
5893   *
5894   */
5895  function someSeries(collection, iterator, callback) {
5896    callback = callback || noop;
5897    detectSeries(collection, iterator, done);
5898
5899    function done(err, res) {
5900      if (err) {
5901        return callback(err);
5902      }
5903      callback(null, !!res);
5904    }
5905  }
5906
5907  /**
5908   * @memberof async
5909   * @namespace someLimit
5910   * @param {Array|Object} collection
5911   * @param {number} limit - limit >= 1
5912   * @param {Function} iterator
5913   * @param {Function} callback
5914   * @example
5915   *
5916   * // array
5917   * var order = [];
5918   * var array = [1, 5, 3, 4, 2];
5919   * var iterator = function(num, done) {
5920   *   setTimeout(function() {
5921   *     order.push(num);
5922   *     done(null, num % 2);
5923   *   }, num * 10);
5924   * };
5925   * async.someLimit(array, 2, iterator, function(err, res) {
5926   *   console.log(res); // true
5927   *   console.log(order); // [1]
5928   * });
5929   *
5930   * @example
5931   *
5932   * // array with index
5933   * var order = [];
5934   * var array = [1, 5, 3, 4, 2];
5935   * var iterator = function(num, index, done) {
5936   *   setTimeout(function() {
5937   *     order.push([num, index]);
5938   *     done(null, num % 2);
5939   *   }, num * 10);
5940   * };
5941   * async.someLimit(array, 2, iterator, function(err, res) {
5942   *   console.log(res); // true
5943   *   console.log(order); // [[1, 0]]
5944   * });
5945   *
5946   * @example
5947   *
5948   * // object
5949   * var order = [];
5950   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5951   * var iterator = function(num, done) {
5952   *   setTimeout(function() {
5953   *     order.push(num);
5954   *     done(null, num % 2);
5955   *   }, num * 10);
5956   * };
5957   * async.someLimit(object, 2, iterator, function(err, res) {
5958   *   console.log(res); // true
5959   *   console.log(order); // [1]
5960   * });
5961   *
5962   * @example
5963   *
5964   * // object with key
5965   * var order = [];
5966   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
5967   * var iterator = function(num, key, done) {
5968   *   setTimeout(function() {
5969   *     order.push([num, key]);
5970   *     done(null, num % 2);
5971   *   }, num * 10);
5972   * };
5973   * async.someLimit(object, 2, iterator, function(err, res) {
5974   *   console.log(res); // true
5975   *   console.log(order); // [[1, 'a']]
5976   * });
5977   *
5978   */
5979  function someLimit(collection, limit, iterator, callback) {
5980    callback = callback || noop;
5981    detectLimit(collection, limit, iterator, done);
5982
5983    function done(err, res) {
5984      if (err) {
5985        return callback(err);
5986      }
5987      callback(null, !!res);
5988    }
5989  }
5990
5991  /**
5992   * @private
5993   * @param {Function} arrayEach
5994   * @param {Function} baseEach
5995   * @param {Function} symbolEach
5996   */
5997  function createEvery(arrayEach, baseEach, symbolEach) {
5998    var deny = createDetect(arrayEach, baseEach, symbolEach, false);
5999
6000    return function every(collection, iterator, callback) {
6001      callback = callback || noop;
6002      deny(collection, iterator, done);
6003
6004      function done(err, res) {
6005        if (err) {
6006          return callback(err);
6007        }
6008        callback(null, !res);
6009      }
6010    };
6011  }
6012
6013  /**
6014   * @private
6015   */
6016  function createEverySeries() {
6017    var denySeries = createDetectSeries(false);
6018
6019    return function everySeries(collection, iterator, callback) {
6020      callback = callback || noop;
6021      denySeries(collection, iterator, done);
6022
6023      function done(err, res) {
6024        if (err) {
6025          return callback(err);
6026        }
6027        callback(null, !res);
6028      }
6029    };
6030  }
6031
6032  /**
6033   * @private
6034   */
6035  function createEveryLimit() {
6036    var denyLimit = createDetectLimit(false);
6037
6038    return function everyLimit(collection, limit, iterator, callback) {
6039      callback = callback || noop;
6040      denyLimit(collection, limit, iterator, done);
6041
6042      function done(err, res) {
6043        if (err) {
6044          return callback(err);
6045        }
6046        callback(null, !res);
6047      }
6048    };
6049  }
6050
6051  /**
6052   * @private
6053   * @param {Function} arrayEach
6054   * @param {Function} baseEach
6055   * @param {Function} symbolEach
6056   */
6057  function createConcat(arrayEach, baseEach, symbolEach) {
6058    return function concat(collection, iterator, callback) {
6059      callback = callback || noop;
6060      var size, result;
6061      var completed = 0;
6062
6063      if (isArray(collection)) {
6064        size = collection.length;
6065        result = Array(size);
6066        arrayEach(collection, iterator, createCallback);
6067      } else if (!collection) {
6068      } else if (iteratorSymbol && collection[iteratorSymbol]) {
6069        result = [];
6070        size = symbolEach(collection, iterator, createCallback);
6071        size && size === completed && callback(null, result);
6072      } else if (typeof collection === obj) {
6073        var keys = nativeKeys(collection);
6074        size = keys.length;
6075        result = Array(size);
6076        baseEach(collection, iterator, createCallback, keys);
6077      }
6078      if (!size) {
6079        callback(null, []);
6080      }
6081
6082      function createCallback(index) {
6083        return function done(err, res) {
6084          if (index === null) {
6085            throwError();
6086          }
6087          if (err) {
6088            index = null;
6089            callback = once(callback);
6090            arrayEachSync(result, function(array, index) {
6091              if (array === undefined) {
6092                result[index] = noop;
6093              }
6094            });
6095            callback(err, makeConcatResult(result));
6096            return;
6097          }
6098          switch (arguments.length) {
6099            case 0:
6100            case 1:
6101              result[index] = noop;
6102              break;
6103            case 2:
6104              result[index] = res;
6105              break;
6106            default:
6107              result[index] = slice(arguments, 1);
6108              break;
6109          }
6110          index = null;
6111          if (++completed === size) {
6112            callback(null, makeConcatResult(result));
6113          }
6114        };
6115      }
6116    };
6117  }
6118
6119  /**
6120   * @memberof async
6121   * @namespace concatSeries
6122   * @param {Array|Object} collection
6123   * @param {Function} iterator
6124   * @param {Function} callback
6125   * @example
6126   *
6127   * // array
6128   * var order = [];
6129   * var array = [1, 3, 2];
6130   * var iterator = function(num, done) {
6131   *   setTimeout(function() {
6132   *     order.push(num);
6133   *     done(null, [num]);
6134   *   }, num * 10);
6135   * };
6136   * async.concatSeries(array, iterator, function(err, res) {
6137   *   console.log(res); // [1, 3, 2];
6138   *   console.log(order); // [1, 3, 2]
6139   * });
6140   *
6141   * @example
6142   *
6143   * // array with index
6144   * var order = [];
6145   * var array = [1, 3, 2];
6146   * var iterator = function(num, index, done) {
6147   *   setTimeout(function() {
6148   *     order.push([num, index]);
6149   *     done(null, [num]);
6150   *   }, num * 10);
6151   * };
6152   * async.concatSeries(array, iterator, function(err, res) {
6153   *   console.log(res); // [1, 3, 2]
6154   *   console.log(order); // [[1, 0], [3, 1], [2, 2]]
6155   * });
6156   *
6157   * @example
6158   *
6159   * // object
6160   * var order = [];
6161   * var object = { a: 1, b: 3, c: 2 };
6162   * var iterator = function(num, done) {
6163   *   setTimeout(function() {
6164   *     order.push(num);
6165   *     done(null, [num]);
6166   *   }, num * 10);
6167   * };
6168   * async.concatSeries(object, iterator, function(err, res) {
6169   *   console.log(res); // [1, 3, 2]
6170   *   console.log(order); // [1, 3, 2]
6171   * });
6172   *
6173   * @example
6174   *
6175   * // object with key
6176   * var order = [];
6177   * var object = { a: 1, b: 3, c: 2 };
6178   * var iterator = function(num, key, done) {
6179   *   setTimeout(function() {
6180   *     order.push([num, key]);
6181   *     done(null, [num]);
6182   *   }, num * 10);
6183   * };
6184   * async.concatSeries(object, iterator, function(err, res) {
6185   *   console.log(res); // [1, 3, 2]
6186   *   console.log(order); // [[1, 'a'], [3, 'b'], [2, 'c']]
6187   * });
6188   *
6189   */
6190  function concatSeries(collection, iterator, callback) {
6191    callback = onlyOnce(callback || noop);
6192    var size, key, keys, iter, item, iterate;
6193    var sync = false;
6194    var result = [];
6195    var completed = 0;
6196
6197    if (isArray(collection)) {
6198      size = collection.length;
6199      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
6200    } else if (!collection) {
6201    } else if (iteratorSymbol && collection[iteratorSymbol]) {
6202      size = Infinity;
6203      iter = collection[iteratorSymbol]();
6204      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
6205    } else if (typeof collection === obj) {
6206      keys = nativeKeys(collection);
6207      size = keys.length;
6208      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
6209    }
6210    if (!size) {
6211      return callback(null, result);
6212    }
6213    iterate();
6214
6215    function arrayIterator() {
6216      iterator(collection[completed], done);
6217    }
6218
6219    function arrayIteratorWithIndex() {
6220      iterator(collection[completed], completed, done);
6221    }
6222
6223    function symbolIterator() {
6224      item = iter.next();
6225      item.done ? callback(null, result) : iterator(item.value, done);
6226    }
6227
6228    function symbolIteratorWithKey() {
6229      item = iter.next();
6230      item.done ? callback(null, result) : iterator(item.value, completed, done);
6231    }
6232
6233    function objectIterator() {
6234      iterator(collection[keys[completed]], done);
6235    }
6236
6237    function objectIteratorWithKey() {
6238      key = keys[completed];
6239      iterator(collection[key], key, done);
6240    }
6241
6242    function done(err, array) {
6243      if (isArray(array)) {
6244        nativePush.apply(result, array);
6245      } else if (arguments.length >= 2) {
6246        nativePush.apply(result, slice(arguments, 1));
6247      }
6248      if (err) {
6249        callback(err, result);
6250      } else if (++completed === size) {
6251        iterate = throwError;
6252        callback(null, result);
6253      } else if (sync) {
6254        nextTick(iterate);
6255      } else {
6256        sync = true;
6257        iterate();
6258      }
6259      sync = false;
6260    }
6261  }
6262
6263  /**
6264   * @memberof async
6265   * @namespace concatLimit
6266   * @param {Array|Object} collection
6267   * @param {number} limit - limit >= 1
6268   * @param {Function} iterator
6269   * @param {Function} callback
6270   * @example
6271   *
6272   * // array
6273   * var order = [];
6274   * var array = [1, 5, 3, 4, 2];
6275   * var iterator = function(num, done) {
6276   *   setTimeout(function() {
6277   *     order.push(num);
6278   *     done(null, [num]);
6279   *   }, num * 10);
6280   * };
6281   * async.concatLimit(array, 2, iterator, function(err, res) {
6282   *   console.log(res); // [1, 3, 5, 2, 4]
6283   *   console.log(order); // [1, 3, 5, 2, 4]
6284   * });
6285   *
6286   * @example
6287   *
6288   * // array with index
6289   * var order = [];
6290   * var array = [1, 5, 3, 4, 2];
6291   * var iterator = function(num, index, done) {
6292   *   setTimeout(function() {
6293   *     order.push([num, index]);
6294   *     done(null, [num]);
6295   *   }, num * 10);
6296   * };
6297   * async.cocnatLimit(array, 2, iterator, function(err, res) {
6298   *   console.log(res); // [1, 3, 5, 2, 4]
6299   *   console.log(order); // [[1, 0], [3, 2], [5, 1], [2, 4], [4, 3]]
6300   * });
6301   *
6302   * @example
6303   *
6304   * // object
6305   * var order = [];
6306   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
6307   * var iterator = function(num, done) {
6308   *   setTimeout(function() {
6309   *     order.push(num);
6310   *     done(null, [num]);
6311   *   }, num * 10);
6312   * };
6313   * async.concatLimit(object, 2, iterator, function(err, res) {
6314   *   console.log(res); // [1, 3, 5, 2, 4]
6315   *   console.log(order); // [1, 3, 5, 2, 4]
6316   * });
6317   *
6318   * @example
6319   *
6320   * // object with key
6321   * var order = [];
6322   * var object = { a: 1, b: 5, c: 3, d: 4, e: 2 };
6323   * var iterator = function(num, key, done) {
6324   *   setTimeout(function() {
6325   *     order.push([num, key]);
6326   *     done(null, num);
6327   *   }, num * 10);
6328   * };
6329   * async.cocnatLimit(object, 2, iterator, function(err, res) {
6330   *   console.log(res); // [1, 3, 5, 2, 4]
6331   *   console.log(order); // [[1, 'a'], [3, 'c'], [5, 'b'], [2, 'e'], [4, 'd']]
6332   * });
6333   *
6334   */
6335  function concatLimit(collection, limit, iterator, callback) {
6336    callback = callback || noop;
6337    var size, key, iter, item, iterate, result;
6338    var sync = false;
6339    var started = 0;
6340    var completed = 0;
6341
6342    if (isArray(collection)) {
6343      size = collection.length;
6344      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
6345    } else if (!collection) {
6346    } else if (iteratorSymbol && collection[iteratorSymbol]) {
6347      size = Infinity;
6348      result = [];
6349      iter = collection[iteratorSymbol]();
6350      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
6351    } else if (typeof collection === obj) {
6352      var keys = nativeKeys(collection);
6353      size = keys.length;
6354      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
6355    }
6356    if (!size || isNaN(limit) || limit < 1) {
6357      return callback(null, []);
6358    }
6359    result = result || Array(size);
6360    timesSync(limit > size ? size : limit, iterate);
6361
6362    function arrayIterator() {
6363      if (started < size) {
6364        iterator(collection[started], createCallback(started++));
6365      }
6366    }
6367
6368    function arrayIteratorWithIndex() {
6369      if (started < size) {
6370        iterator(collection[started], started, createCallback(started++));
6371      }
6372    }
6373
6374    function symbolIterator() {
6375      item = iter.next();
6376      if (item.done === false) {
6377        iterator(item.value, createCallback(started++));
6378      } else if (completed === started && iterator !== noop) {
6379        iterator = noop;
6380        callback(null, makeConcatResult(result));
6381      }
6382    }
6383
6384    function symbolIteratorWithKey() {
6385      item = iter.next();
6386      if (item.done === false) {
6387        iterator(item.value, started, createCallback(started++));
6388      } else if (completed === started && iterator !== noop) {
6389        iterator = noop;
6390        callback(null, makeConcatResult(result));
6391      }
6392    }
6393
6394    function objectIterator() {
6395      if (started < size) {
6396        iterator(collection[keys[started]], createCallback(started++));
6397      }
6398    }
6399
6400    function objectIteratorWithKey() {
6401      if (started < size) {
6402        key = keys[started];
6403        iterator(collection[key], key, createCallback(started++));
6404      }
6405    }
6406
6407    function createCallback(index) {
6408      return function(err, res) {
6409        if (index === null) {
6410          throwError();
6411        }
6412        if (err) {
6413          index = null;
6414          iterate = noop;
6415          callback = once(callback);
6416          arrayEachSync(result, function(array, index) {
6417            if (array === undefined) {
6418              result[index] = noop;
6419            }
6420          });
6421          callback(err, makeConcatResult(result));
6422          return;
6423        }
6424        switch (arguments.length) {
6425          case 0:
6426          case 1:
6427            result[index] = noop;
6428            break;
6429          case 2:
6430            result[index] = res;
6431            break;
6432          default:
6433            result[index] = slice(arguments, 1);
6434            break;
6435        }
6436        index = null;
6437        if (++completed === size) {
6438          iterate = throwError;
6439          callback(null, makeConcatResult(result));
6440          callback = throwError;
6441        } else if (sync) {
6442          nextTick(iterate);
6443        } else {
6444          sync = true;
6445          iterate();
6446        }
6447        sync = false;
6448      };
6449    }
6450  }
6451
6452  /**
6453   * @private
6454   * @param {Function} arrayEach
6455   * @param {Function} baseEach
6456   * @param {Function} symbolEach
6457   */
6458  function createGroupBy(arrayEach, baseEach, symbolEach) {
6459    return function groupBy(collection, iterator, callback) {
6460      callback = callback || noop;
6461      var size;
6462      var completed = 0;
6463      var result = {};
6464
6465      if (isArray(collection)) {
6466        size = collection.length;
6467        arrayEach(collection, iterator, createCallback);
6468      } else if (!collection) {
6469      } else if (iteratorSymbol && collection[iteratorSymbol]) {
6470        size = symbolEach(collection, iterator, createCallback);
6471        size && size === completed && callback(null, result);
6472      } else if (typeof collection === obj) {
6473        var keys = nativeKeys(collection);
6474        size = keys.length;
6475        baseEach(collection, iterator, createCallback, keys);
6476      }
6477      if (!size) {
6478        callback(null, {});
6479      }
6480
6481      function createCallback(value) {
6482        var called = false;
6483        return function done(err, key) {
6484          if (called) {
6485            throwError();
6486          }
6487          called = true;
6488          if (err) {
6489            callback = once(callback);
6490            callback(err, objectClone(result));
6491            return;
6492          }
6493          var array = result[key];
6494          if (!array) {
6495            result[key] = [value];
6496          } else {
6497            array.push(value);
6498          }
6499          if (++completed === size) {
6500            callback(null, result);
6501          }
6502        };
6503      }
6504    };
6505  }
6506
6507  /**
6508   * @memberof async
6509   * @namespace groupBySeries
6510   * @param {Array|Object} collection
6511   * @param {Function} iterator
6512   * @param {Function} callback
6513   * @example
6514   *
6515   * // array
6516   * var order = [];
6517   * var array = [4.2, 6.4, 6.1];
6518   * var iterator = function(num, done) {
6519   *   setTimeout(function() {
6520   *     order.push(num);
6521   *     done(null, Math.floor(num));
6522   *   }, num * 10);
6523   * };
6524   * async.groupBySeries(array, iterator, function(err, res) {
6525   *   console.log(res); // { '4': [4.2], '6': [6.4, 6.1] }
6526   *   console.log(order); // [4.2, 6.4, 6.1]
6527   * });
6528   *
6529   * @example
6530   *
6531   * // array with index
6532   * var order = [];
6533   * var array = [4.2, 6.4, 6.1];
6534   * var iterator = function(num, index, done) {
6535   *   setTimeout(function() {
6536   *     order.push([num, index]);
6537   *     done(null, Math.floor(num));
6538   *   }, num * 10);
6539   * };
6540   * async.groupBySeries(array, iterator, function(err, res) {
6541   *   console.log(res); // { '4': [4.2], '6': [6.4, 6.1] }
6542   *   console.log(order); // [[4.2, 0], [6.4, 1], [6.1, 2]]
6543   * });
6544   *
6545   * @example
6546   *
6547   * // object
6548   * var order = [];
6549   * var object = { a: 4.2, b: 6.4, c: 6.1 };
6550   * var iterator = function(num, done) {
6551   *   setTimeout(function() {
6552   *     order.push(num);
6553   *     done(null, Math.floor(num));
6554   *   }, num * 10);
6555   * };
6556   * async.groupBySeries(object, iterator, function(err, res) {
6557   *   console.log(res); // { '4': [4.2], '6': [6.4, 6.1] }
6558   *   console.log(order); // [4.2, 6.4, 6.1]
6559   * });
6560   *
6561   * @example
6562   *
6563   * // object with key
6564   * var order = [];
6565   * var object = { a: 4.2, b: 6.4, c: 6.1 };
6566   * var iterator = function(num, key, done) {
6567   *   setTimeout(function() {
6568   *     order.push([num, key]);
6569   *     done(null, Math.floor(num));
6570   *   }, num * 10);
6571   * };
6572   * async.groupBySeries(object, iterator, function(err, res) {
6573   *   console.log(res); // { '4': [4.2], '6': [6.4, 6.1] }
6574   *   console.log(order); // [[4.2, 'a'], [6.4, 'b'], [6.1, 'c']]
6575   * });
6576   *
6577   */
6578  function groupBySeries(collection, iterator, callback) {
6579    callback = onlyOnce(callback || noop);
6580    var size, key, value, keys, iter, item, iterate;
6581    var sync = false;
6582    var completed = 0;
6583    var result = {};
6584
6585    if (isArray(collection)) {
6586      size = collection.length;
6587      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
6588    } else if (!collection) {
6589    } else if (iteratorSymbol && collection[iteratorSymbol]) {
6590      size = Infinity;
6591      iter = collection[iteratorSymbol]();
6592      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
6593    } else if (typeof collection === obj) {
6594      keys = nativeKeys(collection);
6595      size = keys.length;
6596      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
6597    }
6598    if (!size) {
6599      return callback(null, result);
6600    }
6601    iterate();
6602
6603    function arrayIterator() {
6604      value = collection[completed];
6605      iterator(value, done);
6606    }
6607
6608    function arrayIteratorWithIndex() {
6609      value = collection[completed];
6610      iterator(value, completed, done);
6611    }
6612
6613    function symbolIterator() {
6614      item = iter.next();
6615      value = item.value;
6616      item.done ? callback(null, result) : iterator(value, done);
6617    }
6618
6619    function symbolIteratorWithKey() {
6620      item = iter.next();
6621      value = item.value;
6622      item.done ? callback(null, result) : iterator(value, completed, done);
6623    }
6624
6625    function objectIterator() {
6626      value = collection[keys[completed]];
6627      iterator(value, done);
6628    }
6629
6630    function objectIteratorWithKey() {
6631      key = keys[completed];
6632      value = collection[key];
6633      iterator(value, key, done);
6634    }
6635
6636    function done(err, key) {
6637      if (err) {
6638        iterate = throwError;
6639        callback = onlyOnce(callback);
6640        callback(err, objectClone(result));
6641        return;
6642      }
6643      var array = result[key];
6644      if (!array) {
6645        result[key] = [value];
6646      } else {
6647        array.push(value);
6648      }
6649      if (++completed === size) {
6650        iterate = throwError;
6651        callback(null, result);
6652      } else if (sync) {
6653        nextTick(iterate);
6654      } else {
6655        sync = true;
6656        iterate();
6657      }
6658      sync = false;
6659    }
6660  }
6661
6662  /**
6663   * @memberof async
6664   * @namespace groupByLimit
6665   * @param {Array|Object} collection
6666   * @param {Function} iterator
6667   * @param {Function} callback
6668   * @example
6669   *
6670   * // array
6671   * var order = [];
6672   * var array = [1.1, 5.9, 3.2, 3.9, 2.1];
6673   * var iterator = function(num, done) {
6674   *   setTimeout(function() {
6675   *     order.push(num);
6676   *     done(null, Math.floor(num));
6677   *   }, num * 10);
6678   * };
6679   * async.groupByLimit(array, 2, iterator, function(err, res) {
6680   *   console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] }
6681   *   console.log(order); // [1.1, 3.2, 5.9, 2.1, 3.9]
6682   * });
6683   *
6684   * @example
6685   *
6686   * // array with index
6687   * var order = [];
6688   * var array = [1.1, 5.9, 3.2, 3.9, 2.1];
6689   * var iterator = function(num, index, done) {
6690   *   setTimeout(function() {
6691   *     order.push([num, index]);
6692   *     done(null, Math.floor(num));
6693   *   }, num * 10);
6694   * };
6695   * async.groupByLimit(array, 2, iterator, function(err, res) {
6696   *   console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] }
6697   *   console.log(order); // [[1.1, 0], [3.2, 2], [5.9, 1], [2.1, 4], [3.9, 3]]
6698   * });
6699   *
6700   * @example
6701   *
6702   * // object
6703   * var order = [];
6704   * var object = { a: 1.1, b: 5.9, c: 3.2, d: 3.9, e: 2.1 }
6705   * var iterator = function(num, done) {
6706   *   setTimeout(function() {
6707   *     order.push(num);
6708   *     done(null, Math.floor(num));
6709   *   }, num * 10);
6710   * };
6711   * async.groupByLimit(object, 2, iterator, function(err, res) {
6712   *   console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] }
6713   *   console.log(order); // [1.1, 3.2, 5.9, 2.1, 3.9]
6714   * });
6715   *
6716   * @example
6717   *
6718   * // object with key
6719   * var order = [];
6720   * var object = { a: 1.1, b: 5.9, c: 3.2, d: 3.9, e: 2.1 }
6721   * var iterator = function(num, key, done) {
6722   *   setTimeout(function() {
6723   *     order.push([num, key]);
6724   *     done(null, Math.floor(num));
6725   *   }, num * 10);
6726   * };
6727   * async.groupByLimit(object, 2, iterator, function(err, res) {
6728   *   console.log(res); // { '1': [1.1], '3': [3.2, 3.9], '5': [5.9], '2': [2.1] }
6729   *   console.log(order); // [[1.1, 'a'], [3.2, 'c'], [5.9, 'b'], [2.1, 'e'], [3.9, 'd']]
6730   * });
6731   *
6732   */
6733  function groupByLimit(collection, limit, iterator, callback) {
6734    callback = callback || noop;
6735    var size, index, key, value, keys, iter, item, iterate;
6736    var sync = false;
6737    var started = 0;
6738    var completed = 0;
6739    var result = {};
6740
6741    if (isArray(collection)) {
6742      size = collection.length;
6743      iterate = iterator.length === 3 ? arrayIteratorWithIndex : arrayIterator;
6744    } else if (!collection) {
6745    } else if (iteratorSymbol && collection[iteratorSymbol]) {
6746      size = Infinity;
6747      iter = collection[iteratorSymbol]();
6748      iterate = iterator.length === 3 ? symbolIteratorWithKey : symbolIterator;
6749    } else if (typeof collection === obj) {
6750      keys = nativeKeys(collection);
6751      size = keys.length;
6752      iterate = iterator.length === 3 ? objectIteratorWithKey : objectIterator;
6753    }
6754    if (!size || isNaN(limit) || limit < 1) {
6755      return callback(null, result);
6756    }
6757    timesSync(limit > size ? size : limit, iterate);
6758
6759    function arrayIterator() {
6760      if (started < size) {
6761        value = collection[started++];
6762        iterator(value, createCallback(value));
6763      }
6764    }
6765
6766    function arrayIteratorWithIndex() {
6767      index = started++;
6768      if (index < size) {
6769        value = collection[index];
6770        iterator(value, index, createCallback(value));
6771      }
6772    }
6773
6774    function symbolIterator() {
6775      item = iter.next();
6776      if (item.done === false) {
6777        started++;
6778        value = item.value;
6779        iterator(value, createCallback(value));
6780      } else if (completed === started && iterator !== noop) {
6781        iterator = noop;
6782        callback(null, result);
6783      }
6784    }
6785
6786    function symbolIteratorWithKey() {
6787      item = iter.next();
6788      if (item.done === false) {
6789        value = item.value;
6790        iterator(value, started++, createCallback(value));
6791      } else if (completed === started && iterator !== noop) {
6792        iterator = noop;
6793        callback(null, result);
6794      }
6795    }
6796
6797    function objectIterator() {
6798      if (started < size) {
6799        value = collection[keys[started++]];
6800        iterator(value, createCallback(value));
6801      }
6802    }
6803
6804    function objectIteratorWithKey() {
6805      if (started < size) {
6806        key = keys[started++];
6807        value = collection[key];
6808        iterator(value, key, createCallback(value));
6809      }
6810    }
6811
6812    function createCallback(value) {
6813      var called = false;
6814      return function(err, key) {
6815        if (called) {
6816          throwError();
6817        }
6818        called = true;
6819        if (err) {
6820          iterate = noop;
6821          callback = once(callback);
6822          callback(err, objectClone(result));
6823          return;
6824        }
6825        var array = result[key];
6826        if (!array) {
6827          result[key] = [value];
6828        } else {
6829          array.push(value);
6830        }
6831        if (++completed === size) {
6832          callback(null, result);
6833        } else if (sync) {
6834          nextTick(iterate);
6835        } else {
6836          sync = true;
6837          iterate();
6838        }
6839        sync = false;
6840      };
6841    }
6842  }
6843
6844  /**
6845   * @private
6846   * @param {Function} arrayEach
6847   * @param {Function} baseEach
6848   */
6849  function createParallel(arrayEach, baseEach) {
6850    return function parallel(tasks, callback) {
6851      callback = callback || noop;
6852      var size, keys, result;
6853      var completed = 0;
6854
6855      if (isArray(tasks)) {
6856        size = tasks.length;
6857        result = Array(size);
6858        arrayEach(tasks, createCallback);
6859      } else if (tasks && typeof tasks === obj) {
6860        keys = nativeKeys(tasks);
6861        size = keys.length;
6862        result = {};
6863        baseEach(tasks, createCallback, keys);
6864      }
6865      if (!size) {
6866        callback(null, result);
6867      }
6868
6869      function createCallback(key) {
6870        return function(err, res) {
6871          if (key === null) {
6872            throwError();
6873          }
6874          if (err) {
6875            key = null;
6876            callback = once(callback);
6877            callback(err, result);
6878            return;
6879          }
6880          result[key] = arguments.length <= 2 ? res : slice(arguments, 1);
6881          key = null;
6882          if (++completed === size) {
6883            callback(null, result);
6884          }
6885        };
6886      }
6887    };
6888  }
6889
6890  /**
6891   * @memberof async
6892   * @namespace series
6893   * @param {Array|Object} tasks - functions
6894   * @param {Function} callback
6895   * @example
6896   *
6897   * var order = [];
6898   * var tasks = [
6899   *  function(done) {
6900   *    setTimeout(function() {
6901   *      order.push(1);
6902   *      done(null, 1);
6903   *    }, 10);
6904   *  },
6905   *  function(done) {
6906   *    setTimeout(function() {
6907   *      order.push(2);
6908   *      done(null, 2);
6909   *    }, 30);
6910   *  },
6911   *  function(done) {
6912   *    setTimeout(function() {
6913   *      order.push(3);
6914   *      done(null, 3);
6915   *    }, 40);
6916   *  },
6917   *  function(done) {
6918   *    setTimeout(function() {
6919   *      order.push(4);
6920   *      done(null, 4);
6921   *    }, 20);
6922   *  }
6923   * ];
6924   * async.series(tasks, function(err, res) {
6925   *   console.log(res); // [1, 2, 3, 4];
6926   *   console.log(order); // [1, 2, 3, 4]
6927   * });
6928   *
6929   * @example
6930   *
6931   * var order = [];
6932   * var tasks = {
6933   *   'a': function(done) {
6934   *     setTimeout(function() {
6935   *       order.push(1);
6936   *       done(null, 1);
6937   *     }, 10);
6938   *   },
6939   *   'b': function(done) {
6940   *     setTimeout(function() {
6941   *       order.push(2);
6942   *       done(null, 2);
6943   *     }, 30);
6944   *   },
6945   *   'c': function(done) {
6946   *     setTimeout(function() {
6947   *       order.push(3);
6948   *       done(null, 3);
6949   *     }, 40);
6950   *   },
6951   *   'd': function(done) {
6952   *     setTimeout(function() {
6953   *       order.push(4);
6954   *       done(null, 4);
6955   *     }, 20);
6956   *   }
6957   * };
6958   * async.series(tasks, function(err, res) {
6959   *   console.log(res); // { a: 1, b: 2, c: 3, d:4 }
6960   *   console.log(order); // [1, 4, 2, 3]
6961   * });
6962   *
6963   */
6964  function series(tasks, callback) {
6965    callback = callback || noop;
6966    var size, key, keys, result, iterate;
6967    var sync = false;
6968    var completed = 0;
6969
6970    if (isArray(tasks)) {
6971      size = tasks.length;
6972      result = Array(size);
6973      iterate = arrayIterator;
6974    } else if (tasks && typeof tasks === obj) {
6975      keys = nativeKeys(tasks);
6976      size = keys.length;
6977      result = {};
6978      iterate = objectIterator;
6979    } else {
6980      return callback(null);
6981    }
6982    if (!size) {
6983      return callback(null, result);
6984    }
6985    iterate();
6986
6987    function arrayIterator() {
6988      key = completed;
6989      tasks[completed](done);
6990    }
6991
6992    function objectIterator() {
6993      key = keys[completed];
6994      tasks[key](done);
6995    }
6996
6997    function done(err, res) {
6998      if (err) {
6999        iterate = throwError;
7000        callback = onlyOnce(callback);
7001        callback(err, result);
7002        return;
7003      }
7004      result[key] = arguments.length <= 2 ? res : slice(arguments, 1);
7005      if (++completed === size) {
7006        iterate = throwError;
7007        callback(null, result);
7008      } else if (sync) {
7009        nextTick(iterate);
7010      } else {
7011        sync = true;
7012        iterate();
7013      }
7014      sync = false;
7015    }
7016  }
7017
7018  /**
7019   * @memberof async
7020   * @namespace parallelLimit
7021   * @param {Array|Object} tasks - functions
7022   * @param {number} limit - limit >= 1
7023   * @param {Function} callback
7024   * @example
7025   *
7026   * var order = [];
7027   * var tasks = [
7028   *  function(done) {
7029   *    setTimeout(function() {
7030   *      order.push(1);
7031   *      done(null, 1);
7032   *    }, 10);
7033   *  },
7034   *  function(done) {
7035   *    setTimeout(function() {
7036   *      order.push(2);
7037   *      done(null, 2);
7038   *    }, 50);
7039   *  },
7040   *  function(done) {
7041   *    setTimeout(function() {
7042   *      order.push(3);
7043   *      done(null, 3);
7044   *    }, 30);
7045   *  },
7046   *  function(done) {
7047   *    setTimeout(function() {
7048   *      order.push(4);
7049   *      done(null, 4);
7050   *    }, 40);
7051   *  }
7052   * ];
7053   * async.parallelLimit(tasks, 2, function(err, res) {
7054   *   console.log(res); // [1, 2, 3, 4];
7055   *   console.log(order); // [1, 3, 2, 4]
7056   * });
7057   *
7058   * @example
7059   *
7060   * var order = [];
7061   * var tasks = {
7062   *   'a': function(done) {
7063   *     setTimeout(function() {
7064   *       order.push(1);
7065   *       done(null, 1);
7066   *     }, 10);
7067   *   },
7068   *   'b': function(done) {
7069   *     setTimeout(function() {
7070   *       order.push(2);
7071   *       done(null, 2);
7072   *     }, 50);
7073   *   },
7074   *   'c': function(done) {
7075   *     setTimeout(function() {
7076   *       order.push(3);
7077   *       done(null, 3);
7078   *     }, 20);
7079   *   },
7080   *   'd': function(done) {
7081   *     setTimeout(function() {
7082   *       order.push(4);
7083   *       done(null, 4);
7084   *     }, 40);
7085   *   }
7086   * };
7087   * async.parallelLimit(tasks, 2, function(err, res) {
7088   *   console.log(res); // { a: 1, b: 2, c: 3, d:4 }
7089   *   console.log(order); // [1, 3, 2, 4]
7090   * });
7091   *
7092   */
7093  function parallelLimit(tasks, limit, callback) {
7094    callback = callback || noop;
7095    var size, index, key, keys, result, iterate;
7096    var sync = false;
7097    var started = 0;
7098    var completed = 0;
7099
7100    if (isArray(tasks)) {
7101      size = tasks.length;
7102      result = Array(size);
7103      iterate = arrayIterator;
7104    } else if (tasks && typeof tasks === obj) {
7105      keys = nativeKeys(tasks);
7106      size = keys.length;
7107      result = {};
7108      iterate = objectIterator;
7109    }
7110    if (!size || isNaN(limit) || limit < 1) {
7111      return callback(null, result);
7112    }
7113    timesSync(limit > size ? size : limit, iterate);
7114
7115    function arrayIterator() {
7116      index = started++;
7117      if (index < size) {
7118        tasks[index](createCallback(index));
7119      }
7120    }
7121
7122    function objectIterator() {
7123      if (started < size) {
7124        key = keys[started++];
7125        tasks[key](createCallback(key));
7126      }
7127    }
7128
7129    function createCallback(key) {
7130      return function(err, res) {
7131        if (key === null) {
7132          throwError();
7133        }
7134        if (err) {
7135          key = null;
7136          iterate = noop;
7137          callback = once(callback);
7138          callback(err, result);
7139          return;
7140        }
7141        result[key] = arguments.length <= 2 ? res : slice(arguments, 1);
7142        key = null;
7143        if (++completed === size) {
7144          callback(null, result);
7145        } else if (sync) {
7146          nextTick(iterate);
7147        } else {
7148          sync = true;
7149          iterate();
7150        }
7151        sync = false;
7152      };
7153    }
7154  }
7155
7156  /**
7157   * @memberof async
7158   * @namespace tryEach
7159   * @param {Array|Object} tasks - functions
7160   * @param {Function} callback
7161   * @example
7162   *
7163   * var tasks = [
7164   *  function(done) {
7165   *    setTimeout(function() {
7166   *      done(new Error('error'));
7167   *    }, 10);
7168   *  },
7169   *  function(done) {
7170   *    setTimeout(function() {
7171   *      done(null, 2);
7172   *    }, 10);
7173   *  }
7174   * ];
7175   * async.tryEach(tasks, function(err, res) {
7176   *   console.log(res); // 2
7177   * });
7178   *
7179   * @example
7180   *
7181   * var tasks = [
7182   *  function(done) {
7183   *    setTimeout(function() {
7184   *      done(new Error('error1'));
7185   *    }, 10);
7186   *  },
7187   *  function(done) {
7188   *    setTimeout(function() {
7189   *      done(new Error('error2');
7190   *    }, 10);
7191   *  }
7192   * ];
7193   * async.tryEach(tasks, function(err, res) {
7194   *   console.log(err); // error2
7195   *   console.log(res); // undefined
7196   * });
7197   *
7198   */
7199  function tryEach(tasks, callback) {
7200    callback = callback || noop;
7201    var size, keys, iterate;
7202    var sync = false;
7203    var completed = 0;
7204
7205    if (isArray(tasks)) {
7206      size = tasks.length;
7207      iterate = arrayIterator;
7208    } else if (tasks && typeof tasks === obj) {
7209      keys = nativeKeys(tasks);
7210      size = keys.length;
7211      iterate = objectIterator;
7212    }
7213    if (!size) {
7214      return callback(null);
7215    }
7216    iterate();
7217
7218    function arrayIterator() {
7219      tasks[completed](done);
7220    }
7221
7222    function objectIterator() {
7223      tasks[keys[completed]](done);
7224    }
7225
7226    function done(err, res) {
7227      if (!err) {
7228        if (arguments.length <= 2) {
7229          callback(null, res);
7230        } else {
7231          callback(null, slice(arguments, 1));
7232        }
7233      } else if (++completed === size) {
7234        callback(err);
7235      } else {
7236        sync = true;
7237        iterate();
7238      }
7239      sync = false;
7240    }
7241  }
7242
7243  /**
7244   * check for waterfall tasks
7245   * @private
7246   * @param {Array} tasks
7247   * @param {Function} callback
7248   * @return {boolean}
7249   */
7250  function checkWaterfallTasks(tasks, callback) {
7251    if (!isArray(tasks)) {
7252      callback(new Error('First argument to waterfall must be an array of functions'));
7253      return false;
7254    }
7255    if (tasks.length === 0) {
7256      callback(null);
7257      return false;
7258    }
7259    return true;
7260  }
7261
7262  /**
7263   * check for waterfall tasks
7264   * @private
7265   * @param {function} func
7266   * @param {Array|Object} args - arguments
7267   * @return {function} next
7268   */
7269  function waterfallIterator(func, args, next) {
7270    switch (args.length) {
7271      case 0:
7272      case 1:
7273        return func(next);
7274      case 2:
7275        return func(args[1], next);
7276      case 3:
7277        return func(args[1], args[2], next);
7278      case 4:
7279        return func(args[1], args[2], args[3], next);
7280      case 5:
7281        return func(args[1], args[2], args[3], args[4], next);
7282      case 6:
7283        return func(args[1], args[2], args[3], args[4], args[5], next);
7284      default:
7285        args = slice(args, 1);
7286        args.push(next);
7287        return func.apply(null, args);
7288    }
7289  }
7290
7291  /**
7292   * @memberof async
7293   * @namespace waterfall
7294   * @param {Array} tasks - functions
7295   * @param {Function} callback
7296   * @example
7297   *
7298   * var order = [];
7299   * var tasks = [
7300   *   function(next) {
7301   *     setTimeout(function() {
7302   *       order.push(1);
7303   *       next(null, 1);
7304   *     }, 10);
7305   *   },
7306   *   function(arg1, next) {
7307   *     setTimeout(function() {
7308   *       order.push(2);
7309   *       next(null, 1, 2);
7310   *     }, 30);
7311   *   },
7312   *   function(arg1, arg2, next) {
7313   *     setTimeout(function() {
7314   *       order.push(3);
7315   *       next(null, 3);
7316   *     }, 20);
7317   *   },
7318   *   function(arg1, next) {
7319   *     setTimeout(function() {
7320   *       order.push(4);
7321   *       next(null, 1, 2, 3, 4);
7322   *     }, 40);
7323   *   }
7324   * ];
7325   * async.waterfall(tasks, function(err, arg1, arg2, arg3, arg4) {
7326   *   console.log(arg1, arg2, arg3, arg4); // 1 2 3 4
7327   * });
7328   *
7329   */
7330  function waterfall(tasks, callback) {
7331    callback = callback || noop;
7332    if (!checkWaterfallTasks(tasks, callback)) {
7333      return;
7334    }
7335    var func, args, done, sync;
7336    var completed = 0;
7337    var size = tasks.length;
7338    waterfallIterator(tasks[0], [], createCallback(0));
7339
7340    function iterate() {
7341      waterfallIterator(func, args, createCallback(func));
7342    }
7343
7344    function createCallback(index) {
7345      return function next(err, res) {
7346        if (index === undefined) {
7347          callback = noop;
7348          throwError();
7349        }
7350        index = undefined;
7351        if (err) {
7352          done = callback;
7353          callback = throwError;
7354          done(err);
7355          return;
7356        }
7357        if (++completed === size) {
7358          done = callback;
7359          callback = throwError;
7360          if (arguments.length <= 2) {
7361            done(err, res);
7362          } else {
7363            done.apply(null, createArray(arguments));
7364          }
7365          return;
7366        }
7367        if (sync) {
7368          args = arguments;
7369          func = tasks[completed] || throwError;
7370          nextTick(iterate);
7371        } else {
7372          sync = true;
7373          waterfallIterator(tasks[completed] || throwError, arguments, createCallback(completed));
7374        }
7375        sync = false;
7376      };
7377    }
7378  }
7379
7380  /**
7381   * `angelFall` is like `waterfall` and inject callback to last argument of next task.
7382   *
7383   * @memberof async
7384   * @namespace angelFall
7385   * @param {Array} tasks - functions
7386   * @param {Function} callback
7387   * @example
7388   *
7389   * var order = [];
7390   * var tasks = [
7391   *   function(next) {
7392   *     setTimeout(function() {
7393   *       order.push(1);
7394   *       next(null, 1);
7395   *     }, 10);
7396   *   },
7397   *   function(arg1, empty, next) {
7398   *     setTimeout(function() {
7399   *       order.push(2);
7400   *       next(null, 1, 2);
7401   *     }, 30);
7402   *   },
7403   *   function(next) {
7404   *     setTimeout(function() {
7405   *       order.push(3);
7406   *       next(null, 3);
7407   *     }, 20);
7408   *   },
7409   *   function(arg1, empty1, empty2, empty3, next) {
7410   *     setTimeout(function() {
7411   *       order.push(4);
7412   *       next(null, 1, 2, 3, 4);
7413   *     }, 40);
7414   *   }
7415   * ];
7416   * async.angelFall(tasks, function(err, arg1, arg2, arg3, arg4) {
7417   *   console.log(arg1, arg2, arg3, arg4); // 1 2 3 4
7418   * });
7419   *
7420   */
7421  function angelFall(tasks, callback) {
7422    callback = callback || noop;
7423    if (!checkWaterfallTasks(tasks, callback)) {
7424      return;
7425    }
7426    var completed = 0;
7427    var sync = false;
7428    var size = tasks.length;
7429    var func = tasks[completed];
7430    var args = [];
7431    var iterate = function() {
7432      switch (func.length) {
7433        case 0:
7434          try {
7435            next(null, func());
7436          } catch (e) {
7437            next(e);
7438          }
7439          return;
7440        case 1:
7441          return func(next);
7442        case 2:
7443          return func(args[1], next);
7444        case 3:
7445          return func(args[1], args[2], next);
7446        case 4:
7447          return func(args[1], args[2], args[3], next);
7448        case 5:
7449          return func(args[1], args[2], args[3], args[4], next);
7450        default:
7451          args = slice(args, 1);
7452          args[func.length - 1] = next;
7453          return func.apply(null, args);
7454      }
7455    };
7456    iterate();
7457
7458    function next(err, res) {
7459      if (err) {
7460        iterate = throwError;
7461        callback = onlyOnce(callback);
7462        callback(err);
7463        return;
7464      }
7465      if (++completed === size) {
7466        iterate = throwError;
7467        var done = callback;
7468        callback = throwError;
7469        if (arguments.length === 2) {
7470          done(err, res);
7471        } else {
7472          done.apply(null, createArray(arguments));
7473        }
7474        return;
7475      }
7476      func = tasks[completed];
7477      args = arguments;
7478      if (sync) {
7479        nextTick(iterate);
7480      } else {
7481        sync = true;
7482        iterate();
7483      }
7484      sync = false;
7485    }
7486  }
7487
7488  /**
7489   * @memberof async
7490   * @namespace whilst
7491   * @param {Function} test
7492   * @param {Function} iterator
7493   * @param {Function} callback
7494   */
7495  function whilst(test, iterator, callback) {
7496    callback = callback || noop;
7497    var sync = false;
7498    if (test()) {
7499      iterate();
7500    } else {
7501      callback(null);
7502    }
7503
7504    function iterate() {
7505      if (sync) {
7506        nextTick(next);
7507      } else {
7508        sync = true;
7509        iterator(done);
7510      }
7511      sync = false;
7512    }
7513
7514    function next() {
7515      iterator(done);
7516    }
7517
7518    function done(err, arg) {
7519      if (err) {
7520        return callback(err);
7521      }
7522      if (arguments.length <= 2) {
7523        if (test(arg)) {
7524          iterate();
7525        } else {
7526          callback(null, arg);
7527        }
7528        return;
7529      }
7530      arg = slice(arguments, 1);
7531      if (test.apply(null, arg)) {
7532        iterate();
7533      } else {
7534        callback.apply(null, [null].concat(arg));
7535      }
7536    }
7537  }
7538
7539  /**
7540   * @memberof async
7541   * @namespace doWhilst
7542   * @param {Function} iterator
7543   * @param {Function} test
7544   * @param {Function} callback
7545   */
7546  function doWhilst(iterator, test, callback) {
7547    callback = callback || noop;
7548    var sync = false;
7549    next();
7550
7551    function iterate() {
7552      if (sync) {
7553        nextTick(next);
7554      } else {
7555        sync = true;
7556        iterator(done);
7557      }
7558      sync = false;
7559    }
7560
7561    function next() {
7562      iterator(done);
7563    }
7564
7565    function done(err, arg) {
7566      if (err) {
7567        return callback(err);
7568      }
7569      if (arguments.length <= 2) {
7570        if (test(arg)) {
7571          iterate();
7572        } else {
7573          callback(null, arg);
7574        }
7575        return;
7576      }
7577      arg = slice(arguments, 1);
7578      if (test.apply(null, arg)) {
7579        iterate();
7580      } else {
7581        callback.apply(null, [null].concat(arg));
7582      }
7583    }
7584  }
7585
7586  /**
7587   * @memberof async
7588   * @namespace until
7589   * @param {Function} test
7590   * @param {Function} iterator
7591   * @param {Function} callback
7592   */
7593  function until(test, iterator, callback) {
7594    callback = callback || noop;
7595    var sync = false;
7596    if (!test()) {
7597      iterate();
7598    } else {
7599      callback(null);
7600    }
7601
7602    function iterate() {
7603      if (sync) {
7604        nextTick(next);
7605      } else {
7606        sync = true;
7607        iterator(done);
7608      }
7609      sync = false;
7610    }
7611
7612    function next() {
7613      iterator(done);
7614    }
7615
7616    function done(err, arg) {
7617      if (err) {
7618        return callback(err);
7619      }
7620      if (arguments.length <= 2) {
7621        if (!test(arg)) {
7622          iterate();
7623        } else {
7624          callback(null, arg);
7625        }
7626        return;
7627      }
7628      arg = slice(arguments, 1);
7629      if (!test.apply(null, arg)) {
7630        iterate();
7631      } else {
7632        callback.apply(null, [null].concat(arg));
7633      }
7634    }
7635  }
7636
7637  /**
7638   * @memberof async
7639   * @namespace doUntil
7640   * @param {Function} iterator
7641   * @param {Function} test
7642   * @param {Function} callback
7643   */
7644  function doUntil(iterator, test, callback) {
7645    callback = callback || noop;
7646    var sync = false;
7647    next();
7648
7649    function iterate() {
7650      if (sync) {
7651        nextTick(next);
7652      } else {
7653        sync = true;
7654        iterator(done);
7655      }
7656      sync = false;
7657    }
7658
7659    function next() {
7660      iterator(done);
7661    }
7662
7663    function done(err, arg) {
7664      if (err) {
7665        return callback(err);
7666      }
7667      if (arguments.length <= 2) {
7668        if (!test(arg)) {
7669          iterate();
7670        } else {
7671          callback(null, arg);
7672        }
7673        return;
7674      }
7675      arg = slice(arguments, 1);
7676      if (!test.apply(null, arg)) {
7677        iterate();
7678      } else {
7679        callback.apply(null, [null].concat(arg));
7680      }
7681    }
7682  }
7683
7684  /**
7685   * @memberof async
7686   * @namespace during
7687   * @param {Function} test
7688   * @param {Function} iterator
7689   * @param {Function} callback
7690   */
7691  function during(test, iterator, callback) {
7692    callback = callback || noop;
7693    _test();
7694
7695    function _test() {
7696      test(iterate);
7697    }
7698
7699    function iterate(err, truth) {
7700      if (err) {
7701        return callback(err);
7702      }
7703      if (truth) {
7704        iterator(done);
7705      } else {
7706        callback(null);
7707      }
7708    }
7709
7710    function done(err) {
7711      if (err) {
7712        return callback(err);
7713      }
7714      _test();
7715    }
7716  }
7717
7718  /**
7719   * @memberof async
7720   * @namespace doDuring
7721   * @param {Function} test
7722   * @param {Function} iterator
7723   * @param {Function} callback
7724   */
7725  function doDuring(iterator, test, callback) {
7726    callback = callback || noop;
7727    iterate(null, true);
7728
7729    function iterate(err, truth) {
7730      if (err) {
7731        return callback(err);
7732      }
7733      if (truth) {
7734        iterator(done);
7735      } else {
7736        callback(null);
7737      }
7738    }
7739
7740    function done(err, res) {
7741      if (err) {
7742        return callback(err);
7743      }
7744      switch (arguments.length) {
7745        case 0:
7746        case 1:
7747          test(iterate);
7748          break;
7749        case 2:
7750          test(res, iterate);
7751          break;
7752        default:
7753          var args = slice(arguments, 1);
7754          args.push(iterate);
7755          test.apply(null, args);
7756          break;
7757      }
7758    }
7759  }
7760
7761  /**
7762   * @memberof async
7763   * @namespace forever
7764   */
7765  function forever(iterator, callback) {
7766    var sync = false;
7767    iterate();
7768
7769    function iterate() {
7770      iterator(next);
7771    }
7772
7773    function next(err) {
7774      if (err) {
7775        if (callback) {
7776          return callback(err);
7777        }
7778        throw err;
7779      }
7780      if (sync) {
7781        nextTick(iterate);
7782      } else {
7783        sync = true;
7784        iterate();
7785      }
7786      sync = false;
7787    }
7788  }
7789
7790  /**
7791   * @memberof async
7792   * @namespace compose
7793   */
7794  function compose() {
7795    return seq.apply(null, reverse(arguments));
7796  }
7797
7798  /**
7799   * @memberof async
7800   * @namespace seq
7801   */
7802  function seq(/* functions... */) {
7803    var fns = createArray(arguments);
7804
7805    return function() {
7806      var self = this;
7807      var args = createArray(arguments);
7808      var callback = args[args.length - 1];
7809      if (typeof callback === func) {
7810        args.pop();
7811      } else {
7812        callback = noop;
7813      }
7814      reduce(fns, args, iterator, done);
7815
7816      function iterator(newargs, fn, callback) {
7817        var func = function(err) {
7818          var nextargs = slice(arguments, 1);
7819          callback(err, nextargs);
7820        };
7821        newargs.push(func);
7822        fn.apply(self, newargs);
7823      }
7824
7825      function done(err, res) {
7826        res = isArray(res) ? res : [res];
7827        res.unshift(err);
7828        callback.apply(self, res);
7829      }
7830    };
7831  }
7832
7833  function createApplyEach(func) {
7834    return function applyEach(fns /* arguments */) {
7835      var go = function() {
7836        var self = this;
7837        var args = createArray(arguments);
7838        var callback = args.pop() || noop;
7839        return func(fns, iterator, callback);
7840
7841        function iterator(fn, done) {
7842          fn.apply(self, args.concat([done]));
7843        }
7844      };
7845      if (arguments.length > 1) {
7846        var args = slice(arguments, 1);
7847        return go.apply(this, args);
7848      } else {
7849        return go;
7850      }
7851    };
7852  }
7853
7854  /**
7855   * @see https://github.com/caolan/async/blob/master/lib/internal/DoublyLinkedList.js
7856   */
7857  function DLL() {
7858    this.head = null;
7859    this.tail = null;
7860    this.length = 0;
7861  }
7862
7863  DLL.prototype._removeLink = function(node) {
7864    var prev = node.prev;
7865    var next = node.next;
7866    if (prev) {
7867      prev.next = next;
7868    } else {
7869      this.head = next;
7870    }
7871    if (next) {
7872      next.prev = prev;
7873    } else {
7874      this.tail = prev;
7875    }
7876    node.prev = null;
7877    node.next = null;
7878    this.length--;
7879    return node;
7880  };
7881
7882  DLL.prototype.empty = DLL;
7883
7884  DLL.prototype._setInitial = function(node) {
7885    this.length = 1;
7886    this.head = this.tail = node;
7887  };
7888
7889  DLL.prototype.insertBefore = function(node, newNode) {
7890    newNode.prev = node.prev;
7891    newNode.next = node;
7892    if (node.prev) {
7893      node.prev.next = newNode;
7894    } else {
7895      this.head = newNode;
7896    }
7897    node.prev = newNode;
7898    this.length++;
7899  };
7900
7901  DLL.prototype.unshift = function(node) {
7902    if (this.head) {
7903      this.insertBefore(this.head, node);
7904    } else {
7905      this._setInitial(node);
7906    }
7907  };
7908
7909  DLL.prototype.push = function(node) {
7910    var tail = this.tail;
7911    if (tail) {
7912      node.prev = tail;
7913      node.next = tail.next;
7914      this.tail = node;
7915      tail.next = node;
7916      this.length++;
7917    } else {
7918      this._setInitial(node);
7919    }
7920  };
7921
7922  DLL.prototype.shift = function() {
7923    return this.head && this._removeLink(this.head);
7924  };
7925
7926  DLL.prototype.splice = function(end) {
7927    var task;
7928    var tasks = [];
7929    while (end-- && (task = this.shift())) {
7930      tasks.push(task);
7931    }
7932    return tasks;
7933  };
7934
7935  DLL.prototype.remove = function(test) {
7936    var node = this.head;
7937    while (node) {
7938      if (test(node)) {
7939        this._removeLink(node);
7940      }
7941      node = node.next;
7942    }
7943    return this;
7944  };
7945
7946  /**
7947   * @private
7948   */
7949  function baseQueue(isQueue, worker, concurrency, payload) {
7950    if (concurrency === undefined) {
7951      concurrency = 1;
7952    } else if (isNaN(concurrency) || concurrency < 1) {
7953      throw new Error('Concurrency must not be zero');
7954    }
7955
7956    var workers = 0;
7957    var workersList = [];
7958    var _callback, _unshift;
7959
7960    var q = {
7961      _tasks: new DLL(),
7962      concurrency: concurrency,
7963      payload: payload,
7964      saturated: noop,
7965      unsaturated: noop,
7966      buffer: concurrency / 4,
7967      empty: noop,
7968      drain: noop,
7969      error: noop,
7970      started: false,
7971      paused: false,
7972      push: push,
7973      kill: kill,
7974      unshift: unshift,
7975      remove: remove,
7976      process: isQueue ? runQueue : runCargo,
7977      length: getLength,
7978      running: running,
7979      workersList: getWorkersList,
7980      idle: idle,
7981      pause: pause,
7982      resume: resume,
7983      _worker: worker
7984    };
7985    return q;
7986
7987    function push(tasks, callback) {
7988      _insert(tasks, callback);
7989    }
7990
7991    function unshift(tasks, callback) {
7992      _insert(tasks, callback, true);
7993    }
7994
7995    function _exec(task) {
7996      var item = {
7997        data: task,
7998        callback: _callback
7999      };
8000      if (_unshift) {
8001        q._tasks.unshift(item);
8002      } else {
8003        q._tasks.push(item);
8004      }
8005      nextTick(q.process);
8006    }
8007
8008    function _insert(tasks, callback, unshift) {
8009      if (callback == null) {
8010        callback = noop;
8011      } else if (typeof callback !== 'function') {
8012        throw new Error('task callback must be a function');
8013      }
8014      q.started = true;
8015      var _tasks = isArray(tasks) ? tasks : [tasks];
8016
8017      if (tasks === undefined || !_tasks.length) {
8018        if (q.idle()) {
8019          nextTick(q.drain);
8020        }
8021        return;
8022      }
8023
8024      _unshift = unshift;
8025      _callback = callback;
8026      arrayEachSync(_tasks, _exec);
8027      // Avoid leaking the callback
8028      _callback = undefined;
8029    }
8030
8031    function kill() {
8032      q.drain = noop;
8033      q._tasks.empty();
8034    }
8035
8036    function _next(q, tasks) {
8037      var called = false;
8038      return function done(err, res) {
8039        if (called) {
8040          throwError();
8041        }
8042        called = true;
8043
8044        workers--;
8045        var task;
8046        var index = -1;
8047        var size = workersList.length;
8048        var taskIndex = -1;
8049        var taskSize = tasks.length;
8050        var useApply = arguments.length > 2;
8051        var args = useApply && createArray(arguments);
8052        while (++taskIndex < taskSize) {
8053          task = tasks[taskIndex];
8054          while (++index < size) {
8055            if (workersList[index] === task) {
8056              if (index === 0) {
8057                workersList.shift();
8058              } else {
8059                workersList.splice(index, 1);
8060              }
8061              index = size;
8062              size--;
8063            }
8064          }
8065          index = -1;
8066          if (useApply) {
8067            task.callback.apply(task, args);
8068          } else {
8069            task.callback(err, res);
8070          }
8071          if (err) {
8072            q.error(err, task.data);
8073          }
8074        }
8075
8076        if (workers <= q.concurrency - q.buffer) {
8077          q.unsaturated();
8078        }
8079
8080        if (q._tasks.length + workers === 0) {
8081          q.drain();
8082        }
8083        q.process();
8084      };
8085    }
8086
8087    function runQueue() {
8088      while (!q.paused && workers < q.concurrency && q._tasks.length) {
8089        var task = q._tasks.shift();
8090        workers++;
8091        workersList.push(task);
8092        if (q._tasks.length === 0) {
8093          q.empty();
8094        }
8095        if (workers === q.concurrency) {
8096          q.saturated();
8097        }
8098        var done = _next(q, [task]);
8099        worker(task.data, done);
8100      }
8101    }
8102
8103    function runCargo() {
8104      while (!q.paused && workers < q.concurrency && q._tasks.length) {
8105        var tasks = q._tasks.splice(q.payload || q._tasks.length);
8106        var index = -1;
8107        var size = tasks.length;
8108        var data = Array(size);
8109        while (++index < size) {
8110          data[index] = tasks[index].data;
8111        }
8112        workers++;
8113        nativePush.apply(workersList, tasks);
8114        if (q._tasks.length === 0) {
8115          q.empty();
8116        }
8117        if (workers === q.concurrency) {
8118          q.saturated();
8119        }
8120        var done = _next(q, tasks);
8121        worker(data, done);
8122      }
8123    }
8124
8125    function getLength() {
8126      return q._tasks.length;
8127    }
8128
8129    function running() {
8130      return workers;
8131    }
8132
8133    function getWorkersList() {
8134      return workersList;
8135    }
8136
8137    function idle() {
8138      return q.length() + workers === 0;
8139    }
8140
8141    function pause() {
8142      q.paused = true;
8143    }
8144
8145    function _resume() {
8146      nextTick(q.process);
8147    }
8148
8149    function resume() {
8150      if (q.paused === false) {
8151        return;
8152      }
8153      q.paused = false;
8154      var count = q.concurrency < q._tasks.length ? q.concurrency : q._tasks.length;
8155      timesSync(count, _resume);
8156    }
8157
8158    /**
8159     * @param {Function} test
8160     */
8161    function remove(test) {
8162      q._tasks.remove(test);
8163    }
8164  }
8165
8166  /**
8167   * @memberof async
8168   * @namespace queue
8169   */
8170  function queue(worker, concurrency) {
8171    return baseQueue(true, worker, concurrency);
8172  }
8173
8174  /**
8175   * @memberof async
8176   * @namespace priorityQueue
8177   */
8178  function priorityQueue(worker, concurrency) {
8179    var q = baseQueue(true, worker, concurrency);
8180    q.push = push;
8181    delete q.unshift;
8182    return q;
8183
8184    function push(tasks, priority, callback) {
8185      q.started = true;
8186      priority = priority || 0;
8187      var _tasks = isArray(tasks) ? tasks : [tasks];
8188      var taskSize = _tasks.length;
8189
8190      if (tasks === undefined || taskSize === 0) {
8191        if (q.idle()) {
8192          nextTick(q.drain);
8193        }
8194        return;
8195      }
8196
8197      callback = typeof callback === func ? callback : noop;
8198      var nextNode = q._tasks.head;
8199      while (nextNode && priority >= nextNode.priority) {
8200        nextNode = nextNode.next;
8201      }
8202      while (taskSize--) {
8203        var item = {
8204          data: _tasks[taskSize],
8205          priority: priority,
8206          callback: callback
8207        };
8208        if (nextNode) {
8209          q._tasks.insertBefore(nextNode, item);
8210        } else {
8211          q._tasks.push(item);
8212        }
8213        nextTick(q.process);
8214      }
8215    }
8216  }
8217
8218  /**
8219   * @memberof async
8220   * @namespace cargo
8221   */
8222  function cargo(worker, payload) {
8223    return baseQueue(false, worker, 1, payload);
8224  }
8225
8226  /**
8227   * @memberof async
8228   * @namespace auto
8229   * @param {Object} tasks
8230   * @param {number} [concurrency]
8231   * @param {Function} [callback]
8232   */
8233  function auto(tasks, concurrency, callback) {
8234    if (typeof concurrency === func) {
8235      callback = concurrency;
8236      concurrency = null;
8237    }
8238    var keys = nativeKeys(tasks);
8239    var rest = keys.length;
8240    var results = {};
8241    if (rest === 0) {
8242      return callback(null, results);
8243    }
8244    var runningTasks = 0;
8245    var readyTasks = new DLL();
8246    var listeners = Object.create(null);
8247    callback = onlyOnce(callback || noop);
8248    concurrency = concurrency || rest;
8249
8250    baseEachSync(tasks, iterator, keys);
8251    proceedQueue();
8252
8253    function iterator(task, key) {
8254      // no dependencies
8255      var _task, _taskSize;
8256      if (!isArray(task)) {
8257        _task = task;
8258        _taskSize = 0;
8259        readyTasks.push([_task, _taskSize, done]);
8260        return;
8261      }
8262      var dependencySize = task.length - 1;
8263      _task = task[dependencySize];
8264      _taskSize = dependencySize;
8265      if (dependencySize === 0) {
8266        readyTasks.push([_task, _taskSize, done]);
8267        return;
8268      }
8269      // dependencies
8270      var index = -1;
8271      while (++index < dependencySize) {
8272        var dependencyName = task[index];
8273        if (notInclude(keys, dependencyName)) {
8274          var msg =
8275            'async.auto task `' +
8276            key +
8277            '` has non-existent dependency `' +
8278            dependencyName +
8279            '` in ' +
8280            task.join(', ');
8281          throw new Error(msg);
8282        }
8283        var taskListeners = listeners[dependencyName];
8284        if (!taskListeners) {
8285          taskListeners = listeners[dependencyName] = [];
8286        }
8287        taskListeners.push(taskListener);
8288      }
8289
8290      function done(err, arg) {
8291        if (key === null) {
8292          throwError();
8293        }
8294        arg = arguments.length <= 2 ? arg : slice(arguments, 1);
8295        if (err) {
8296          rest = 0;
8297          runningTasks = 0;
8298          readyTasks.length = 0;
8299          var safeResults = objectClone(results);
8300          safeResults[key] = arg;
8301          key = null;
8302          var _callback = callback;
8303          callback = noop;
8304          _callback(err, safeResults);
8305          return;
8306        }
8307        runningTasks--;
8308        rest--;
8309        results[key] = arg;
8310        taskComplete(key);
8311        key = null;
8312      }
8313
8314      function taskListener() {
8315        if (--dependencySize === 0) {
8316          readyTasks.push([_task, _taskSize, done]);
8317        }
8318      }
8319    }
8320
8321    function proceedQueue() {
8322      if (readyTasks.length === 0 && runningTasks === 0) {
8323        if (rest !== 0) {
8324          throw new Error('async.auto task has cyclic dependencies');
8325        }
8326        return callback(null, results);
8327      }
8328      while (readyTasks.length && runningTasks < concurrency && callback !== noop) {
8329        runningTasks++;
8330        var array = readyTasks.shift();
8331        if (array[1] === 0) {
8332          array[0](array[2]);
8333        } else {
8334          array[0](results, array[2]);
8335        }
8336      }
8337    }
8338
8339    function taskComplete(key) {
8340      var taskListeners = listeners[key] || [];
8341      arrayEachSync(taskListeners, function(task) {
8342        task();
8343      });
8344      proceedQueue();
8345    }
8346  }
8347
8348  var FN_ARGS = /^(function)?\s*[^\(]*\(\s*([^\)]*)\)/m;
8349  var FN_ARG_SPLIT = /,/;
8350  var FN_ARG = /(=.+)?(\s*)$/;
8351  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
8352
8353  /**
8354   * parse function arguments for `autoInject`
8355   *
8356   * @private
8357   */
8358  function parseParams(func) {
8359    func = func.toString().replace(STRIP_COMMENTS, '');
8360    func = func.match(FN_ARGS)[2].replace(' ', '');
8361    func = func ? func.split(FN_ARG_SPLIT) : [];
8362    func = func.map(function(arg) {
8363      return arg.replace(FN_ARG, '').trim();
8364    });
8365    return func;
8366  }
8367
8368  /**
8369   * @memberof async
8370   * @namespace autoInject
8371   * @param {Object} tasks
8372   * @param {number} [concurrency]
8373   * @param {Function} [callback]
8374   */
8375  function autoInject(tasks, concurrency, callback) {
8376    var newTasks = {};
8377    baseEachSync(tasks, iterator, nativeKeys(tasks));
8378    auto(newTasks, concurrency, callback);
8379
8380    function iterator(task, key) {
8381      var params;
8382      var taskLength = task.length;
8383
8384      if (isArray(task)) {
8385        if (taskLength === 0) {
8386          throw new Error('autoInject task functions require explicit parameters.');
8387        }
8388        params = createArray(task);
8389        taskLength = params.length - 1;
8390        task = params[taskLength];
8391        if (taskLength === 0) {
8392          newTasks[key] = task;
8393          return;
8394        }
8395      } else if (taskLength === 1) {
8396        newTasks[key] = task;
8397        return;
8398      } else {
8399        params = parseParams(task);
8400        if (taskLength === 0 && params.length === 0) {
8401          throw new Error('autoInject task functions require explicit parameters.');
8402        }
8403        taskLength = params.length - 1;
8404      }
8405      params[taskLength] = newTask;
8406      newTasks[key] = params;
8407
8408      function newTask(results, done) {
8409        switch (taskLength) {
8410          case 1:
8411            task(results[params[0]], done);
8412            break;
8413          case 2:
8414            task(results[params[0]], results[params[1]], done);
8415            break;
8416          case 3:
8417            task(results[params[0]], results[params[1]], results[params[2]], done);
8418            break;
8419          default:
8420            var i = -1;
8421            while (++i < taskLength) {
8422              params[i] = results[params[i]];
8423            }
8424            params[i] = done;
8425            task.apply(null, params);
8426            break;
8427        }
8428      }
8429    }
8430  }
8431
8432  /**
8433   * @memberof async
8434   * @namespace retry
8435   * @param {integer|Object|Function} opts
8436   * @param {Function} [task]
8437   * @param {Function} [callback]
8438   */
8439  function retry(opts, task, callback) {
8440    var times, intervalFunc, errorFilter;
8441    var count = 0;
8442    if (arguments.length < 3 && typeof opts === func) {
8443      callback = task || noop;
8444      task = opts;
8445      opts = null;
8446      times = DEFAULT_TIMES;
8447    } else {
8448      callback = callback || noop;
8449      switch (typeof opts) {
8450        case 'object':
8451          if (typeof opts.errorFilter === func) {
8452            errorFilter = opts.errorFilter;
8453          }
8454          var interval = opts.interval;
8455          switch (typeof interval) {
8456            case func:
8457              intervalFunc = interval;
8458              break;
8459            case 'string':
8460            case 'number':
8461              interval = +interval;
8462              intervalFunc = interval
8463                ? function() {
8464                    return interval;
8465                  }
8466                : function() {
8467                    return DEFAULT_INTERVAL;
8468                  };
8469              break;
8470          }
8471          times = +opts.times || DEFAULT_TIMES;
8472          break;
8473        case 'number':
8474          times = opts || DEFAULT_TIMES;
8475          break;
8476        case 'string':
8477          times = +opts || DEFAULT_TIMES;
8478          break;
8479        default:
8480          throw new Error('Invalid arguments for async.retry');
8481      }
8482    }
8483    if (typeof task !== 'function') {
8484      throw new Error('Invalid arguments for async.retry');
8485    }
8486
8487    if (intervalFunc) {
8488      task(intervalCallback);
8489    } else {
8490      task(simpleCallback);
8491    }
8492
8493    function simpleIterator() {
8494      task(simpleCallback);
8495    }
8496
8497    function simpleCallback(err, res) {
8498      if (++count === times || !err || (errorFilter && !errorFilter(err))) {
8499        if (arguments.length <= 2) {
8500          return callback(err, res);
8501        }
8502        var args = createArray(arguments);
8503        return callback.apply(null, args);
8504      }
8505      simpleIterator();
8506    }
8507
8508    function intervalIterator() {
8509      task(intervalCallback);
8510    }
8511
8512    function intervalCallback(err, res) {
8513      if (++count === times || !err || (errorFilter && !errorFilter(err))) {
8514        if (arguments.length <= 2) {
8515          return callback(err, res);
8516        }
8517        var args = createArray(arguments);
8518        return callback.apply(null, args);
8519      }
8520      setTimeout(intervalIterator, intervalFunc(count));
8521    }
8522  }
8523
8524  function retryable(opts, task) {
8525    if (!task) {
8526      task = opts;
8527      opts = null;
8528    }
8529    return done;
8530
8531    function done() {
8532      var taskFn;
8533      var args = createArray(arguments);
8534      var lastIndex = args.length - 1;
8535      var callback = args[lastIndex];
8536      switch (task.length) {
8537        case 1:
8538          taskFn = task1;
8539          break;
8540        case 2:
8541          taskFn = task2;
8542          break;
8543        case 3:
8544          taskFn = task3;
8545          break;
8546        default:
8547          taskFn = task4;
8548      }
8549      if (opts) {
8550        retry(opts, taskFn, callback);
8551      } else {
8552        retry(taskFn, callback);
8553      }
8554
8555      function task1(done) {
8556        task(done);
8557      }
8558
8559      function task2(done) {
8560        task(args[0], done);
8561      }
8562
8563      function task3(done) {
8564        task(args[0], args[1], done);
8565      }
8566
8567      function task4(callback) {
8568        args[lastIndex] = callback;
8569        task.apply(null, args);
8570      }
8571    }
8572  }
8573
8574  /**
8575   * @memberof async
8576   * @namespace iterator
8577   */
8578  function iterator(tasks) {
8579    var size = 0;
8580    var keys = [];
8581    if (isArray(tasks)) {
8582      size = tasks.length;
8583    } else {
8584      keys = nativeKeys(tasks);
8585      size = keys.length;
8586    }
8587    return makeCallback(0);
8588
8589    function makeCallback(index) {
8590      var fn = function() {
8591        if (size) {
8592          var key = keys[index] || index;
8593          tasks[key].apply(null, createArray(arguments));
8594        }
8595        return fn.next();
8596      };
8597      fn.next = function() {
8598        return index < size - 1 ? makeCallback(index + 1) : null;
8599      };
8600      return fn;
8601    }
8602  }
8603
8604  /**
8605   * @memberof async
8606   * @namespace apply
8607   */
8608  function apply(func) {
8609    switch (arguments.length) {
8610      case 0:
8611      case 1:
8612        return func;
8613      case 2:
8614        return func.bind(null, arguments[1]);
8615      case 3:
8616        return func.bind(null, arguments[1], arguments[2]);
8617      case 4:
8618        return func.bind(null, arguments[1], arguments[2], arguments[3]);
8619      case 5:
8620        return func.bind(null, arguments[1], arguments[2], arguments[3], arguments[4]);
8621      default:
8622        var size = arguments.length;
8623        var index = 0;
8624        var args = Array(size);
8625        args[index] = null;
8626        while (++index < size) {
8627          args[index] = arguments[index];
8628        }
8629        return func.bind.apply(func, args);
8630    }
8631  }
8632
8633  /**
8634   * @memberof async
8635   * @namespace timeout
8636   * @param {Function} func
8637   * @param {number} millisec
8638   * @param {*} info
8639   */
8640  function timeout(func, millisec, info) {
8641    var callback, timer;
8642    return wrappedFunc;
8643
8644    function wrappedFunc() {
8645      timer = setTimeout(timeoutCallback, millisec);
8646      var args = createArray(arguments);
8647      var lastIndex = args.length - 1;
8648      callback = args[lastIndex];
8649      args[lastIndex] = injectedCallback;
8650      simpleApply(func, args);
8651    }
8652
8653    function timeoutCallback() {
8654      var name = func.name || 'anonymous';
8655      var err = new Error('Callback function "' + name + '" timed out.');
8656      err.code = 'ETIMEDOUT';
8657      if (info) {
8658        err.info = info;
8659      }
8660      timer = null;
8661      callback(err);
8662    }
8663
8664    function injectedCallback() {
8665      if (timer !== null) {
8666        simpleApply(callback, createArray(arguments));
8667        clearTimeout(timer);
8668      }
8669    }
8670
8671    function simpleApply(func, args) {
8672      switch (args.length) {
8673        case 0:
8674          func();
8675          break;
8676        case 1:
8677          func(args[0]);
8678          break;
8679        case 2:
8680          func(args[0], args[1]);
8681          break;
8682        default:
8683          func.apply(null, args);
8684          break;
8685      }
8686    }
8687  }
8688
8689  /**
8690   * @memberof async
8691   * @namespace times
8692   * @param {number} n - n >= 1
8693   * @param {Function} iterator
8694   * @param {Function} callback
8695   * @example
8696   *
8697   * var iterator = function(n, done) {
8698   *   done(null, n);
8699   * };
8700   * async.times(4, iterator, function(err, res) {
8701   *   console.log(res); // [0, 1, 2, 3];
8702   * });
8703   *
8704   */
8705  function times(n, iterator, callback) {
8706    callback = callback || noop;
8707    n = +n;
8708    if (isNaN(n) || n < 1) {
8709      return callback(null, []);
8710    }
8711    var result = Array(n);
8712    timesSync(n, iterate);
8713
8714    function iterate(num) {
8715      iterator(num, createCallback(num));
8716    }
8717
8718    function createCallback(index) {
8719      return function(err, res) {
8720        if (index === null) {
8721          throwError();
8722        }
8723        result[index] = res;
8724        index = null;
8725        if (err) {
8726          callback(err);
8727          callback = noop;
8728        } else if (--n === 0) {
8729          callback(null, result);
8730        }
8731      };
8732    }
8733  }
8734
8735  /**
8736   * @memberof async
8737   * @namespace timesSeries
8738   * @param {number} n - n >= 1
8739   * @param {Function} iterator
8740   * @param {Function} callback
8741   * @example
8742   *
8743   * var iterator = function(n, done) {
8744   *   done(null, n);
8745   * };
8746   * async.timesSeries(4, iterator, function(err, res) {
8747   *   console.log(res); // [0, 1, 2, 3];
8748   * });
8749   *
8750   */
8751  function timesSeries(n, iterator, callback) {
8752    callback = callback || noop;
8753    n = +n;
8754    if (isNaN(n) || n < 1) {
8755      return callback(null, []);
8756    }
8757    var result = Array(n);
8758    var sync = false;
8759    var completed = 0;
8760    iterate();
8761
8762    function iterate() {
8763      iterator(completed, done);
8764    }
8765
8766    function done(err, res) {
8767      result[completed] = res;
8768      if (err) {
8769        callback(err);
8770        callback = throwError;
8771      } else if (++completed >= n) {
8772        callback(null, result);
8773        callback = throwError;
8774      } else if (sync) {
8775        nextTick(iterate);
8776      } else {
8777        sync = true;
8778        iterate();
8779      }
8780      sync = false;
8781    }
8782  }
8783
8784  /**
8785   * @memberof async
8786   * @namespace timesLimit
8787   * @param {number} n - n >= 1
8788   * @param {number} limit - n >= 1
8789   * @param {Function} iterator
8790   * @param {Function} callback
8791   * @example
8792   *
8793   * var iterator = function(n, done) {
8794   *   done(null, n);
8795   * };
8796   * async.timesLimit(4, 2, iterator, function(err, res) {
8797   *   console.log(res); // [0, 1, 2, 3];
8798   * });
8799   *
8800   */
8801  function timesLimit(n, limit, iterator, callback) {
8802    callback = callback || noop;
8803    n = +n;
8804    if (isNaN(n) || n < 1 || isNaN(limit) || limit < 1) {
8805      return callback(null, []);
8806    }
8807    var result = Array(n);
8808    var sync = false;
8809    var started = 0;
8810    var completed = 0;
8811    timesSync(limit > n ? n : limit, iterate);
8812
8813    function iterate() {
8814      var index = started++;
8815      if (index < n) {
8816        iterator(index, createCallback(index));
8817      }
8818    }
8819
8820    function createCallback(index) {
8821      return function(err, res) {
8822        if (index === null) {
8823          throwError();
8824        }
8825        result[index] = res;
8826        index = null;
8827        if (err) {
8828          callback(err);
8829          callback = noop;
8830        } else if (++completed >= n) {
8831          callback(null, result);
8832          callback = throwError;
8833        } else if (sync) {
8834          nextTick(iterate);
8835        } else {
8836          sync = true;
8837          iterate();
8838        }
8839        sync = false;
8840      };
8841    }
8842  }
8843
8844  /**
8845   * @memberof async
8846   * @namespace race
8847   * @param {Array|Object} tasks - functions
8848   * @param {Function} callback
8849   * @example
8850   *
8851   * // array
8852   * var called = 0;
8853   * var tasks = [
8854   *   function(done) {
8855   *     setTimeout(function() {
8856   *       called++;
8857   *       done(null, '1');
8858   *     }, 30);
8859   *   },
8860   *   function(done) {
8861   *     setTimeout(function() {
8862   *       called++;
8863   *       done(null, '2');
8864   *     }, 20);
8865   *   },
8866   *   function(done) {
8867   *     setTimeout(function() {
8868   *       called++;
8869   *       done(null, '3');
8870   *     }, 10);
8871   *   }
8872   * ];
8873   * async.race(tasks, function(err, res) {
8874   *   console.log(res); // '3'
8875   *   console.log(called); // 1
8876   *   setTimeout(function() {
8877   *     console.log(called); // 3
8878   *   }, 50);
8879   * });
8880   *
8881   * @example
8882   *
8883   * // object
8884   * var called = 0;
8885   * var tasks = {
8886   *   'test1': function(done) {
8887   *     setTimeout(function() {
8888   *       called++;
8889   *       done(null, '1');
8890   *     }, 30);
8891   *   },
8892   *   'test2': function(done) {
8893   *     setTimeout(function() {
8894   *       called++;
8895   *       done(null, '2');
8896   *     }, 20);
8897   *   },
8898   *   'test3': function(done) {
8899   *     setTimeout(function() {
8900   *       called++;
8901   *       done(null, '3');
8902   *     }, 10);
8903   *   }
8904   * };
8905   * async.race(tasks, function(err, res) {
8906   *   console.log(res); // '3'
8907   *   console.log(called); // 1
8908   *   setTimeout(function() {
8909   *     console.log(called); // 3
8910   *     done();
8911   *   }, 50);
8912   * });
8913   *
8914   */
8915  function race(tasks, callback) {
8916    callback = once(callback || noop);
8917    var size, keys;
8918    var index = -1;
8919    if (isArray(tasks)) {
8920      size = tasks.length;
8921      while (++index < size) {
8922        tasks[index](callback);
8923      }
8924    } else if (tasks && typeof tasks === obj) {
8925      keys = nativeKeys(tasks);
8926      size = keys.length;
8927      while (++index < size) {
8928        tasks[keys[index]](callback);
8929      }
8930    } else {
8931      return callback(new TypeError('First argument to race must be a collection of functions'));
8932    }
8933    if (!size) {
8934      callback(null);
8935    }
8936  }
8937
8938  /**
8939   * @memberof async
8940   * @namespace memoize
8941   */
8942  function memoize(fn, hasher) {
8943    hasher =
8944      hasher ||
8945      function(hash) {
8946        return hash;
8947      };
8948
8949    var memo = {};
8950    var queues = {};
8951    var memoized = function() {
8952      var args = createArray(arguments);
8953      var callback = args.pop();
8954      var key = hasher.apply(null, args);
8955      if (has(memo, key)) {
8956        nextTick(function() {
8957          callback.apply(null, memo[key]);
8958        });
8959        return;
8960      }
8961      if (has(queues, key)) {
8962        return queues[key].push(callback);
8963      }
8964
8965      queues[key] = [callback];
8966      args.push(done);
8967      fn.apply(null, args);
8968
8969      function done(err) {
8970        var args = createArray(arguments);
8971        if (!err) {
8972          memo[key] = args;
8973        }
8974        var q = queues[key];
8975        delete queues[key];
8976
8977        var i = -1;
8978        var size = q.length;
8979        while (++i < size) {
8980          q[i].apply(null, args);
8981        }
8982      }
8983    };
8984    memoized.memo = memo;
8985    memoized.unmemoized = fn;
8986    return memoized;
8987  }
8988
8989  /**
8990   * @memberof async
8991   * @namespace unmemoize
8992   */
8993  function unmemoize(fn) {
8994    return function() {
8995      return (fn.unmemoized || fn).apply(null, arguments);
8996    };
8997  }
8998
8999  /**
9000   * @memberof async
9001   * @namespace ensureAsync
9002   */
9003  function ensureAsync(fn) {
9004    return function(/* ...args, callback */) {
9005      var args = createArray(arguments);
9006      var lastIndex = args.length - 1;
9007      var callback = args[lastIndex];
9008      var sync = true;
9009      args[lastIndex] = done;
9010      fn.apply(this, args);
9011      sync = false;
9012
9013      function done() {
9014        var innerArgs = createArray(arguments);
9015        if (sync) {
9016          nextTick(function() {
9017            callback.apply(null, innerArgs);
9018          });
9019        } else {
9020          callback.apply(null, innerArgs);
9021        }
9022      }
9023    };
9024  }
9025
9026  /**
9027   * @memberof async
9028   * @namespace constant
9029   */
9030  function constant(/* values... */) {
9031    var args = [null].concat(createArray(arguments));
9032    return function(callback) {
9033      callback = arguments[arguments.length - 1];
9034      callback.apply(this, args);
9035    };
9036  }
9037
9038  function asyncify(fn) {
9039    return function(/* args..., callback */) {
9040      var args = createArray(arguments);
9041      var callback = args.pop();
9042      var result;
9043      try {
9044        result = fn.apply(this, args);
9045      } catch (e) {
9046        return callback(e);
9047      }
9048      if (result && typeof result.then === func) {
9049        result.then(
9050          function(value) {
9051            invokeCallback(callback, null, value);
9052          },
9053          function(err) {
9054            invokeCallback(callback, err && err.message ? err : new Error(err));
9055          }
9056        );
9057      } else {
9058        callback(null, result);
9059      }
9060    };
9061  }
9062
9063  function invokeCallback(callback, err, value) {
9064    try {
9065      callback(err, value);
9066    } catch (e) {
9067      nextTick(rethrow, e);
9068    }
9069  }
9070
9071  function rethrow(error) {
9072    throw error;
9073  }
9074
9075  /**
9076   * @memberof async
9077   * @namespace reflect
9078   * @param {Function} func
9079   * @return {Function}
9080   */
9081  function reflect(func) {
9082    return function(/* args..., callback */) {
9083      var callback;
9084      switch (arguments.length) {
9085        case 1:
9086          callback = arguments[0];
9087          return func(done);
9088        case 2:
9089          callback = arguments[1];
9090          return func(arguments[0], done);
9091        default:
9092          var args = createArray(arguments);
9093          var lastIndex = args.length - 1;
9094          callback = args[lastIndex];
9095          args[lastIndex] = done;
9096          func.apply(this, args);
9097      }
9098
9099      function done(err, res) {
9100        if (err) {
9101          return callback(null, {
9102            error: err
9103          });
9104        }
9105        if (arguments.length > 2) {
9106          res = slice(arguments, 1);
9107        }
9108        callback(null, {
9109          value: res
9110        });
9111      }
9112    };
9113  }
9114
9115  /**
9116   * @memberof async
9117   * @namespace reflectAll
9118   * @param {Array[]|Object} tasks
9119   * @return {Function}
9120   */
9121  function reflectAll(tasks) {
9122    var newTasks, keys;
9123    if (isArray(tasks)) {
9124      newTasks = Array(tasks.length);
9125      arrayEachSync(tasks, iterate);
9126    } else if (tasks && typeof tasks === obj) {
9127      keys = nativeKeys(tasks);
9128      newTasks = {};
9129      baseEachSync(tasks, iterate, keys);
9130    }
9131    return newTasks;
9132
9133    function iterate(func, key) {
9134      newTasks[key] = reflect(func);
9135    }
9136  }
9137
9138  /**
9139   * @memberof async
9140   * @namespace createLogger
9141   */
9142  function createLogger(name) {
9143    return function(fn) {
9144      var args = slice(arguments, 1);
9145      args.push(done);
9146      fn.apply(null, args);
9147    };
9148
9149    function done(err) {
9150      if (typeof console === obj) {
9151        if (err) {
9152          if (console.error) {
9153            console.error(err);
9154          }
9155          return;
9156        }
9157        if (console[name]) {
9158          var args = slice(arguments, 1);
9159          arrayEachSync(args, function(arg) {
9160            console[name](arg);
9161          });
9162        }
9163      }
9164    }
9165  }
9166
9167  /**
9168   * @memberof async
9169   * @namespace safe
9170   */
9171  function safe() {
9172    createImmediate();
9173    return exports;
9174  }
9175
9176  /**
9177   * @memberof async
9178   * @namespace fast
9179   */
9180  function fast() {
9181    createImmediate(false);
9182    return exports;
9183  }
9184});
9185