Initial commit
[yaffs-website] / node_modules / grunt-contrib-sass / node_modules / async / lib / async.js
1 /*!
2  * async
3  * https://github.com/caolan/async
4  *
5  * Copyright 2010-2014 Caolan McMahon
6  * Released under the MIT license
7  */
8 /*jshint onevar: false, indent:4 */
9 /*global setImmediate: false, setTimeout: false, console: false */
10 (function () {
11
12     var async = {};
13
14     // global on the server, window in the browser
15     var root, previous_async;
16
17     root = this;
18     if (root != null) {
19       previous_async = root.async;
20     }
21
22     async.noConflict = function () {
23         root.async = previous_async;
24         return async;
25     };
26
27     function only_once(fn) {
28         var called = false;
29         return function() {
30             if (called) throw new Error("Callback was already called.");
31             called = true;
32             fn.apply(root, arguments);
33         }
34     }
35
36     //// cross-browser compatiblity functions ////
37
38     var _toString = Object.prototype.toString;
39
40     var _isArray = Array.isArray || function (obj) {
41         return _toString.call(obj) === '[object Array]';
42     };
43
44     var _each = function (arr, iterator) {
45         for (var i = 0; i < arr.length; i += 1) {
46             iterator(arr[i], i, arr);
47         }
48     };
49
50     var _map = function (arr, iterator) {
51         if (arr.map) {
52             return arr.map(iterator);
53         }
54         var results = [];
55         _each(arr, function (x, i, a) {
56             results.push(iterator(x, i, a));
57         });
58         return results;
59     };
60
61     var _reduce = function (arr, iterator, memo) {
62         if (arr.reduce) {
63             return arr.reduce(iterator, memo);
64         }
65         _each(arr, function (x, i, a) {
66             memo = iterator(memo, x, i, a);
67         });
68         return memo;
69     };
70
71     var _keys = function (obj) {
72         if (Object.keys) {
73             return Object.keys(obj);
74         }
75         var keys = [];
76         for (var k in obj) {
77             if (obj.hasOwnProperty(k)) {
78                 keys.push(k);
79             }
80         }
81         return keys;
82     };
83
84     //// exported async module functions ////
85
86     //// nextTick implementation with browser-compatible fallback ////
87     if (typeof process === 'undefined' || !(process.nextTick)) {
88         if (typeof setImmediate === 'function') {
89             async.nextTick = function (fn) {
90                 // not a direct alias for IE10 compatibility
91                 setImmediate(fn);
92             };
93             async.setImmediate = async.nextTick;
94         }
95         else {
96             async.nextTick = function (fn) {
97                 setTimeout(fn, 0);
98             };
99             async.setImmediate = async.nextTick;
100         }
101     }
102     else {
103         async.nextTick = process.nextTick;
104         if (typeof setImmediate !== 'undefined') {
105             async.setImmediate = function (fn) {
106               // not a direct alias for IE10 compatibility
107               setImmediate(fn);
108             };
109         }
110         else {
111             async.setImmediate = async.nextTick;
112         }
113     }
114
115     async.each = function (arr, iterator, callback) {
116         callback = callback || function () {};
117         if (!arr.length) {
118             return callback();
119         }
120         var completed = 0;
121         _each(arr, function (x) {
122             iterator(x, only_once(done) );
123         });
124         function done(err) {
125           if (err) {
126               callback(err);
127               callback = function () {};
128           }
129           else {
130               completed += 1;
131               if (completed >= arr.length) {
132                   callback();
133               }
134           }
135         }
136     };
137     async.forEach = async.each;
138
139     async.eachSeries = function (arr, iterator, callback) {
140         callback = callback || function () {};
141         if (!arr.length) {
142             return callback();
143         }
144         var completed = 0;
145         var iterate = function () {
146             iterator(arr[completed], function (err) {
147                 if (err) {
148                     callback(err);
149                     callback = function () {};
150                 }
151                 else {
152                     completed += 1;
153                     if (completed >= arr.length) {
154                         callback();
155                     }
156                     else {
157                         iterate();
158                     }
159                 }
160             });
161         };
162         iterate();
163     };
164     async.forEachSeries = async.eachSeries;
165
166     async.eachLimit = function (arr, limit, iterator, callback) {
167         var fn = _eachLimit(limit);
168         fn.apply(null, [arr, iterator, callback]);
169     };
170     async.forEachLimit = async.eachLimit;
171
172     var _eachLimit = function (limit) {
173
174         return function (arr, iterator, callback) {
175             callback = callback || function () {};
176             if (!arr.length || limit <= 0) {
177                 return callback();
178             }
179             var completed = 0;
180             var started = 0;
181             var running = 0;
182
183             (function replenish () {
184                 if (completed >= arr.length) {
185                     return callback();
186                 }
187
188                 while (running < limit && started < arr.length) {
189                     started += 1;
190                     running += 1;
191                     iterator(arr[started - 1], function (err) {
192                         if (err) {
193                             callback(err);
194                             callback = function () {};
195                         }
196                         else {
197                             completed += 1;
198                             running -= 1;
199                             if (completed >= arr.length) {
200                                 callback();
201                             }
202                             else {
203                                 replenish();
204                             }
205                         }
206                     });
207                 }
208             })();
209         };
210     };
211
212
213     var doParallel = function (fn) {
214         return function () {
215             var args = Array.prototype.slice.call(arguments);
216             return fn.apply(null, [async.each].concat(args));
217         };
218     };
219     var doParallelLimit = function(limit, fn) {
220         return function () {
221             var args = Array.prototype.slice.call(arguments);
222             return fn.apply(null, [_eachLimit(limit)].concat(args));
223         };
224     };
225     var doSeries = function (fn) {
226         return function () {
227             var args = Array.prototype.slice.call(arguments);
228             return fn.apply(null, [async.eachSeries].concat(args));
229         };
230     };
231
232
233     var _asyncMap = function (eachfn, arr, iterator, callback) {
234         arr = _map(arr, function (x, i) {
235             return {index: i, value: x};
236         });
237         if (!callback) {
238             eachfn(arr, function (x, callback) {
239                 iterator(x.value, function (err) {
240                     callback(err);
241                 });
242             });
243         } else {
244             var results = [];
245             eachfn(arr, function (x, callback) {
246                 iterator(x.value, function (err, v) {
247                     results[x.index] = v;
248                     callback(err);
249                 });
250             }, function (err) {
251                 callback(err, results);
252             });
253         }
254     };
255     async.map = doParallel(_asyncMap);
256     async.mapSeries = doSeries(_asyncMap);
257     async.mapLimit = function (arr, limit, iterator, callback) {
258         return _mapLimit(limit)(arr, iterator, callback);
259     };
260
261     var _mapLimit = function(limit) {
262         return doParallelLimit(limit, _asyncMap);
263     };
264
265     // reduce only has a series version, as doing reduce in parallel won't
266     // work in many situations.
267     async.reduce = function (arr, memo, iterator, callback) {
268         async.eachSeries(arr, function (x, callback) {
269             iterator(memo, x, function (err, v) {
270                 memo = v;
271                 callback(err);
272             });
273         }, function (err) {
274             callback(err, memo);
275         });
276     };
277     // inject alias
278     async.inject = async.reduce;
279     // foldl alias
280     async.foldl = async.reduce;
281
282     async.reduceRight = function (arr, memo, iterator, callback) {
283         var reversed = _map(arr, function (x) {
284             return x;
285         }).reverse();
286         async.reduce(reversed, memo, iterator, callback);
287     };
288     // foldr alias
289     async.foldr = async.reduceRight;
290
291     var _filter = function (eachfn, arr, iterator, callback) {
292         var results = [];
293         arr = _map(arr, function (x, i) {
294             return {index: i, value: x};
295         });
296         eachfn(arr, function (x, callback) {
297             iterator(x.value, function (v) {
298                 if (v) {
299                     results.push(x);
300                 }
301                 callback();
302             });
303         }, function (err) {
304             callback(_map(results.sort(function (a, b) {
305                 return a.index - b.index;
306             }), function (x) {
307                 return x.value;
308             }));
309         });
310     };
311     async.filter = doParallel(_filter);
312     async.filterSeries = doSeries(_filter);
313     // select alias
314     async.select = async.filter;
315     async.selectSeries = async.filterSeries;
316
317     var _reject = function (eachfn, arr, iterator, callback) {
318         var results = [];
319         arr = _map(arr, function (x, i) {
320             return {index: i, value: x};
321         });
322         eachfn(arr, function (x, callback) {
323             iterator(x.value, function (v) {
324                 if (!v) {
325                     results.push(x);
326                 }
327                 callback();
328             });
329         }, function (err) {
330             callback(_map(results.sort(function (a, b) {
331                 return a.index - b.index;
332             }), function (x) {
333                 return x.value;
334             }));
335         });
336     };
337     async.reject = doParallel(_reject);
338     async.rejectSeries = doSeries(_reject);
339
340     var _detect = function (eachfn, arr, iterator, main_callback) {
341         eachfn(arr, function (x, callback) {
342             iterator(x, function (result) {
343                 if (result) {
344                     main_callback(x);
345                     main_callback = function () {};
346                 }
347                 else {
348                     callback();
349                 }
350             });
351         }, function (err) {
352             main_callback();
353         });
354     };
355     async.detect = doParallel(_detect);
356     async.detectSeries = doSeries(_detect);
357
358     async.some = function (arr, iterator, main_callback) {
359         async.each(arr, function (x, callback) {
360             iterator(x, function (v) {
361                 if (v) {
362                     main_callback(true);
363                     main_callback = function () {};
364                 }
365                 callback();
366             });
367         }, function (err) {
368             main_callback(false);
369         });
370     };
371     // any alias
372     async.any = async.some;
373
374     async.every = function (arr, iterator, main_callback) {
375         async.each(arr, function (x, callback) {
376             iterator(x, function (v) {
377                 if (!v) {
378                     main_callback(false);
379                     main_callback = function () {};
380                 }
381                 callback();
382             });
383         }, function (err) {
384             main_callback(true);
385         });
386     };
387     // all alias
388     async.all = async.every;
389
390     async.sortBy = function (arr, iterator, callback) {
391         async.map(arr, function (x, callback) {
392             iterator(x, function (err, criteria) {
393                 if (err) {
394                     callback(err);
395                 }
396                 else {
397                     callback(null, {value: x, criteria: criteria});
398                 }
399             });
400         }, function (err, results) {
401             if (err) {
402                 return callback(err);
403             }
404             else {
405                 var fn = function (left, right) {
406                     var a = left.criteria, b = right.criteria;
407                     return a < b ? -1 : a > b ? 1 : 0;
408                 };
409                 callback(null, _map(results.sort(fn), function (x) {
410                     return x.value;
411                 }));
412             }
413         });
414     };
415
416     async.auto = function (tasks, callback) {
417         callback = callback || function () {};
418         var keys = _keys(tasks);
419         var remainingTasks = keys.length
420         if (!remainingTasks) {
421             return callback();
422         }
423
424         var results = {};
425
426         var listeners = [];
427         var addListener = function (fn) {
428             listeners.unshift(fn);
429         };
430         var removeListener = function (fn) {
431             for (var i = 0; i < listeners.length; i += 1) {
432                 if (listeners[i] === fn) {
433                     listeners.splice(i, 1);
434                     return;
435                 }
436             }
437         };
438         var taskComplete = function () {
439             remainingTasks--
440             _each(listeners.slice(0), function (fn) {
441                 fn();
442             });
443         };
444
445         addListener(function () {
446             if (!remainingTasks) {
447                 var theCallback = callback;
448                 // prevent final callback from calling itself if it errors
449                 callback = function () {};
450
451                 theCallback(null, results);
452             }
453         });
454
455         _each(keys, function (k) {
456             var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
457             var taskCallback = function (err) {
458                 var args = Array.prototype.slice.call(arguments, 1);
459                 if (args.length <= 1) {
460                     args = args[0];
461                 }
462                 if (err) {
463                     var safeResults = {};
464                     _each(_keys(results), function(rkey) {
465                         safeResults[rkey] = results[rkey];
466                     });
467                     safeResults[k] = args;
468                     callback(err, safeResults);
469                     // stop subsequent errors hitting callback multiple times
470                     callback = function () {};
471                 }
472                 else {
473                     results[k] = args;
474                     async.setImmediate(taskComplete);
475                 }
476             };
477             var requires = task.slice(0, Math.abs(task.length - 1)) || [];
478             var ready = function () {
479                 return _reduce(requires, function (a, x) {
480                     return (a && results.hasOwnProperty(x));
481                 }, true) && !results.hasOwnProperty(k);
482             };
483             if (ready()) {
484                 task[task.length - 1](taskCallback, results);
485             }
486             else {
487                 var listener = function () {
488                     if (ready()) {
489                         removeListener(listener);
490                         task[task.length - 1](taskCallback, results);
491                     }
492                 };
493                 addListener(listener);
494             }
495         });
496     };
497
498     async.retry = function(times, task, callback) {
499         var DEFAULT_TIMES = 5;
500         var attempts = [];
501         // Use defaults if times not passed
502         if (typeof times === 'function') {
503             callback = task;
504             task = times;
505             times = DEFAULT_TIMES;
506         }
507         // Make sure times is a number
508         times = parseInt(times, 10) || DEFAULT_TIMES;
509         var wrappedTask = function(wrappedCallback, wrappedResults) {
510             var retryAttempt = function(task, finalAttempt) {
511                 return function(seriesCallback) {
512                     task(function(err, result){
513                         seriesCallback(!err || finalAttempt, {err: err, result: result});
514                     }, wrappedResults);
515                 };
516             };
517             while (times) {
518                 attempts.push(retryAttempt(task, !(times-=1)));
519             }
520             async.series(attempts, function(done, data){
521                 data = data[data.length - 1];
522                 (wrappedCallback || callback)(data.err, data.result);
523             });
524         }
525         // If a callback is passed, run this as a controll flow
526         return callback ? wrappedTask() : wrappedTask
527     };
528
529     async.waterfall = function (tasks, callback) {
530         callback = callback || function () {};
531         if (!_isArray(tasks)) {
532           var err = new Error('First argument to waterfall must be an array of functions');
533           return callback(err);
534         }
535         if (!tasks.length) {
536             return callback();
537         }
538         var wrapIterator = function (iterator) {
539             return function (err) {
540                 if (err) {
541                     callback.apply(null, arguments);
542                     callback = function () {};
543                 }
544                 else {
545                     var args = Array.prototype.slice.call(arguments, 1);
546                     var next = iterator.next();
547                     if (next) {
548                         args.push(wrapIterator(next));
549                     }
550                     else {
551                         args.push(callback);
552                     }
553                     async.setImmediate(function () {
554                         iterator.apply(null, args);
555                     });
556                 }
557             };
558         };
559         wrapIterator(async.iterator(tasks))();
560     };
561
562     var _parallel = function(eachfn, tasks, callback) {
563         callback = callback || function () {};
564         if (_isArray(tasks)) {
565             eachfn.map(tasks, function (fn, callback) {
566                 if (fn) {
567                     fn(function (err) {
568                         var args = Array.prototype.slice.call(arguments, 1);
569                         if (args.length <= 1) {
570                             args = args[0];
571                         }
572                         callback.call(null, err, args);
573                     });
574                 }
575             }, callback);
576         }
577         else {
578             var results = {};
579             eachfn.each(_keys(tasks), function (k, callback) {
580                 tasks[k](function (err) {
581                     var args = Array.prototype.slice.call(arguments, 1);
582                     if (args.length <= 1) {
583                         args = args[0];
584                     }
585                     results[k] = args;
586                     callback(err);
587                 });
588             }, function (err) {
589                 callback(err, results);
590             });
591         }
592     };
593
594     async.parallel = function (tasks, callback) {
595         _parallel({ map: async.map, each: async.each }, tasks, callback);
596     };
597
598     async.parallelLimit = function(tasks, limit, callback) {
599         _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
600     };
601
602     async.series = function (tasks, callback) {
603         callback = callback || function () {};
604         if (_isArray(tasks)) {
605             async.mapSeries(tasks, function (fn, callback) {
606                 if (fn) {
607                     fn(function (err) {
608                         var args = Array.prototype.slice.call(arguments, 1);
609                         if (args.length <= 1) {
610                             args = args[0];
611                         }
612                         callback.call(null, err, args);
613                     });
614                 }
615             }, callback);
616         }
617         else {
618             var results = {};
619             async.eachSeries(_keys(tasks), function (k, callback) {
620                 tasks[k](function (err) {
621                     var args = Array.prototype.slice.call(arguments, 1);
622                     if (args.length <= 1) {
623                         args = args[0];
624                     }
625                     results[k] = args;
626                     callback(err);
627                 });
628             }, function (err) {
629                 callback(err, results);
630             });
631         }
632     };
633
634     async.iterator = function (tasks) {
635         var makeCallback = function (index) {
636             var fn = function () {
637                 if (tasks.length) {
638                     tasks[index].apply(null, arguments);
639                 }
640                 return fn.next();
641             };
642             fn.next = function () {
643                 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
644             };
645             return fn;
646         };
647         return makeCallback(0);
648     };
649
650     async.apply = function (fn) {
651         var args = Array.prototype.slice.call(arguments, 1);
652         return function () {
653             return fn.apply(
654                 null, args.concat(Array.prototype.slice.call(arguments))
655             );
656         };
657     };
658
659     var _concat = function (eachfn, arr, fn, callback) {
660         var r = [];
661         eachfn(arr, function (x, cb) {
662             fn(x, function (err, y) {
663                 r = r.concat(y || []);
664                 cb(err);
665             });
666         }, function (err) {
667             callback(err, r);
668         });
669     };
670     async.concat = doParallel(_concat);
671     async.concatSeries = doSeries(_concat);
672
673     async.whilst = function (test, iterator, callback) {
674         if (test()) {
675             iterator(function (err) {
676                 if (err) {
677                     return callback(err);
678                 }
679                 async.whilst(test, iterator, callback);
680             });
681         }
682         else {
683             callback();
684         }
685     };
686
687     async.doWhilst = function (iterator, test, callback) {
688         iterator(function (err) {
689             if (err) {
690                 return callback(err);
691             }
692             var args = Array.prototype.slice.call(arguments, 1);
693             if (test.apply(null, args)) {
694                 async.doWhilst(iterator, test, callback);
695             }
696             else {
697                 callback();
698             }
699         });
700     };
701
702     async.until = function (test, iterator, callback) {
703         if (!test()) {
704             iterator(function (err) {
705                 if (err) {
706                     return callback(err);
707                 }
708                 async.until(test, iterator, callback);
709             });
710         }
711         else {
712             callback();
713         }
714     };
715
716     async.doUntil = function (iterator, test, callback) {
717         iterator(function (err) {
718             if (err) {
719                 return callback(err);
720             }
721             var args = Array.prototype.slice.call(arguments, 1);
722             if (!test.apply(null, args)) {
723                 async.doUntil(iterator, test, callback);
724             }
725             else {
726                 callback();
727             }
728         });
729     };
730
731     async.queue = function (worker, concurrency) {
732         if (concurrency === undefined) {
733             concurrency = 1;
734         }
735         function _insert(q, data, pos, callback) {
736           if (!q.started){
737             q.started = true;
738           }
739           if (!_isArray(data)) {
740               data = [data];
741           }
742           if(data.length == 0) {
743              // call drain immediately if there are no tasks
744              return async.setImmediate(function() {
745                  if (q.drain) {
746                      q.drain();
747                  }
748              });
749           }
750           _each(data, function(task) {
751               var item = {
752                   data: task,
753                   callback: typeof callback === 'function' ? callback : null
754               };
755
756               if (pos) {
757                 q.tasks.unshift(item);
758               } else {
759                 q.tasks.push(item);
760               }
761
762               if (q.saturated && q.tasks.length === q.concurrency) {
763                   q.saturated();
764               }
765               async.setImmediate(q.process);
766           });
767         }
768
769         var workers = 0;
770         var q = {
771             tasks: [],
772             concurrency: concurrency,
773             saturated: null,
774             empty: null,
775             drain: null,
776             started: false,
777             paused: false,
778             push: function (data, callback) {
779               _insert(q, data, false, callback);
780             },
781             kill: function () {
782               q.drain = null;
783               q.tasks = [];
784             },
785             unshift: function (data, callback) {
786               _insert(q, data, true, callback);
787             },
788             process: function () {
789                 if (!q.paused && workers < q.concurrency && q.tasks.length) {
790                     var task = q.tasks.shift();
791                     if (q.empty && q.tasks.length === 0) {
792                         q.empty();
793                     }
794                     workers += 1;
795                     var next = function () {
796                         workers -= 1;
797                         if (task.callback) {
798                             task.callback.apply(task, arguments);
799                         }
800                         if (q.drain && q.tasks.length + workers === 0) {
801                             q.drain();
802                         }
803                         q.process();
804                     };
805                     var cb = only_once(next);
806                     worker(task.data, cb);
807                 }
808             },
809             length: function () {
810                 return q.tasks.length;
811             },
812             running: function () {
813                 return workers;
814             },
815             idle: function() {
816                 return q.tasks.length + workers === 0;
817             },
818             pause: function () {
819                 if (q.paused === true) { return; }
820                 q.paused = true;
821             },
822             resume: function () {
823                 if (q.paused === false) { return; }
824                 q.paused = false;
825                 // Need to call q.process once per concurrent
826                 // worker to preserve full concurrency after pause
827                 for (var w = 1; w <= q.concurrency; w++) {
828                     async.setImmediate(q.process);
829                 }
830             }
831         };
832         return q;
833     };
834
835     async.priorityQueue = function (worker, concurrency) {
836
837         function _compareTasks(a, b){
838           return a.priority - b.priority;
839         };
840
841         function _binarySearch(sequence, item, compare) {
842           var beg = -1,
843               end = sequence.length - 1;
844           while (beg < end) {
845             var mid = beg + ((end - beg + 1) >>> 1);
846             if (compare(item, sequence[mid]) >= 0) {
847               beg = mid;
848             } else {
849               end = mid - 1;
850             }
851           }
852           return beg;
853         }
854
855         function _insert(q, data, priority, callback) {
856           if (!q.started){
857             q.started = true;
858           }
859           if (!_isArray(data)) {
860               data = [data];
861           }
862           if(data.length == 0) {
863              // call drain immediately if there are no tasks
864              return async.setImmediate(function() {
865                  if (q.drain) {
866                      q.drain();
867                  }
868              });
869           }
870           _each(data, function(task) {
871               var item = {
872                   data: task,
873                   priority: priority,
874                   callback: typeof callback === 'function' ? callback : null
875               };
876
877               q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
878
879               if (q.saturated && q.tasks.length === q.concurrency) {
880                   q.saturated();
881               }
882               async.setImmediate(q.process);
883           });
884         }
885
886         // Start with a normal queue
887         var q = async.queue(worker, concurrency);
888
889         // Override push to accept second parameter representing priority
890         q.push = function (data, priority, callback) {
891           _insert(q, data, priority, callback);
892         };
893
894         // Remove unshift function
895         delete q.unshift;
896
897         return q;
898     };
899
900     async.cargo = function (worker, payload) {
901         var working     = false,
902             tasks       = [];
903
904         var cargo = {
905             tasks: tasks,
906             payload: payload,
907             saturated: null,
908             empty: null,
909             drain: null,
910             drained: true,
911             push: function (data, callback) {
912                 if (!_isArray(data)) {
913                     data = [data];
914                 }
915                 _each(data, function(task) {
916                     tasks.push({
917                         data: task,
918                         callback: typeof callback === 'function' ? callback : null
919                     });
920                     cargo.drained = false;
921                     if (cargo.saturated && tasks.length === payload) {
922                         cargo.saturated();
923                     }
924                 });
925                 async.setImmediate(cargo.process);
926             },
927             process: function process() {
928                 if (working) return;
929                 if (tasks.length === 0) {
930                     if(cargo.drain && !cargo.drained) cargo.drain();
931                     cargo.drained = true;
932                     return;
933                 }
934
935                 var ts = typeof payload === 'number'
936                             ? tasks.splice(0, payload)
937                             : tasks.splice(0, tasks.length);
938
939                 var ds = _map(ts, function (task) {
940                     return task.data;
941                 });
942
943                 if(cargo.empty) cargo.empty();
944                 working = true;
945                 worker(ds, function () {
946                     working = false;
947
948                     var args = arguments;
949                     _each(ts, function (data) {
950                         if (data.callback) {
951                             data.callback.apply(null, args);
952                         }
953                     });
954
955                     process();
956                 });
957             },
958             length: function () {
959                 return tasks.length;
960             },
961             running: function () {
962                 return working;
963             }
964         };
965         return cargo;
966     };
967
968     var _console_fn = function (name) {
969         return function (fn) {
970             var args = Array.prototype.slice.call(arguments, 1);
971             fn.apply(null, args.concat([function (err) {
972                 var args = Array.prototype.slice.call(arguments, 1);
973                 if (typeof console !== 'undefined') {
974                     if (err) {
975                         if (console.error) {
976                             console.error(err);
977                         }
978                     }
979                     else if (console[name]) {
980                         _each(args, function (x) {
981                             console[name](x);
982                         });
983                     }
984                 }
985             }]));
986         };
987     };
988     async.log = _console_fn('log');
989     async.dir = _console_fn('dir');
990     /*async.info = _console_fn('info');
991     async.warn = _console_fn('warn');
992     async.error = _console_fn('error');*/
993
994     async.memoize = function (fn, hasher) {
995         var memo = {};
996         var queues = {};
997         hasher = hasher || function (x) {
998             return x;
999         };
1000         var memoized = function () {
1001             var args = Array.prototype.slice.call(arguments);
1002             var callback = args.pop();
1003             var key = hasher.apply(null, args);
1004             if (key in memo) {
1005                 async.nextTick(function () {
1006                     callback.apply(null, memo[key]);
1007                 });
1008             }
1009             else if (key in queues) {
1010                 queues[key].push(callback);
1011             }
1012             else {
1013                 queues[key] = [callback];
1014                 fn.apply(null, args.concat([function () {
1015                     memo[key] = arguments;
1016                     var q = queues[key];
1017                     delete queues[key];
1018                     for (var i = 0, l = q.length; i < l; i++) {
1019                       q[i].apply(null, arguments);
1020                     }
1021                 }]));
1022             }
1023         };
1024         memoized.memo = memo;
1025         memoized.unmemoized = fn;
1026         return memoized;
1027     };
1028
1029     async.unmemoize = function (fn) {
1030       return function () {
1031         return (fn.unmemoized || fn).apply(null, arguments);
1032       };
1033     };
1034
1035     async.times = function (count, iterator, callback) {
1036         var counter = [];
1037         for (var i = 0; i < count; i++) {
1038             counter.push(i);
1039         }
1040         return async.map(counter, iterator, callback);
1041     };
1042
1043     async.timesSeries = function (count, iterator, callback) {
1044         var counter = [];
1045         for (var i = 0; i < count; i++) {
1046             counter.push(i);
1047         }
1048         return async.mapSeries(counter, iterator, callback);
1049     };
1050
1051     async.seq = function (/* functions... */) {
1052         var fns = arguments;
1053         return function () {
1054             var that = this;
1055             var args = Array.prototype.slice.call(arguments);
1056             var callback = args.pop();
1057             async.reduce(fns, args, function (newargs, fn, cb) {
1058                 fn.apply(that, newargs.concat([function () {
1059                     var err = arguments[0];
1060                     var nextargs = Array.prototype.slice.call(arguments, 1);
1061                     cb(err, nextargs);
1062                 }]))
1063             },
1064             function (err, results) {
1065                 callback.apply(that, [err].concat(results));
1066             });
1067         };
1068     };
1069
1070     async.compose = function (/* functions... */) {
1071       return async.seq.apply(null, Array.prototype.reverse.call(arguments));
1072     };
1073
1074     var _applyEach = function (eachfn, fns /*args...*/) {
1075         var go = function () {
1076             var that = this;
1077             var args = Array.prototype.slice.call(arguments);
1078             var callback = args.pop();
1079             return eachfn(fns, function (fn, cb) {
1080                 fn.apply(that, args.concat([cb]));
1081             },
1082             callback);
1083         };
1084         if (arguments.length > 2) {
1085             var args = Array.prototype.slice.call(arguments, 2);
1086             return go.apply(this, args);
1087         }
1088         else {
1089             return go;
1090         }
1091     };
1092     async.applyEach = doParallel(_applyEach);
1093     async.applyEachSeries = doSeries(_applyEach);
1094
1095     async.forever = function (fn, callback) {
1096         function next(err) {
1097             if (err) {
1098                 if (callback) {
1099                     return callback(err);
1100                 }
1101                 throw err;
1102             }
1103             fn(next);
1104         }
1105         next();
1106     };
1107
1108     // Node.js
1109     if (typeof module !== 'undefined' && module.exports) {
1110         module.exports = async;
1111     }
1112     // AMD / RequireJS
1113     else if (typeof define !== 'undefined' && define.amd) {
1114         define([], function () {
1115             return async;
1116         });
1117     }
1118     // included directly via <script> tag
1119     else {
1120         root.async = async;
1121     }
1122
1123 }());