diff --git a/LICENSE.md b/LICENSE.md
index 57b6a91d..55a84793 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -226,7 +226,8 @@ https://github.com/mhevery/jasmine-node
## js2xmlparser ##
-js2xmlparser is distributed under the MIT license, which is reproduced above.
+js2xmlparser is distributed under the Apache License 2.0, which is
+included with this package.
Copyright (c) 2012 Michael Kourlas.
@@ -374,7 +375,7 @@ https://github.com/geraintluff/tv4
Underscore.js is distributed under the MIT license, which is reproduced above.
-Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative
+Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors.
The source code for Underscore.js is available at:
diff --git a/lib/jsdoc/src/astbuilder.js b/lib/jsdoc/src/astbuilder.js
index b36e42f6..b5aaf8ef 100644
--- a/lib/jsdoc/src/astbuilder.js
+++ b/lib/jsdoc/src/astbuilder.js
@@ -82,11 +82,13 @@ var parserOptions = exports.parserOptions = {
classes: true,
defaultParams: true,
destructuring: true,
+ experimentalObjectRestSpread: true,
forOf: true,
generators: true,
globalReturn: true,
jsx: false,
modules: true,
+ newTarget: true,
objectLiteralComputedProperties: true,
objectLiteralDuplicateProperties: true,
objectLiteralShorthandMethods: true,
diff --git a/lib/jsdoc/src/syntax.js b/lib/jsdoc/src/syntax.js
index 2b466c4f..942f6a18 100644
--- a/lib/jsdoc/src/syntax.js
+++ b/lib/jsdoc/src/syntax.js
@@ -22,6 +22,8 @@ exports.Syntax = {
DebuggerStatement: 'DebuggerStatement',
DoWhileStatement: 'DoWhileStatement',
EmptyStatement: 'EmptyStatement',
+ ExperimentalRestProperty: 'ExperimentalRestProperty',
+ ExperimentalSpreadProperty: 'ExperimentalSpreadProperty',
ExportAllDeclaration: 'ExportAllDeclaration',
ExportDefaultDeclaration: 'ExportDefaultDeclaration',
ExportNamedDeclaration: 'ExportNamedDeclaration',
@@ -43,6 +45,7 @@ exports.Syntax = {
Literal: 'Literal',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
+ MetaProperty: 'MetaProperty',
MethodDefinition: 'MethodDefinition',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
diff --git a/lib/jsdoc/src/walker.js b/lib/jsdoc/src/walker.js
index 030b8098..02c7febd 100644
--- a/lib/jsdoc/src/walker.js
+++ b/lib/jsdoc/src/walker.js
@@ -163,6 +163,12 @@ walkers[Syntax.DoWhileStatement] = function(node, parent, state, cb) {
walkers[Syntax.EmptyStatement] = leafNode;
+walkers[Syntax.ExperimentalRestProperty] = function(node, parent, state, cb) {
+ cb(node.argument);
+};
+
+walkers[Syntax.ExperimentalSpreadProperty] = walkers[Syntax.ExperimentalRestProperty];
+
walkers[Syntax.ExportAllDeclaration] = function(node, parent, state, cb) {
if (node.source) {
cb(node.source, node, state);
@@ -297,6 +303,8 @@ walkers[Syntax.MemberExpression] = function(node, parent, state, cb) {
}
};
+walkers[Syntax.MetaProperty] = leafNode;
+
walkers[Syntax.MethodDefinition] = function(node, parent, state, cb) {
if (node.key) {
cb(node.key, node, state);
diff --git a/node_modules/async/lib/async.js b/node_modules/async/lib/async.js
old mode 100755
new mode 100644
index 01e8afcc..f3cfb807
--- a/node_modules/async/lib/async.js
+++ b/node_modules/async/lib/async.js
@@ -5,18 +5,32 @@
* Copyright 2010-2014 Caolan McMahon
* Released under the MIT license
*/
-/*jshint onevar: false, indent:4 */
-/*global setImmediate: false, setTimeout: false, console: false */
(function () {
var async = {};
+ function noop() {}
+ function identity(v) {
+ return v;
+ }
+ function toBool(v) {
+ return !!v;
+ }
+ function notId(v) {
+ return !v;
+ }
// global on the server, window in the browser
- var root, previous_async;
+ var previous_async;
+
+ // Establish the root object, `window` (`self`) in the browser, `global`
+ // on the server, or `this` in some virtual machines. We use `self`
+ // instead of `window` for `WebWorker` support.
+ var root = typeof self === 'object' && self.self === self && self ||
+ typeof global === 'object' && global.global === global && global ||
+ this;
- root = this;
if (root != null) {
- previous_async = root.async;
+ previous_async = root.async;
}
async.noConflict = function () {
@@ -25,12 +39,19 @@
};
function only_once(fn) {
- var called = false;
return function() {
- if (called) throw new Error("Callback was already called.");
- called = true;
- fn.apply(root, arguments);
- }
+ if (fn === null) throw new Error("Callback was already called.");
+ fn.apply(this, arguments);
+ fn = null;
+ };
+ }
+
+ function _once(fn) {
+ return function() {
+ if (fn === null) return;
+ fn.apply(this, arguments);
+ fn = null;
+ };
}
//// cross-browser compatiblity functions ////
@@ -41,40 +62,66 @@
return _toString.call(obj) === '[object Array]';
};
- var _each = function (arr, iterator) {
- if (arr.forEach) {
- return arr.forEach(iterator);
- }
- for (var i = 0; i < arr.length; i += 1) {
- iterator(arr[i], i, arr);
- }
- };
+ function _isArrayLike(arr) {
+ return _isArray(arr) || (
+ // has a positive integer length property
+ typeof arr.length === "number" &&
+ arr.length >= 0 &&
+ arr.length % 1 === 0
+ );
+ }
- var _map = function (arr, iterator) {
- if (arr.map) {
- return arr.map(iterator);
- }
- var results = [];
- _each(arr, function (x, i, a) {
- results.push(iterator(x, i, a));
- });
- return results;
- };
+ function _each(coll, iterator) {
+ return _isArrayLike(coll) ?
+ _arrayEach(coll, iterator) :
+ _forEachOf(coll, iterator);
+ }
- var _reduce = function (arr, iterator, memo) {
- if (arr.reduce) {
- return arr.reduce(iterator, memo);
+ function _arrayEach(arr, iterator) {
+ var index = -1,
+ length = arr.length;
+
+ while (++index < length) {
+ iterator(arr[index], index, arr);
}
- _each(arr, function (x, i, a) {
+ }
+
+ function _map(arr, iterator) {
+ var index = -1,
+ length = arr.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iterator(arr[index], index, arr);
+ }
+ return result;
+ }
+
+ function _range(count) {
+ return _map(Array(count), function (v, i) { return i; });
+ }
+
+ function _reduce(arr, iterator, memo) {
+ _arrayEach(arr, function (x, i, a) {
memo = iterator(memo, x, i, a);
});
return memo;
- };
+ }
- var _keys = function (obj) {
- if (Object.keys) {
- return Object.keys(obj);
+ function _forEachOf(object, iterator) {
+ _arrayEach(_keys(object), function (key) {
+ iterator(object[key], key);
+ });
+ }
+
+ function _indexOf(arr, item) {
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] === item) return i;
}
+ return -1;
+ }
+
+ var _keys = Object.keys || function (obj) {
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
@@ -84,311 +131,337 @@
return keys;
};
+ function _keyIterator(coll) {
+ var i = -1;
+ var len;
+ var keys;
+ if (_isArrayLike(coll)) {
+ len = coll.length;
+ return function next() {
+ i++;
+ return i < len ? i : null;
+ };
+ } else {
+ keys = _keys(coll);
+ len = keys.length;
+ return function next() {
+ i++;
+ return i < len ? keys[i] : null;
+ };
+ }
+ }
+
+ // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
+ // This accumulates the arguments passed into an array, after a given index.
+ // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).
+ function _restParam(func, startIndex) {
+ startIndex = startIndex == null ? func.length - 1 : +startIndex;
+ return function() {
+ var length = Math.max(arguments.length - startIndex, 0);
+ var rest = Array(length);
+ for (var index = 0; index < length; index++) {
+ rest[index] = arguments[index + startIndex];
+ }
+ switch (startIndex) {
+ case 0: return func.call(this, rest);
+ case 1: return func.call(this, arguments[0], rest);
+ case 2: return func.call(this, arguments[0], arguments[1], rest);
+ }
+ // Currently unused but handle cases outside of the switch statement:
+ // var args = Array(startIndex + 1);
+ // for (index = 0; index < startIndex; index++) {
+ // args[index] = arguments[index];
+ // }
+ // args[startIndex] = rest;
+ // return func.apply(this, args);
+ };
+ }
+
+ function _withoutIndex(iterator) {
+ return function (value, index, callback) {
+ return iterator(value, callback);
+ };
+ }
+
//// exported async module functions ////
//// nextTick implementation with browser-compatible fallback ////
- if (typeof process === 'undefined' || !(process.nextTick)) {
- if (typeof setImmediate === 'function') {
- async.nextTick = function (fn) {
- // not a direct alias for IE10 compatibility
- setImmediate(fn);
- };
- async.setImmediate = async.nextTick;
- }
- else {
- async.nextTick = function (fn) {
- setTimeout(fn, 0);
- };
- async.setImmediate = async.nextTick;
- }
- }
- else {
- async.nextTick = process.nextTick;
- if (typeof setImmediate !== 'undefined') {
- async.setImmediate = function (fn) {
- // not a direct alias for IE10 compatibility
- setImmediate(fn);
- };
- }
- else {
- async.setImmediate = async.nextTick;
- }
- }
+ // capture the global reference to guard against fakeTimer mocks
+ var _setImmediate = typeof setImmediate === 'function' && setImmediate;
+
+ var _delay = _setImmediate ? function(fn) {
+ // not a direct alias for IE10 compatibility
+ _setImmediate(fn);
+ } : function(fn) {
+ setTimeout(fn, 0);
+ };
+
+ if (typeof process === 'object' && typeof process.nextTick === 'function') {
+ async.nextTick = process.nextTick;
+ } else {
+ async.nextTick = _delay;
+ }
+ async.setImmediate = _setImmediate ? _delay : async.nextTick;
+
+
+ async.forEach =
async.each = function (arr, iterator, callback) {
- callback = callback || function () {};
- if (!arr.length) {
- return callback();
- }
+ return async.eachOf(arr, _withoutIndex(iterator), callback);
+ };
+
+ async.forEachSeries =
+ async.eachSeries = function (arr, iterator, callback) {
+ return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
+ };
+
+
+ async.forEachLimit =
+ async.eachLimit = function (arr, limit, iterator, callback) {
+ return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
+ };
+
+ async.forEachOf =
+ async.eachOf = function (object, iterator, callback) {
+ callback = _once(callback || noop);
+ object = object || [];
+ var size = _isArrayLike(object) ? object.length : _keys(object).length;
var completed = 0;
- _each(arr, function (x) {
- iterator(x, only_once(done) );
+ if (!size) {
+ return callback(null);
+ }
+ _each(object, function (value, key) {
+ iterator(object[key], key, only_once(done));
});
function done(err) {
- if (err) {
- callback(err);
- callback = function () {};
- }
- else {
- completed += 1;
- if (completed >= arr.length) {
- callback();
- }
- }
+ if (err) {
+ callback(err);
+ }
+ else {
+ completed += 1;
+ if (completed >= size) {
+ callback(null);
+ }
+ }
}
};
- async.forEach = async.each;
- async.eachSeries = function (arr, iterator, callback) {
- callback = callback || function () {};
- if (!arr.length) {
- return callback();
- }
- var completed = 0;
- var iterate = function () {
- iterator(arr[completed], function (err) {
+ async.forEachOfSeries =
+ async.eachOfSeries = function (obj, iterator, callback) {
+ callback = _once(callback || noop);
+ obj = obj || [];
+ var nextKey = _keyIterator(obj);
+ var key = nextKey();
+ function iterate() {
+ var sync = true;
+ if (key === null) {
+ return callback(null);
+ }
+ iterator(obj[key], key, only_once(function (err) {
if (err) {
callback(err);
- callback = function () {};
}
else {
- completed += 1;
- if (completed >= arr.length) {
- callback();
- }
- else {
- iterate();
+ key = nextKey();
+ if (key === null) {
+ return callback(null);
+ } else {
+ if (sync) {
+ async.nextTick(iterate);
+ } else {
+ iterate();
+ }
}
}
- });
- };
+ }));
+ sync = false;
+ }
iterate();
};
- async.forEachSeries = async.eachSeries;
- async.eachLimit = function (arr, limit, iterator, callback) {
- var fn = _eachLimit(limit);
- fn.apply(null, [arr, iterator, callback]);
+
+
+ async.forEachOfLimit =
+ async.eachOfLimit = function (obj, limit, iterator, callback) {
+ _eachOfLimit(limit)(obj, iterator, callback);
};
- async.forEachLimit = async.eachLimit;
- var _eachLimit = function (limit) {
+ function _eachOfLimit(limit) {
- return function (arr, iterator, callback) {
- callback = callback || function () {};
- if (!arr.length || limit <= 0) {
- return callback();
+ return function (obj, iterator, callback) {
+ callback = _once(callback || noop);
+ obj = obj || [];
+ var nextKey = _keyIterator(obj);
+ if (limit <= 0) {
+ return callback(null);
}
- var completed = 0;
- var started = 0;
+ var done = false;
var running = 0;
+ var errored = false;
(function replenish () {
- if (completed >= arr.length) {
- return callback();
+ if (done && running <= 0) {
+ return callback(null);
}
- while (running < limit && started < arr.length) {
- started += 1;
+ while (running < limit && !errored) {
+ var key = nextKey();
+ if (key === null) {
+ done = true;
+ if (running <= 0) {
+ callback(null);
+ }
+ return;
+ }
running += 1;
- iterator(arr[started - 1], function (err) {
+ iterator(obj[key], key, only_once(function (err) {
+ running -= 1;
if (err) {
callback(err);
- callback = function () {};
+ errored = true;
}
else {
- completed += 1;
- running -= 1;
- if (completed >= arr.length) {
- callback();
- }
- else {
- replenish();
- }
+ replenish();
}
- });
+ }));
}
})();
};
- };
+ }
- var doParallel = function (fn) {
- return function () {
- var args = Array.prototype.slice.call(arguments);
- return fn.apply(null, [async.each].concat(args));
+ function doParallel(fn) {
+ return function (obj, iterator, callback) {
+ return fn(async.eachOf, obj, iterator, callback);
};
- };
- var doParallelLimit = function(limit, fn) {
- return function () {
- var args = Array.prototype.slice.call(arguments);
- return fn.apply(null, [_eachLimit(limit)].concat(args));
+ }
+ function doParallelLimit(fn) {
+ return function (obj, limit, iterator, callback) {
+ return fn(_eachOfLimit(limit), obj, iterator, callback);
};
- };
- var doSeries = function (fn) {
- return function () {
- var args = Array.prototype.slice.call(arguments);
- return fn.apply(null, [async.eachSeries].concat(args));
+ }
+ function doSeries(fn) {
+ return function (obj, iterator, callback) {
+ return fn(async.eachOfSeries, obj, iterator, callback);
};
- };
+ }
-
- var _asyncMap = function (eachfn, arr, iterator, callback) {
- arr = _map(arr, function (x, i) {
- return {index: i, value: x};
+ function _asyncMap(eachfn, arr, iterator, callback) {
+ callback = _once(callback || noop);
+ var results = [];
+ eachfn(arr, function (value, index, callback) {
+ iterator(value, function (err, v) {
+ results[index] = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
});
- if (!callback) {
- eachfn(arr, function (x, callback) {
- iterator(x.value, function (err) {
- callback(err);
- });
- });
- } else {
- var results = [];
- eachfn(arr, function (x, callback) {
- iterator(x.value, function (err, v) {
- results[x.index] = v;
- callback(err);
- });
- }, function (err) {
- callback(err, results);
- });
- }
- };
+ }
+
async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
- async.mapLimit = function (arr, limit, iterator, callback) {
- return _mapLimit(limit)(arr, iterator, callback);
- };
-
- var _mapLimit = function(limit) {
- return doParallelLimit(limit, _asyncMap);
- };
+ async.mapLimit = doParallelLimit(_asyncMap);
// reduce only has a series version, as doing reduce in parallel won't
// work in many situations.
+ async.inject =
+ async.foldl =
async.reduce = function (arr, memo, iterator, callback) {
- async.eachSeries(arr, function (x, callback) {
+ async.eachOfSeries(arr, function (x, i, callback) {
iterator(memo, x, function (err, v) {
memo = v;
callback(err);
});
}, function (err) {
- callback(err, memo);
+ callback(err || null, memo);
});
};
- // inject alias
- async.inject = async.reduce;
- // foldl alias
- async.foldl = async.reduce;
+ async.foldr =
async.reduceRight = function (arr, memo, iterator, callback) {
- var reversed = _map(arr, function (x) {
- return x;
- }).reverse();
+ var reversed = _map(arr, identity).reverse();
async.reduce(reversed, memo, iterator, callback);
};
- // foldr alias
- async.foldr = async.reduceRight;
- var _filter = function (eachfn, arr, iterator, callback) {
+ function _filter(eachfn, arr, iterator, callback) {
var results = [];
- arr = _map(arr, function (x, i) {
- return {index: i, value: x};
- });
- eachfn(arr, function (x, callback) {
- iterator(x.value, function (v) {
+ eachfn(arr, function (x, index, callback) {
+ iterator(x, function (v) {
if (v) {
- results.push(x);
+ results.push({index: index, value: x});
}
callback();
});
- }, function (err) {
+ }, function () {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
- };
- async.filter = doParallel(_filter);
- async.filterSeries = doSeries(_filter);
- // select alias
- async.select = async.filter;
- async.selectSeries = async.filterSeries;
+ }
- var _reject = function (eachfn, arr, iterator, callback) {
- var results = [];
- arr = _map(arr, function (x, i) {
- return {index: i, value: x};
- });
- eachfn(arr, function (x, callback) {
- iterator(x.value, function (v) {
- if (!v) {
- results.push(x);
- }
- callback();
+ async.select =
+ async.filter = doParallel(_filter);
+
+ async.selectLimit =
+ async.filterLimit = doParallelLimit(_filter);
+
+ async.selectSeries =
+ async.filterSeries = doSeries(_filter);
+
+ function _reject(eachfn, arr, iterator, callback) {
+ _filter(eachfn, arr, function(value, cb) {
+ iterator(value, function(v) {
+ cb(!v);
});
- }, function (err) {
- callback(_map(results.sort(function (a, b) {
- return a.index - b.index;
- }), function (x) {
- return x.value;
- }));
- });
- };
+ }, callback);
+ }
async.reject = doParallel(_reject);
+ async.rejectLimit = doParallelLimit(_reject);
async.rejectSeries = doSeries(_reject);
- var _detect = function (eachfn, arr, iterator, main_callback) {
- eachfn(arr, function (x, callback) {
- iterator(x, function (result) {
- if (result) {
- main_callback(x);
- main_callback = function () {};
- }
- else {
+ function _createTester(eachfn, check, getResult) {
+ return function(arr, limit, iterator, cb) {
+ function done() {
+ if (cb) cb(getResult(false, void 0));
+ }
+ function iteratee(x, _, callback) {
+ if (!cb) return callback();
+ iterator(x, function (v) {
+ if (cb && check(v)) {
+ cb(getResult(true, x));
+ cb = iterator = false;
+ }
callback();
- }
- });
- }, function (err) {
- main_callback();
- });
- };
- async.detect = doParallel(_detect);
- async.detectSeries = doSeries(_detect);
+ });
+ }
+ if (arguments.length > 3) {
+ eachfn(arr, limit, iteratee, done);
+ } else {
+ cb = iterator;
+ iterator = limit;
+ eachfn(arr, iteratee, done);
+ }
+ };
+ }
- async.some = function (arr, iterator, main_callback) {
- async.each(arr, function (x, callback) {
- iterator(x, function (v) {
- if (v) {
- main_callback(true);
- main_callback = function () {};
- }
- callback();
- });
- }, function (err) {
- main_callback(false);
- });
- };
- // any alias
- async.any = async.some;
+ async.any =
+ async.some = _createTester(async.eachOf, toBool, identity);
- async.every = function (arr, iterator, main_callback) {
- async.each(arr, function (x, callback) {
- iterator(x, function (v) {
- if (!v) {
- main_callback(false);
- main_callback = function () {};
- }
- callback();
- });
- }, function (err) {
- main_callback(true);
- });
- };
- // all alias
- async.all = async.every;
+ async.someLimit = _createTester(async.eachOfLimit, toBool, identity);
+
+ async.all =
+ async.every = _createTester(async.eachOf, notId, notId);
+
+ async.everyLimit = _createTester(async.eachOfLimit, notId, notId);
+
+ function _findGetResult(v, x) {
+ return x;
+ }
+ async.detect = _createTester(async.eachOf, identity, _findGetResult);
+ async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
async.sortBy = function (arr, iterator, callback) {
async.map(arr, function (x, callback) {
@@ -405,147 +478,189 @@
return callback(err);
}
else {
- var fn = function (left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- };
- callback(null, _map(results.sort(fn), function (x) {
+ callback(null, _map(results.sort(comparator), function (x) {
return x.value;
}));
}
+
});
+
+ function comparator(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }
};
async.auto = function (tasks, callback) {
- callback = callback || function () {};
+ callback = _once(callback || noop);
var keys = _keys(tasks);
- var remainingTasks = keys.length
+ var remainingTasks = keys.length;
if (!remainingTasks) {
- return callback();
+ return callback(null);
}
var results = {};
var listeners = [];
- var addListener = function (fn) {
+ function addListener(fn) {
listeners.unshift(fn);
- };
- var removeListener = function (fn) {
- for (var i = 0; i < listeners.length; i += 1) {
- if (listeners[i] === fn) {
- listeners.splice(i, 1);
- return;
- }
- }
- };
- var taskComplete = function () {
- remainingTasks--
- _each(listeners.slice(0), function (fn) {
+ }
+ function removeListener(fn) {
+ var idx = _indexOf(listeners, fn);
+ if (idx >= 0) listeners.splice(idx, 1);
+ }
+ function taskComplete() {
+ remainingTasks--;
+ _arrayEach(listeners.slice(0), function (fn) {
fn();
});
- };
+ }
addListener(function () {
if (!remainingTasks) {
- var theCallback = callback;
- // prevent final callback from calling itself if it errors
- callback = function () {};
-
- theCallback(null, results);
+ callback(null, results);
}
});
- _each(keys, function (k) {
+ _arrayEach(keys, function (k) {
var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
- var taskCallback = function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
+ var taskCallback = _restParam(function(err, args) {
if (args.length <= 1) {
args = args[0];
}
if (err) {
var safeResults = {};
- _each(_keys(results), function(rkey) {
- safeResults[rkey] = results[rkey];
+ _forEachOf(results, function(val, rkey) {
+ safeResults[rkey] = val;
});
safeResults[k] = args;
callback(err, safeResults);
- // stop subsequent errors hitting callback multiple times
- callback = function () {};
}
else {
results[k] = args;
async.setImmediate(taskComplete);
}
- };
- var requires = task.slice(0, Math.abs(task.length - 1)) || [];
- var ready = function () {
+ });
+ var requires = task.slice(0, task.length - 1);
+ // prevent dead-locks
+ var len = requires.length;
+ var dep;
+ while (len--) {
+ if (!(dep = tasks[requires[len]])) {
+ throw new Error('Has inexistant dependency');
+ }
+ if (_isArray(dep) && _indexOf(dep, k) >= 0) {
+ throw new Error('Has cyclic dependencies');
+ }
+ }
+ function ready() {
return _reduce(requires, function (a, x) {
return (a && results.hasOwnProperty(x));
}, true) && !results.hasOwnProperty(k);
- };
+ }
if (ready()) {
task[task.length - 1](taskCallback, results);
}
else {
- var listener = function () {
- if (ready()) {
- removeListener(listener);
- task[task.length - 1](taskCallback, results);
- }
- };
addListener(listener);
}
+ function listener() {
+ if (ready()) {
+ removeListener(listener);
+ task[task.length - 1](taskCallback, results);
+ }
+ }
});
};
+
+
async.retry = function(times, task, callback) {
var DEFAULT_TIMES = 5;
+ var DEFAULT_INTERVAL = 0;
+
var attempts = [];
- // Use defaults if times not passed
- if (typeof times === 'function') {
+
+ var opts = {
+ times: DEFAULT_TIMES,
+ interval: DEFAULT_INTERVAL
+ };
+
+ function parseTimes(acc, t){
+ if(typeof t === 'number'){
+ acc.times = parseInt(t, 10) || DEFAULT_TIMES;
+ } else if(typeof t === 'object'){
+ acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
+ acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
+ } else {
+ throw new Error('Unsupported argument type for \'times\': ' + typeof(t));
+ }
+ }
+
+ var length = arguments.length;
+ if (length < 1 || length > 3) {
+ throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
+ } else if (length <= 2 && typeof times === 'function') {
callback = task;
task = times;
- times = DEFAULT_TIMES;
}
- // Make sure times is a number
- times = parseInt(times, 10) || DEFAULT_TIMES;
- var wrappedTask = function(wrappedCallback, wrappedResults) {
- var retryAttempt = function(task, finalAttempt) {
+ if (typeof times !== 'function') {
+ parseTimes(opts, times);
+ }
+ opts.callback = callback;
+ opts.task = task;
+
+ function wrappedTask(wrappedCallback, wrappedResults) {
+ function retryAttempt(task, finalAttempt) {
return function(seriesCallback) {
task(function(err, result){
seriesCallback(!err || finalAttempt, {err: err, result: result});
}, wrappedResults);
};
- };
- while (times) {
- attempts.push(retryAttempt(task, !(times-=1)));
}
+
+ function retryInterval(interval){
+ return function(seriesCallback){
+ setTimeout(function(){
+ seriesCallback(null);
+ }, interval);
+ };
+ }
+
+ while (opts.times) {
+
+ var finalAttempt = !(opts.times-=1);
+ attempts.push(retryAttempt(opts.task, finalAttempt));
+ if(!finalAttempt && opts.interval > 0){
+ attempts.push(retryInterval(opts.interval));
+ }
+ }
+
async.series(attempts, function(done, data){
data = data[data.length - 1];
- (wrappedCallback || callback)(data.err, data.result);
+ (wrappedCallback || opts.callback)(data.err, data.result);
});
}
+
// If a callback is passed, run this as a controll flow
- return callback ? wrappedTask() : wrappedTask
+ return opts.callback ? wrappedTask() : wrappedTask;
};
async.waterfall = function (tasks, callback) {
- callback = callback || function () {};
+ callback = _once(callback || noop);
if (!_isArray(tasks)) {
- var err = new Error('First argument to waterfall must be an array of functions');
- return callback(err);
+ var err = new Error('First argument to waterfall must be an array of functions');
+ return callback(err);
}
if (!tasks.length) {
return callback();
}
- var wrapIterator = function (iterator) {
- return function (err) {
+ function wrapIterator(iterator) {
+ return _restParam(function (err, args) {
if (err) {
- callback.apply(null, arguments);
- callback = function () {};
+ callback.apply(null, [err].concat(args));
}
else {
- var args = Array.prototype.slice.call(arguments, 1);
var next = iterator.next();
if (next) {
args.push(wrapIterator(next));
@@ -553,260 +668,244 @@
else {
args.push(callback);
}
- async.setImmediate(function () {
- iterator.apply(null, args);
- });
+ ensureAsync(iterator).apply(null, args);
}
- };
- };
+ });
+ }
wrapIterator(async.iterator(tasks))();
};
- var _parallel = function(eachfn, tasks, callback) {
- callback = callback || function () {};
- if (_isArray(tasks)) {
- eachfn.map(tasks, function (fn, callback) {
- if (fn) {
- fn(function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
- if (args.length <= 1) {
- args = args[0];
- }
- callback.call(null, err, args);
- });
+ function _parallel(eachfn, tasks, callback) {
+ callback = callback || noop;
+ var results = _isArrayLike(tasks) ? [] : {};
+
+ eachfn(tasks, function (task, key, callback) {
+ task(_restParam(function (err, args) {
+ if (args.length <= 1) {
+ args = args[0];
}
- }, callback);
- }
- else {
- var results = {};
- eachfn.each(_keys(tasks), function (k, callback) {
- tasks[k](function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
- if (args.length <= 1) {
- args = args[0];
- }
- results[k] = args;
- callback(err);
- });
- }, function (err) {
- callback(err, results);
- });
- }
- };
+ results[key] = args;
+ callback(err);
+ }));
+ }, function (err) {
+ callback(err, results);
+ });
+ }
async.parallel = function (tasks, callback) {
- _parallel({ map: async.map, each: async.each }, tasks, callback);
+ _parallel(async.eachOf, tasks, callback);
};
async.parallelLimit = function(tasks, limit, callback) {
- _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+ _parallel(_eachOfLimit(limit), tasks, callback);
};
- async.series = function (tasks, callback) {
- callback = callback || function () {};
- if (_isArray(tasks)) {
- async.mapSeries(tasks, function (fn, callback) {
- if (fn) {
- fn(function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
- if (args.length <= 1) {
- args = args[0];
- }
- callback.call(null, err, args);
- });
- }
- }, callback);
- }
- else {
- var results = {};
- async.eachSeries(_keys(tasks), function (k, callback) {
- tasks[k](function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
- if (args.length <= 1) {
- args = args[0];
- }
- results[k] = args;
- callback(err);
- });
- }, function (err) {
- callback(err, results);
- });
- }
+ async.series = function(tasks, callback) {
+ _parallel(async.eachOfSeries, tasks, callback);
};
async.iterator = function (tasks) {
- var makeCallback = function (index) {
- var fn = function () {
+ function makeCallback(index) {
+ function fn() {
if (tasks.length) {
tasks[index].apply(null, arguments);
}
return fn.next();
- };
+ }
fn.next = function () {
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
};
return fn;
- };
+ }
return makeCallback(0);
};
- async.apply = function (fn) {
- var args = Array.prototype.slice.call(arguments, 1);
- return function () {
+ async.apply = _restParam(function (fn, args) {
+ return _restParam(function (callArgs) {
return fn.apply(
- null, args.concat(Array.prototype.slice.call(arguments))
+ null, args.concat(callArgs)
);
- };
- };
+ });
+ });
- var _concat = function (eachfn, arr, fn, callback) {
- var r = [];
- eachfn(arr, function (x, cb) {
+ function _concat(eachfn, arr, fn, callback) {
+ var result = [];
+ eachfn(arr, function (x, index, cb) {
fn(x, function (err, y) {
- r = r.concat(y || []);
+ result = result.concat(y || []);
cb(err);
});
}, function (err) {
- callback(err, r);
+ callback(err, result);
});
- };
+ }
async.concat = doParallel(_concat);
async.concatSeries = doSeries(_concat);
async.whilst = function (test, iterator, callback) {
+ callback = callback || noop;
if (test()) {
- iterator(function (err) {
+ var next = _restParam(function(err, args) {
if (err) {
- return callback(err);
+ callback(err);
+ } else if (test.apply(this, args)) {
+ iterator(next);
+ } else {
+ callback(null);
}
- async.whilst(test, iterator, callback);
});
- }
- else {
- callback();
+ iterator(next);
+ } else {
+ callback(null);
}
};
async.doWhilst = function (iterator, test, callback) {
- iterator(function (err) {
- if (err) {
- return callback(err);
- }
- var args = Array.prototype.slice.call(arguments, 1);
- if (test.apply(null, args)) {
- async.doWhilst(iterator, test, callback);
- }
- else {
- callback();
- }
- });
+ var calls = 0;
+ return async.whilst(function() {
+ return ++calls <= 1 || test.apply(this, arguments);
+ }, iterator, callback);
};
async.until = function (test, iterator, callback) {
- if (!test()) {
- iterator(function (err) {
- if (err) {
- return callback(err);
- }
- async.until(test, iterator, callback);
- });
- }
- else {
- callback();
- }
+ return async.whilst(function() {
+ return !test.apply(this, arguments);
+ }, iterator, callback);
};
async.doUntil = function (iterator, test, callback) {
- iterator(function (err) {
- if (err) {
- return callback(err);
- }
- var args = Array.prototype.slice.call(arguments, 1);
- if (!test.apply(null, args)) {
- async.doUntil(iterator, test, callback);
- }
- else {
- callback();
- }
- });
+ return async.doWhilst(iterator, function() {
+ return !test.apply(this, arguments);
+ }, callback);
};
- async.queue = function (worker, concurrency) {
- if (concurrency === undefined) {
+ async.during = function (test, iterator, callback) {
+ callback = callback || noop;
+
+ var next = _restParam(function(err, args) {
+ if (err) {
+ callback(err);
+ } else {
+ args.push(check);
+ test.apply(this, args);
+ }
+ });
+
+ var check = function(err, truth) {
+ if (err) {
+ callback(err);
+ } else if (truth) {
+ iterator(next);
+ } else {
+ callback(null);
+ }
+ };
+
+ test(check);
+ };
+
+ async.doDuring = function (iterator, test, callback) {
+ var calls = 0;
+ async.during(function(next) {
+ if (calls++ < 1) {
+ next(null, true);
+ } else {
+ test.apply(this, arguments);
+ }
+ }, iterator, callback);
+ };
+
+ function _queue(worker, concurrency, payload) {
+ if (concurrency == null) {
concurrency = 1;
}
+ else if(concurrency === 0) {
+ throw new Error('Concurrency must not be zero');
+ }
function _insert(q, data, pos, callback) {
- if (!q.started){
+ if (callback != null && typeof callback !== "function") {
+ throw new Error("task callback must be a function");
+ }
q.started = true;
- }
- if (!_isArray(data)) {
- data = [data];
- }
- if(data.length == 0) {
- // call drain immediately if there are no tasks
- return async.setImmediate(function() {
- if (q.drain) {
- q.drain();
- }
- });
- }
- _each(data, function(task) {
- var item = {
- data: task,
- callback: typeof callback === 'function' ? callback : null
- };
+ if (!_isArray(data)) {
+ data = [data];
+ }
+ if(data.length === 0 && q.idle()) {
+ // call drain immediately if there are no tasks
+ return async.setImmediate(function() {
+ q.drain();
+ });
+ }
+ _arrayEach(data, function(task) {
+ var item = {
+ data: task,
+ callback: callback || noop
+ };
- if (pos) {
- q.tasks.unshift(item);
- } else {
- q.tasks.push(item);
- }
+ if (pos) {
+ q.tasks.unshift(item);
+ } else {
+ q.tasks.push(item);
+ }
- if (q.saturated && q.tasks.length === q.concurrency) {
- q.saturated();
- }
- async.setImmediate(q.process);
- });
+ if (q.tasks.length === q.concurrency) {
+ q.saturated();
+ }
+ });
+ async.setImmediate(q.process);
+ }
+ function _next(q, tasks) {
+ return function(){
+ workers -= 1;
+ var args = arguments;
+ _arrayEach(tasks, function (task) {
+ task.callback.apply(task, args);
+ });
+ if (q.tasks.length + workers === 0) {
+ q.drain();
+ }
+ q.process();
+ };
}
var workers = 0;
var q = {
tasks: [],
concurrency: concurrency,
- saturated: null,
- empty: null,
- drain: null,
+ payload: payload,
+ saturated: noop,
+ empty: noop,
+ drain: noop,
started: false,
paused: false,
push: function (data, callback) {
- _insert(q, data, false, callback);
+ _insert(q, data, false, callback);
},
kill: function () {
- q.drain = null;
- q.tasks = [];
+ q.drain = noop;
+ q.tasks = [];
},
unshift: function (data, callback) {
- _insert(q, data, true, callback);
+ _insert(q, data, true, callback);
},
process: function () {
if (!q.paused && workers < q.concurrency && q.tasks.length) {
- var task = q.tasks.shift();
- if (q.empty && q.tasks.length === 0) {
- q.empty();
+ while(workers < q.concurrency && q.tasks.length){
+ var tasks = q.payload ?
+ q.tasks.splice(0, q.payload) :
+ q.tasks.splice(0, q.tasks.length);
+
+ var data = _map(tasks, function (task) {
+ return task.data;
+ });
+
+ if (q.tasks.length === 0) {
+ q.empty();
+ }
+ workers += 1;
+ var cb = only_once(_next(q, tasks));
+ worker(data, cb);
}
- workers += 1;
- var next = function () {
- workers -= 1;
- if (task.callback) {
- task.callback.apply(task, arguments);
- }
- if (q.drain && q.tasks.length + workers === 0) {
- q.drain();
- }
- q.process();
- };
- var cb = only_once(next);
- worker(task.data, cb);
}
},
length: function () {
@@ -819,78 +918,88 @@
return q.tasks.length + workers === 0;
},
pause: function () {
- if (q.paused === true) { return; }
q.paused = true;
- q.process();
},
resume: function () {
if (q.paused === false) { return; }
q.paused = false;
- q.process();
+ var resumeCount = Math.min(q.concurrency, q.tasks.length);
+ // Need to call q.process once per concurrent
+ // worker to preserve full concurrency after pause
+ for (var w = 1; w <= resumeCount; w++) {
+ async.setImmediate(q.process);
+ }
}
};
return q;
- };
-
- async.priorityQueue = function (worker, concurrency) {
-
- function _compareTasks(a, b){
- return a.priority - b.priority;
- };
-
- function _binarySearch(sequence, item, compare) {
- var beg = -1,
- end = sequence.length - 1;
- while (beg < end) {
- var mid = beg + ((end - beg + 1) >>> 1);
- if (compare(item, sequence[mid]) >= 0) {
- beg = mid;
- } else {
- end = mid - 1;
- }
- }
- return beg;
- }
-
- function _insert(q, data, priority, callback) {
- if (!q.started){
- q.started = true;
- }
- if (!_isArray(data)) {
- data = [data];
- }
- if(data.length == 0) {
- // call drain immediately if there are no tasks
- return async.setImmediate(function() {
- if (q.drain) {
- q.drain();
- }
- });
- }
- _each(data, function(task) {
- var item = {
- data: task,
- priority: priority,
- callback: typeof callback === 'function' ? callback : null
- };
-
- q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+ }
- if (q.saturated && q.tasks.length === q.concurrency) {
- q.saturated();
- }
- async.setImmediate(q.process);
- });
+ async.queue = function (worker, concurrency) {
+ var q = _queue(function (items, cb) {
+ worker(items[0], cb);
+ }, concurrency, 1);
+
+ return q;
+ };
+
+ async.priorityQueue = function (worker, concurrency) {
+
+ function _compareTasks(a, b){
+ return a.priority - b.priority;
}
-
+
+ function _binarySearch(sequence, item, compare) {
+ var beg = -1,
+ end = sequence.length - 1;
+ while (beg < end) {
+ var mid = beg + ((end - beg + 1) >>> 1);
+ if (compare(item, sequence[mid]) >= 0) {
+ beg = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return beg;
+ }
+
+ function _insert(q, data, priority, callback) {
+ if (callback != null && typeof callback !== "function") {
+ throw new Error("task callback must be a function");
+ }
+ q.started = true;
+ if (!_isArray(data)) {
+ data = [data];
+ }
+ if(data.length === 0) {
+ // call drain immediately if there are no tasks
+ return async.setImmediate(function() {
+ q.drain();
+ });
+ }
+ _arrayEach(data, function(task) {
+ var item = {
+ data: task,
+ priority: priority,
+ callback: typeof callback === 'function' ? callback : noop
+ };
+
+ q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+
+ if (q.tasks.length === q.concurrency) {
+ q.saturated();
+ }
+ async.setImmediate(q.process);
+ });
+ }
+
// Start with a normal queue
var q = async.queue(worker, concurrency);
-
+
// Override push to accept second parameter representing priority
q.push = function (data, priority, callback) {
- _insert(q, data, priority, callback);
+ _insert(q, data, priority, callback);
};
-
+
// Remove unshift function
delete q.unshift;
@@ -898,78 +1007,12 @@
};
async.cargo = function (worker, payload) {
- var working = false,
- tasks = [];
-
- var cargo = {
- tasks: tasks,
- payload: payload,
- saturated: null,
- empty: null,
- drain: null,
- drained: true,
- push: function (data, callback) {
- if (!_isArray(data)) {
- data = [data];
- }
- _each(data, function(task) {
- tasks.push({
- data: task,
- callback: typeof callback === 'function' ? callback : null
- });
- cargo.drained = false;
- if (cargo.saturated && tasks.length === payload) {
- cargo.saturated();
- }
- });
- async.setImmediate(cargo.process);
- },
- process: function process() {
- if (working) return;
- if (tasks.length === 0) {
- if(cargo.drain && !cargo.drained) cargo.drain();
- cargo.drained = true;
- return;
- }
-
- var ts = typeof payload === 'number'
- ? tasks.splice(0, payload)
- : tasks.splice(0, tasks.length);
-
- var ds = _map(ts, function (task) {
- return task.data;
- });
-
- if(cargo.empty) cargo.empty();
- working = true;
- worker(ds, function () {
- working = false;
-
- var args = arguments;
- _each(ts, function (data) {
- if (data.callback) {
- data.callback.apply(null, args);
- }
- });
-
- process();
- });
- },
- length: function () {
- return tasks.length;
- },
- running: function () {
- return working;
- }
- };
- return cargo;
+ return _queue(worker, 1, payload);
};
- var _console_fn = function (name) {
- return function (fn) {
- var args = Array.prototype.slice.call(arguments, 1);
- fn.apply(null, args.concat([function (err) {
- var args = Array.prototype.slice.call(arguments, 1);
+ function _console_fn(name) {
+ return _restParam(function (fn, args) {
+ fn.apply(null, args.concat([_restParam(function (err, args) {
if (typeof console !== 'undefined') {
if (err) {
if (console.error) {
@@ -977,14 +1020,14 @@
}
}
else if (console[name]) {
- _each(args, function (x) {
+ _arrayEach(args, function (x) {
console[name](x);
});
}
}
- }]));
- };
- };
+ })]));
+ });
+ }
async.log = _console_fn('log');
async.dir = _console_fn('dir');
/*async.info = _console_fn('info');
@@ -994,11 +1037,8 @@
async.memoize = function (fn, hasher) {
var memo = {};
var queues = {};
- hasher = hasher || function (x) {
- return x;
- };
- var memoized = function () {
- var args = Array.prototype.slice.call(arguments);
+ hasher = hasher || identity;
+ var memoized = _restParam(function memoized(args) {
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
@@ -1011,100 +1051,153 @@
}
else {
queues[key] = [callback];
- fn.apply(null, args.concat([function () {
- memo[key] = arguments;
+ fn.apply(null, args.concat([_restParam(function (args) {
+ memo[key] = args;
var q = queues[key];
delete queues[key];
for (var i = 0, l = q.length; i < l; i++) {
- q[i].apply(null, arguments);
+ q[i].apply(null, args);
}
- }]));
+ })]));
}
- };
+ });
memoized.memo = memo;
memoized.unmemoized = fn;
return memoized;
};
async.unmemoize = function (fn) {
- return function () {
- return (fn.unmemoized || fn).apply(null, arguments);
- };
+ return function () {
+ return (fn.unmemoized || fn).apply(null, arguments);
+ };
};
- async.times = function (count, iterator, callback) {
- var counter = [];
- for (var i = 0; i < count; i++) {
- counter.push(i);
- }
- return async.map(counter, iterator, callback);
- };
+ function _times(mapper) {
+ return function (count, iterator, callback) {
+ mapper(_range(count), iterator, callback);
+ };
+ }
- async.timesSeries = function (count, iterator, callback) {
- var counter = [];
- for (var i = 0; i < count; i++) {
- counter.push(i);
- }
- return async.mapSeries(counter, iterator, callback);
+ async.times = _times(async.map);
+ async.timesSeries = _times(async.mapSeries);
+ async.timesLimit = function (count, limit, iterator, callback) {
+ return async.mapLimit(_range(count), limit, iterator, callback);
};
async.seq = function (/* functions... */) {
var fns = arguments;
- return function () {
+ return _restParam(function (args) {
var that = this;
- var args = Array.prototype.slice.call(arguments);
- var callback = args.pop();
+
+ var callback = args[args.length - 1];
+ if (typeof callback == 'function') {
+ args.pop();
+ } else {
+ callback = noop;
+ }
+
async.reduce(fns, args, function (newargs, fn, cb) {
- fn.apply(that, newargs.concat([function () {
- var err = arguments[0];
- var nextargs = Array.prototype.slice.call(arguments, 1);
+ fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
cb(err, nextargs);
- }]))
+ })]));
},
function (err, results) {
callback.apply(that, [err].concat(results));
});
- };
+ });
};
async.compose = function (/* functions... */) {
- return async.seq.apply(null, Array.prototype.reverse.call(arguments));
+ return async.seq.apply(null, Array.prototype.reverse.call(arguments));
};
- var _applyEach = function (eachfn, fns /*args...*/) {
- var go = function () {
- var that = this;
- var args = Array.prototype.slice.call(arguments);
- var callback = args.pop();
- return eachfn(fns, function (fn, cb) {
- fn.apply(that, args.concat([cb]));
- },
- callback);
- };
- if (arguments.length > 2) {
- var args = Array.prototype.slice.call(arguments, 2);
- return go.apply(this, args);
- }
- else {
- return go;
- }
- };
- async.applyEach = doParallel(_applyEach);
- async.applyEachSeries = doSeries(_applyEach);
+
+ function _applyEach(eachfn) {
+ return _restParam(function(fns, args) {
+ var go = _restParam(function(args) {
+ var that = this;
+ var callback = args.pop();
+ return eachfn(fns, function (fn, _, cb) {
+ fn.apply(that, args.concat([cb]));
+ },
+ callback);
+ });
+ if (args.length) {
+ return go.apply(this, args);
+ }
+ else {
+ return go;
+ }
+ });
+ }
+
+ async.applyEach = _applyEach(async.eachOf);
+ async.applyEachSeries = _applyEach(async.eachOfSeries);
+
async.forever = function (fn, callback) {
+ var done = only_once(callback || noop);
+ var task = ensureAsync(fn);
function next(err) {
if (err) {
- if (callback) {
- return callback(err);
- }
- throw err;
+ return done(err);
}
- fn(next);
+ task(next);
}
next();
};
+ function ensureAsync(fn) {
+ return _restParam(function (args) {
+ var callback = args.pop();
+ args.push(function () {
+ var innerArgs = arguments;
+ if (sync) {
+ async.setImmediate(function () {
+ callback.apply(null, innerArgs);
+ });
+ } else {
+ callback.apply(null, innerArgs);
+ }
+ });
+ var sync = true;
+ fn.apply(this, args);
+ sync = false;
+ });
+ }
+
+ async.ensureAsync = ensureAsync;
+
+ async.constant = _restParam(function(values) {
+ var args = [null].concat(values);
+ return function (callback) {
+ return callback.apply(this, args);
+ };
+ });
+
+ async.wrapSync =
+ async.asyncify = function asyncify(func) {
+ return _restParam(function (args) {
+ var callback = args.pop();
+ var result;
+ try {
+ result = func.apply(this, args);
+ } catch (e) {
+ return callback(e);
+ }
+ // if result is Promise object
+ if (typeof result !== 'undefined' && typeof result.then === "function") {
+ result.then(function(value) {
+ callback(null, value);
+ }).catch(function(err) {
+ callback(err.message ? err : new Error(err));
+ });
+ } else {
+ callback(null, result);
+ }
+ });
+ };
+
// Node.js
if (typeof module !== 'undefined' && module.exports) {
module.exports = async;
diff --git a/node_modules/async/package.json b/node_modules/async/package.json
index 78fc84d7..c540f718 100644
--- a/node_modules/async/package.json
+++ b/node_modules/async/package.json
@@ -1,28 +1,41 @@
{
"name": "async",
"description": "Higher-order functions and common patterns for asynchronous code",
- "main": "./lib/async",
+ "main": "lib/async.js",
"author": {
"name": "Caolan McMahon"
},
- "version": "0.9.0",
+ "version": "1.4.0",
+ "keywords": [
+ "async",
+ "callback",
+ "utility",
+ "module"
+ ],
"repository": {
"type": "git",
- "url": "https://github.com/caolan/async.git"
+ "url": "git+https://github.com/caolan/async.git"
},
"bugs": {
"url": "https://github.com/caolan/async/issues"
},
- "licenses": [
- {
- "type": "MIT",
- "url": "https://github.com/caolan/async/raw/master/LICENSE"
- }
- ],
+ "license": "MIT",
"devDependencies": {
+ "benchmark": "github:bestiejs/benchmark.js",
+ "bluebird": "^2.9.32",
+ "coveralls": "^2.11.2",
+ "es6-promise": "^2.3.0",
+ "jscs": "^1.13.1",
+ "jshint": "~2.8.0",
+ "lodash": "^3.9.0",
+ "mkdirp": "~0.5.1",
+ "native-promise-only": "^0.8.0-a",
"nodeunit": ">0.0.0",
- "uglify-js": "1.2.x",
- "nodelint": ">0.0.0"
+ "nyc": "^2.1.0",
+ "rsvp": "^3.0.18",
+ "uglify-js": "~2.4.0",
+ "xyz": "^0.5.0",
+ "yargs": "~3.9.1"
},
"jam": {
"main": "lib/async.js",
@@ -30,16 +43,63 @@
"lib/async.js",
"README.md",
"LICENSE"
+ ],
+ "categories": [
+ "Utilities"
]
},
"scripts": {
- "test": "nodeunit test/test-async.js"
+ "test": "npm run-script lint && nodeunit test/test-async.js",
+ "lint": "jshint lib/*.js test/*.js perf/*.js && jscs lib/*.js test/*.js perf/*.js",
+ "coverage": "nyc npm test && nyc report",
+ "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls"
},
- "readme": "# Async.js\n\n[](https://travis-ci.org/caolan/async)\n\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [Node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns\nfor asynchronous control flow (`parallel`, `series`, `waterfall`…). All these\nfunctions assume you follow the Node.js convention of providing a single\ncallback as the last argument of your `async` function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n\nasync.parallel([\n function(){ ... },\n function(){ ... }\n], callback);\n\nasync.series([\n function(){ ... },\n function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about `bind`, not about `async`. If you are wondering how to\nmake `async` execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n squareExponent: 2,\n square: function(number, callback){ \n var result = Math.pow(number, this.squareExponent);\n setTimeout(function(){\n callback(null, result);\n }, 200);\n }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n // result is [NaN, NaN, NaN]\n // This fails because the `this.squareExponent` expression in the square\n // function is not evaluated in the context of AsyncSquaringLibrary, and is\n // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n // result is [1, 4, 9]\n // With the help of bind we can attach a context to the iterator before\n // passing it to async. Now the square function will be executed in its \n // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (`npm`):\n\n npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. \n\nUsage:\n\n```html\n\n\n```\n\n## Documentation\n\n### Collections\n\n* [`each`](#each)\n* [`eachSeries`](#eachSeries)\n* [`eachLimit`](#eachLimit)\n* [`map`](#map)\n* [`mapSeries`](#mapSeries)\n* [`mapLimit`](#mapLimit)\n* [`filter`](#filter)\n* [`filterSeries`](#filterSeries)\n* [`reject`](#reject)\n* [`rejectSeries`](#rejectSeries)\n* [`reduce`](#reduce)\n* [`reduceRight`](#reduceRight)\n* [`detect`](#detect)\n* [`detectSeries`](#detectSeries)\n* [`sortBy`](#sortBy)\n* [`some`](#some)\n* [`every`](#every)\n* [`concat`](#concat)\n* [`concatSeries`](#concatSeries)\n\n### Control Flow\n\n* [`series`](#seriestasks-callback)\n* [`parallel`](#parallel)\n* [`parallelLimit`](#parallellimittasks-limit-callback)\n* [`whilst`](#whilst)\n* [`doWhilst`](#doWhilst)\n* [`until`](#until)\n* [`doUntil`](#doUntil)\n* [`forever`](#forever)\n* [`waterfall`](#waterfall)\n* [`compose`](#compose)\n* [`seq`](#seq)\n* [`applyEach`](#applyEach)\n* [`applyEachSeries`](#applyEachSeries)\n* [`queue`](#queue)\n* [`priorityQueue`](#priorityQueue)\n* [`cargo`](#cargo)\n* [`auto`](#auto)\n* [`retry`](#retry)\n* [`iterator`](#iterator)\n* [`apply`](#apply)\n* [`nextTick`](#nextTick)\n* [`times`](#times)\n* [`timesSeries`](#timesSeries)\n\n### Utils\n\n* [`memoize`](#memoize)\n* [`unmemoize`](#unmemoize)\n* [`log`](#log)\n* [`dir`](#dir)\n* [`noConflict`](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies the function `iterator` to each item in `arr`, in parallel.\nThe `iterator` is called with an item from the list, and a callback for when it\nhas finished. If the `iterator` passes an error to its `callback`, the main\n`callback` (for the `each` function) is immediately called with the error.\n\nNote, that since this function applies `iterator` to each item in parallel,\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err)` which must be called once it has \n completed. If no error has occured, the `callback` should be run without \n arguments or with an explicit `null` argument.\n* `callback(err)` - A callback which is called when all `iterator` functions\n have finished, or an error occurs.\n\n__Examples__\n\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n```js\n// assuming openFiles is an array of file names \n\nasync.each(openFiles, function( file, callback) {\n \n // Perform operation on file here.\n console.log('Processing file ' + file);\n \n if( file.length > 32 ) {\n console.log('This file name is too long');\n callback('File name too long');\n } else {\n // Do work to process file here\n console.log('File processed');\n callback();\n }\n}, function(err){\n // if any of the file processing produced an error, err would equal that error\n if( err ) {\n // One of the iterations produced an error.\n // All processing will now stop.\n console.log('A file failed to process');\n } else {\n console.log('All files have been processed successfully');\n }\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as [`each`](#each), only `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThis means the `iterator` functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items in `arr` are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err)` which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit `null` argument.\n* `callback(err)` - A callback which is called when all `iterator` functions\n have finished, or an error occurs.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in `arr` through\nthe `iterator` function. The `iterator` is called with an item from `arr` and a\ncallback for when it has finished processing. Each of these callback takes 2 arguments: \nan `error`, and the transformed item from `arr`. If `iterator` passes an error to this \ncallback, the main `callback` (for the `map` function) is immediately called with the error.\n\nNote, that since this function applies the `iterator` to each item in parallel,\nthere is no guarantee that the `iterator` functions will complete in order. \nHowever, the results array will be in the same order as the original `arr`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, transformed)` which must be called once \n it has completed with an error (which can be `null`) and a transformed item.\n* `callback(err, results)` - A callback which is called when all `iterator`\n functions have finished, or an error occurs. Results is an array of the\n transformed items from the `arr`.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as [`map`](#map), only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, transformed)` which must be called once \n it has completed with an error (which can be `null`) and a transformed item.\n* `callback(err, results)` - A callback which is called when all `iterator`\n calls have finished, or an error occurs. The result is an array of the\n transformed items from the original `arr`.\n\n__Example__\n\n```js\nasync.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ `select`\n\nReturns a new array of all the values in `arr` which pass an async truth test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in `arr`.\n The `iterator` is passed a `callback(truthValue)`, which must be called with a \n boolean argument once it has completed.\n* `callback(results)` - A callback which is called after all the `iterator`\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n\n### filterSeries(arr, iterator, callback)\n\n__Alias:__ `selectSeries`\n\nThe same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of [`filter`](#filter). Removes values that pass an `async` truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__Aliases:__ `inject`, `foldl`\n\nReduces `arr` into a single value using an async `iterator` to return\neach successive step. `memo` is the initial state of the reduction. \nThis function only operates in series. \n\nFor performance reasons, it may make sense to split a call to this function into \na parallel map, and then use the normal `Array.prototype.reduce` on the results. \nThis function is for situations where each step in the reduction needs to be async; \nif you can get the data before reducing it, then it's probably a good idea to do so.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `memo` - The initial state of the reduction.\n* `iterator(memo, item, callback)` - A function applied to each item in the\n array to produce the next step in the reduction. The `iterator` is passed a\n `callback(err, reduction)` which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main `callback` is \n immediately called with the error.\n* `callback(err, result)` - A callback which is called after all the `iterator`\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ `foldr`\n\nSame as [`reduce`](#reduce), only operates on `arr` in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in `arr` that passes an async truth test. The\n`iterator` is applied in parallel, meaning the first iterator to return `true` will\nfire the detect `callback` with that result. That means the result might not be\nthe first item in the original `arr` (in terms of order) that passes the test.\n\nIf order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in `arr`.\n The iterator is passed a `callback(truthValue)` which must be called with a \n boolean argument once it has completed.\n* `callback(result)` - A callback which is called as soon as any iterator returns\n `true`, or after all the `iterator` functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value `undefined` if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`\nin series. This means the result is always the first in the original `arr` (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each `arr` value through an async `iterator`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, sortValue)` which must be called once it\n has completed with an error (which can be `null`) and a value to use as the sort\n criteria.\n* `callback(err, results)` - A callback which is called after all the `iterator`\n functions have finished, or an error occurs. Results is the items from\n the original `arr` sorted by the values returned by the `iterator` calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n__Sort Order__\n\nBy modifying the callback parameter the sorting order can be influenced:\n\n```js\n//ascending order\nasync.sortBy([1,9,3,5], function(x, callback){\n callback(err, x);\n}, function(err,result){\n //result callback\n} );\n\n//descending order\nasync.sortBy([1,9,3,5], function(x, callback){\n callback(err, x*-1); //<- x*-1 instead of x, turns the order around\n}, function(err,result){\n //result callback\n} );\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ `any`\n\nReturns `true` if at least one element in the `arr` satisfies an async test.\n_The callback for each iterator call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`. Once any iterator\ncall returns `true`, the main `callback` is immediately called.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in the array\n in parallel. The iterator is passed a callback(truthValue) which must be \n called with a boolean argument once it has completed.\n* `callback(result)` - A callback which is called as soon as any iterator returns\n `true`, or after all the iterator functions have finished. Result will be\n either `true` or `false` depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ `all`\n\nReturns `true` if every element in `arr` satisfies an async test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in the array\n in parallel. The iterator is passed a callback(truthValue) which must be \n called with a boolean argument once it has completed.\n* `callback(result)` - A callback which is called after all the `iterator`\n functions have finished. Result will be either `true` or `false` depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies `iterator` to each item in `arr`, concatenating the results. Returns the\nconcatenated list. The `iterator`s are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of `arr` passed to the `iterator` function.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, results)` which must be called once it \n has completed with an error (which can be `null`) and an array of results.\n* `callback(err, results)` - A callback which is called after all the `iterator`\n functions have finished, or an error occurs. Results is an array containing\n the concatenated results of the `iterator` function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as [`concat`](#concat), but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun the functions in the `tasks` array in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run, and `callback` is immediately called with the value of the error. \nOtherwise, `callback` receives an array of results when `tasks` have completed.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function, and the results will be passed to the final `callback` as an object\ninstead of an array. This can be a more readable way of handling results from\n[`series`](#series).\n\n**Note** that while many implementations preserve the order of object properties, the\n[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) \nexplicitly states that\n\n> The mechanics and order of enumerating the properties is not specified.\n\nSo if you rely on the order in which your series of functions are executed, and want\nthis to work on all platforms, consider using an array. \n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run, each function is passed\n a `callback(err, result)` it must call on completion with an error `err` (which can\n be `null`) and an optional `result` value.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the `task` callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun the `tasks` array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main `callback` is immediately called with the value of the error.\nOnce the `tasks` have completed, the results are passed to the final `callback` as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final `callback` as an object\ninstead of an array. This can be a more readable way of handling results from\n[`parallel`](#parallel).\n\n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run. Each function is passed \n a `callback(err, result)` which it must call on completion with an error `err` \n (which can be `null`) and an optional `result` value.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as [`parallel`](#parallel), only `tasks` are executed in parallel \nwith a maximum of `limit` tasks executing at any time.\n\nNote that the `tasks` are not executed in batches, so there is no guarantee that \nthe first `limit` tasks will complete before any others are started.\n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run, each function is passed \n a `callback(err, result)` it must call on completion with an error `err` (which can\n be `null`) and an optional `result` value.\n* `limit` - The maximum number of `tasks` to run at any time.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the `task` callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,\nor an error occurs.\n\n__Arguments__\n\n* `test()` - synchronous truth test to perform before each execution of `fn`.\n* `fn(callback)` - A function which is called each time `test` passes. The function is\n passed a `callback(err)`, which must be called once it has completed with an \n optional `err` argument.\n* `callback(err)` - A callback which is called after the test fails and repeated\n execution of `fn` has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post-check version of [`whilst`](#whilst). To reflect the difference in \nthe order of operations, the arguments `test` and `fn` are switched. \n\n`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,\nor an error occurs.\n\nThe inverse of [`whilst`](#whilst).\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, errback)\n\nCalls the asynchronous function `fn` with a callback parameter that allows it to\ncall itself again, in series, indefinitely.\n\nIf an error is passed to the callback then `errback` is called with the\nerror, and execution stops, otherwise it will never be called.\n\n```js\nasync.forever(\n function(next) {\n // next is suitable for passing to things that need a callback(err [, whatever]);\n // it will result in this function being called again.\n },\n function(err) {\n // if next is called with a value in its first parameter, it will appear\n // in here as 'err', and execution will stop.\n }\n);\n```\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns the `tasks` array of functions in series, each passing their results to the next in\nthe array. However, if any of the `tasks` pass an error to their own callback, the\nnext function is not executed, and the main `callback` is immediately called with\nthe error.\n\n__Arguments__\n\n* `tasks` - An array of functions to run, each function is passed a \n `callback(err, result1, result2, ...)` it must call on completion. The first\n argument is an error (which can be `null`) and any further arguments will be \n passed as arguments in order to the next task.\n* `callback(err, [results])` - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n // arg1 now equals 'one' and arg2 now equals 'two'\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions `f()`, `g()`, and `h()` would produce the result of\n`f(g(h()))`, only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* `functions...` - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### seq(fn1, fn2...)\n\nVersion of the compose function that is more natural to read.\nEach following function consumes the return value of the latter function. \n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\n// Requires lodash (or underscore), express3 and dresende's orm2.\n// Part of an app, that fetches cats of the logged user.\n// This example uses `seq` function to avoid overnesting and error \n// handling clutter.\napp.get('/cats', function(request, response) {\n function handleError(err, data, callback) {\n if (err) {\n console.error(err);\n response.json({ status: 'error', message: err.message });\n }\n else {\n callback(data);\n }\n }\n var User = request.models.User;\n async.seq(\n _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))\n handleError,\n function(user, fn) {\n user.getCats(fn); // 'getCats' has signature (callback(err, data))\n },\n handleError,\n function(cats) {\n response.json({ status: 'ok', message: 'Cats found', data: cats });\n }\n )(req.session.user_id);\n }\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling \n`callback` after all functions have completed. If you only provide the first\nargument, then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* `fns` - the asynchronous functions to all call with the same arguments\n* `args...` - any number of separate arguments to pass to the function\n* `callback` - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as [`applyEach`](#applyEach) only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a `queue` object with the specified `concurrency`. Tasks added to the\n`queue` are processed in parallel (up to the `concurrency` limit). If all\n`worker`s are in progress, the task is queued until one becomes available. \nOnce a `worker` completes a `task`, that `task`'s callback is called.\n\n__Arguments__\n\n* `worker(task, callback)` - An asynchronous function for processing a queued\n task, which must call its `callback(err)` argument when finished, with an \n optional `error` as an argument.\n* `concurrency` - An `integer` for determining how many `worker` functions should be\n run in parallel.\n\n__Queue objects__\n\nThe `queue` object returned by this function has the following properties and\nmethods:\n\n* `length()` - a function returning the number of items waiting to be processed.\n* `started` - a function returning whether or not any items have been pushed and processed by the queue\n* `running()` - a function returning the number of items currently being processed.\n* `idle()` - a function returning false if there are items waiting or being processed, or true if not.\n* `concurrency` - an integer for determining how many `worker` functions should be\n run in parallel. This property can be changed after a `queue` is created to\n alter the concurrency on-the-fly.\n* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once \n the `worker` has finished processing the task. Instead of a single task, a `tasks` array\n can be submitted. The respective callback is used for every task in the list.\n* `unshift(task, [callback])` - add a new task to the front of the `queue`.\n* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, \n and further tasks will be queued.\n* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`.\n* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`.\n* `paused` - a boolean for determining whether the queue is in a paused state\n* `pause()` - a function that pauses the processing of tasks until `resume()` is called.\n* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.\n* `kill()` - a function that empties remaining tasks from the queue forcing it to go idle.\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n\n---------------------------------------\n\n\n### priorityQueue(worker, concurrency)\n\nThe same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:\n\n* `push(task, priority, [callback])` - `priority` should be a number. If an array of\n `tasks` is given, all tasks will be assigned the same priority.\n* The `unshift` method was removed.\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a `cargo` object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the `payload` limit). If the\n`worker` is in progress, the task is queued until it becomes available. Once\nthe `worker` has completed some tasks, each callback of those tasks is called.\nCheck out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.\n\nWhile [queue](#queue) passes only one task to one of a group of workers\nat a time, cargo passes an array of tasks to a single worker, repeating\nwhen the worker is finished.\n\n__Arguments__\n\n* `worker(tasks, callback)` - An asynchronous function for processing an array of\n queued tasks, which must call its `callback(err)` argument when finished, with \n an optional `err` argument.\n* `payload` - An optional `integer` for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe `cargo` object returned by this function has the following properties and\nmethods:\n\n* `length()` - A function returning the number of items waiting to be processed.\n* `payload` - An `integer` for determining how many tasks should be\n process per round. This property can be changed after a `cargo` is created to\n alter the payload on-the-fly.\n* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called\n once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` \n can be submitted. The respective callback is used for every task in the list.\n* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued.\n* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`.\n* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`.\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i
I am using markdown.
\n```\n\nExample setting options with default values:\n\n```js\nvar marked = require('marked');\nmarked.setOptions({\n renderer: new marked.Renderer(),\n gfm: true,\n tables: true,\n breaks: false,\n pedantic: false,\n sanitize: true,\n smartLists: true,\n smartypants: false\n});\n\nconsole.log(marked('I am using __markdown__.'));\n```\n\n## marked(markdownString [,options] [,callback])\n\n### markdownString\n\nType: `string`\n\nString of markdown source to be compiled.\n\n### options\n\nType: `object`\n\nHash of options. Can also be set using the `marked.setOptions` method as seen\nabove.\n\n### callback\n\nType: `function`\n\nFunction called when the `markdownString` has been fully parsed when using\nasync highlighting. If the `options` argument is omitted, this can be used as\nthe second argument.\n\n## Options\n\n### highlight\n\nType: `function`\n\nA function to highlight code blocks. The first example below uses async highlighting with\n[node-pygmentize-bundled][pygmentize], and the second is a synchronous example using\n[highlight.js][highlight]:\n\n```js\nvar marked = require('marked');\n\nvar markdownString = '```js\\n console.log(\"hello\"); \\n```';\n\n// Async highlighting with pygmentize-bundled\nmarked.setOptions({\n highlight: function (code, lang, callback) {\n require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {\n callback(err, result.toString());\n });\n }\n});\n\n// Using async version of marked\nmarked(markdownString, function (err, content) {\n if (err) throw err;\n console.log(content);\n});\n\n// Synchronous highlighting with highlight.js\nmarked.setOptions({\n highlight: function (code) {\n return require('highlight.js').highlightAuto(code).value;\n }\n});\n\nconsole.log(marked(markdownString));\n```\n\n#### highlight arguments\n\n`code`\n\nType: `string`\n\nThe section of code to pass to the highlighter.\n\n`lang`\n\nType: `string`\n\nThe programming language specified in the code block.\n\n`callback`\n\nType: `function`\n\nThe callback function to call when using an async highlighter.\n\n### renderer\n\nType: `object`\nDefault: `new Renderer()`\n\nAn object containing functions to render tokens to HTML.\n\n#### Overriding renderer methods\n\nThe renderer option allows you to render tokens in a custom manor. Here is an\nexample of overriding the default heading token rendering by adding an embedded anchor tag like on GitHub:\n\n```javascript\nvar marked = require('marked');\nvar renderer = new marked.Renderer();\n\nrenderer.heading = function (text, level) {\n var escapedText = text.toLowerCase().replace(/[^\\w]+/g, '-');\n\n return 'hello world
\n```\n\n## Philosophy behind marked\n\nThe point of marked was to create a markdown compiler where it was possible to\nfrequently parse huge chunks of markdown without having to worry about\ncaching the compiled output somehow...or blocking for an unnecesarily long time.\n\nmarked is very concise and still implements all markdown features. It is also\nnow fully compatible with the client-side.\n\nmarked more or less passes the official markdown test suite in its\nentirety. This is important because a surprising number of markdown compilers\ncannot pass more than a few tests. It was very difficult to get marked as\ncompliant as it is. It could have cut corners in several areas for the sake\nof performance, but did not in order to be exactly what you expect in terms\nof a markdown rendering. In fact, this is why marked could be considered at a\ndisadvantage in the benchmarks above.\n\nAlong with implementing every markdown feature, marked also implements [GFM\nfeatures][gfmf].\n\n## Benchmarks\n\nnode v0.8.x\n\n``` bash\n$ node test --bench\nmarked completed in 3411ms.\nmarked (gfm) completed in 3727ms.\nmarked (pedantic) completed in 3201ms.\nrobotskirt completed in 808ms.\nshowdown (reuse converter) completed in 11954ms.\nshowdown (new converter) completed in 17774ms.\nmarkdown-js completed in 17191ms.\n```\n\n__Marked is now faster than Discount, which is written in C.__\n\nFor those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects.\n\n### Pro level\n\nYou also have direct access to the lexer and parser if you so desire.\n\n``` js\nvar tokens = marked.lexer(text, options);\nconsole.log(marked.parser(tokens));\n```\n\n``` js\nvar lexer = new marked.Lexer(options);\nvar tokens = lexer.lex(text);\nconsole.log(tokens);\nconsole.log(lexer.rules);\n```\n\n``` bash\n$ node\n> require('marked').lexer('> i am using marked.')\n[ { type: 'blockquote_start' },\n { type: 'paragraph',\n text: 'i am using marked.' },\n { type: 'blockquote_end' },\n links: {} ]\n```\n\n## Running Tests & Contributing\n\nIf you want to submit a pull request, make sure your changes pass the test\nsuite. If you're adding a new feature, be sure to add your own test.\n\nThe marked test suite is set up slightly strangely: `test/new` is for all tests\nthat are not part of the original markdown.pl test suite (this is where your\ntest should go if you make one). `test/original` is only for the original\nmarkdown.pl tests. `test/tests` houses both types of tests after they have been\ncombined and moved/generated by running `node test --fix` or `marked --test\n--fix`.\n\nIn other words, if you have a test to add, add it to `test/new/` and then\nregenerate the tests with `node test --fix`. Commit the result. If your test\nuses a certain feature, for example, maybe it assumes GFM is *not* enabled, you\ncan add `.nogfm` to the filename. So, `my-test.text` becomes\n`my-test.nogfm.text`. You can do this with any marked option. Say you want\nline breaks and smartypants enabled, your filename should be:\n`my-test.breaks.smartypants.text`.\n\nTo run the tests:\n\n``` bash\ncd marked/\nnode test\n```\n\n### Contribution and License Agreement\n\nIf you contribute code to this project, you are implicitly allowing your code\nto be distributed under the MIT license. You are also implicitly verifying that\nall code is your original work. ``\n\n## License\n\nCopyright (c) 2011-2014, Christopher Jeffrey. (MIT License)\n\nSee LICENSE for more info.\n\n[gfm]: https://help.github.com/articles/github-flavored-markdown\n[gfmf]: http://github.github.com/github-flavored-markdown/\n[pygmentize]: https://github.com/rvagg/node-pygmentize-bundled\n[highlight]: https://github.com/isagalaev/highlight.js\n[badge]: http://badge.fury.io/js/marked\n[tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables\n[breaks]: https://help.github.com/articles/github-flavored-markdown#newlines\n", - "readmeFilename": "README.md", - "_id": "marked@0.3.2", - "_shasum": "015db158864438f24a64bdd61a0428b418706d09", - "_from": "marked@~0.3.2", - "_resolved": "https://registry.npmjs.org/marked/-/marked-0.3.2.tgz" + "gitHead": "cb4981c553d8ee22953f5eacca989e65a821c764", + "_id": "marked@0.3.4", + "_shasum": "b0afa8e0b33f80c9265e864a333ec99ecebdf2b0", + "_from": "marked@>=0.3.4 <0.4.0", + "_npmVersion": "2.13.2", + "_nodeVersion": "0.12.7", + "_npmUser": { + "name": "chjj", + "email": "chjjeffrey@gmail.com" + }, + "maintainers": [ + { + "name": "chjj", + "email": "chjjeffrey@gmail.com" + } + ], + "dist": { + "shasum": "b0afa8e0b33f80c9265e864a333ec99ecebdf2b0", + "tarball": "http://registry.npmjs.org/marked/-/marked-0.3.4.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/marked/-/marked-0.3.4.tgz" } diff --git a/node_modules/underscore/LICENSE b/node_modules/underscore/LICENSE index 0d6b8739..ad0e71bc 100644 --- a/node_modules/underscore/LICENSE +++ b/node_modules/underscore/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative +Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person diff --git a/node_modules/underscore/package.json b/node_modules/underscore/package.json index 5a82a144..3b021d07 100644 --- a/node_modules/underscore/package.json +++ b/node_modules/underscore/package.json @@ -18,37 +18,38 @@ "url": "git://github.com/jashkenas/underscore.git" }, "main": "underscore.js", - "version": "1.7.0", + "version": "1.8.3", "devDependencies": { - "docco": "0.6.x", - "phantomjs": "1.9.7-1", - "uglify-js": "2.4.x", - "eslint": "0.6.x" + "docco": "*", + "eslint": "0.6.x", + "karma": "~0.12.31", + "karma-qunit": "~0.1.4", + "qunit-cli": "~0.2.0", + "uglify-js": "2.4.x" }, "scripts": { - "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true && eslint underscore.js test/*.js test/vendor/runner.js", + "test": "npm run test-node && npm run lint", + "lint": "eslint underscore.js test/*.js", + "test-node": "qunit-cli test/*.js", + "test-browser": "npm i karma-phantomjs-launcher && ./node_modules/karma/bin/karma start", "build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js", "doc": "docco underscore.js" }, - "licenses": [ - { - "type": "MIT", - "url": "https://raw.github.com/jashkenas/underscore/master/LICENSE" - } - ], + "license": "MIT", "files": [ "underscore.js", "underscore-min.js", + "underscore-min.map", "LICENSE" ], - "gitHead": "da996e665deb0b69b257e80e3e257c04fde4191c", + "gitHead": "e4743ab712b8ab42ad4ccb48b155034d02394e4d", "bugs": { "url": "https://github.com/jashkenas/underscore/issues" }, - "_id": "underscore@1.7.0", - "_shasum": "6bbaf0877500d36be34ecaa584e0db9fef035209", - "_from": "underscore@~1.7.0", - "_npmVersion": "1.4.24", + "_id": "underscore@1.8.3", + "_shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022", + "_from": "underscore@1.8.3", + "_npmVersion": "1.4.28", "_npmUser": { "name": "jashkenas", "email": "jashkenas@gmail.com" @@ -60,10 +61,9 @@ } ], "dist": { - "shasum": "6bbaf0877500d36be34ecaa584e0db9fef035209", - "tarball": "http://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + "shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022", + "tarball": "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", - "readme": "ERROR: No README data found!" + "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" } diff --git a/node_modules/underscore/underscore.js b/node_modules/underscore/underscore.js index b4f49a02..b29332f9 100644 --- a/node_modules/underscore/underscore.js +++ b/node_modules/underscore/underscore.js @@ -1,6 +1,6 @@ -// Underscore.js 1.7.0 +// Underscore.js 1.8.3 // http://underscorejs.org -// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Underscore may be freely distributed under the MIT license. (function() { @@ -21,7 +21,6 @@ var push = ArrayProto.push, slice = ArrayProto.slice, - concat = ArrayProto.concat, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; @@ -30,7 +29,11 @@ var nativeIsArray = Array.isArray, nativeKeys = Object.keys, - nativeBind = FuncProto.bind; + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; // Create a safe reference to the Underscore object for use below. var _ = function(obj) { @@ -52,12 +55,12 @@ } // Current version. - _.VERSION = '1.7.0'; + _.VERSION = '1.8.3'; // Internal function that returns an efficient (for current engines) version // of the passed-in callback, to be repeatedly applied in other Underscore // functions. - var createCallback = function(func, context, argCount) { + var optimizeCb = function(func, context, argCount) { if (context === void 0) return func; switch (argCount == null ? 3 : argCount) { case 1: return function(value) { @@ -81,12 +84,60 @@ // A mostly-internal function to generate callbacks that can be applied // to each element in a collection, returning the desired result — either // identity, an arbitrary callback, a property matcher, or a property accessor. - _.iteratee = function(value, context, argCount) { + var cb = function(value, context, argCount) { if (value == null) return _.identity; - if (_.isFunction(value)) return createCallback(value, context, argCount); - if (_.isObject(value)) return _.matches(value); + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); return _.property(value); }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; + + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; + + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; + + var property = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; + + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = property('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; // Collection Functions // -------------------- @@ -95,11 +146,10 @@ // Handles raw objects in addition to array-likes. Treats all // sparse array-likes as if they were dense. _.each = _.forEach = function(obj, iteratee, context) { - if (obj == null) return obj; - iteratee = createCallback(iteratee, context); - var i, length = obj.length; - if (length === +length) { - for (i = 0; i < length; i++) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { iteratee(obj[i], i, obj); } } else { @@ -113,77 +163,66 @@ // Return the results of applying the iteratee to each element. _.map = _.collect = function(obj, iteratee, context) { - if (obj == null) return []; - iteratee = _.iteratee(iteratee, context); - var keys = obj.length !== +obj.length && _.keys(obj), + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, - results = Array(length), - currentKey; + results = Array(length); for (var index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + var currentKey = keys ? keys[index] : index; results[index] = iteratee(obj[currentKey], currentKey, obj); } return results; }; - var reduceError = 'Reduce of empty array with no initial value'; + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } + + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } // **Reduce** builds up a single result from a list of values, aka `inject`, // or `foldl`. - _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index = 0, currentKey; - if (arguments.length < 3) { - if (!length) throw new TypeError(reduceError); - memo = obj[keys ? keys[index++] : index++]; - } - for (; index < length; index++) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; + _.reduce = _.foldl = _.inject = createReduce(1); // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = function(obj, iteratee, memo, context) { - if (obj == null) obj = []; - iteratee = createCallback(iteratee, context, 4); - var keys = obj.length !== + obj.length && _.keys(obj), - index = (keys || obj).length, - currentKey; - if (arguments.length < 3) { - if (!index) throw new TypeError(reduceError); - memo = obj[keys ? keys[--index] : --index]; - } - while (index--) { - currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; + _.reduceRight = _.foldr = createReduce(-1); // Return the first value which passes a truth test. Aliased as `detect`. _.find = _.detect = function(obj, predicate, context) { - var result; - predicate = _.iteratee(predicate, context); - _.some(obj, function(value, index, list) { - if (predicate(value, index, list)) { - result = value; - return true; - } - }); - return result; + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; }; // Return all the elements that pass a truth test. // Aliased as `select`. _.filter = _.select = function(obj, predicate, context) { var results = []; - if (obj == null) return results; - predicate = _.iteratee(predicate, context); + predicate = cb(predicate, context); _.each(obj, function(value, index, list) { if (predicate(value, index, list)) results.push(value); }); @@ -192,19 +231,17 @@ // Return all the elements for which a truth test fails. _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(_.iteratee(predicate)), context); + return _.filter(obj, _.negate(cb(predicate)), context); }; // Determine whether all of the elements match a truth test. // Aliased as `all`. _.every = _.all = function(obj, predicate, context) { - if (obj == null) return true; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; if (!predicate(obj[currentKey], currentKey, obj)) return false; } return true; @@ -213,24 +250,22 @@ // Determine if at least one element in the object matches a truth test. // Aliased as `any`. _.some = _.any = function(obj, predicate, context) { - if (obj == null) return false; - predicate = _.iteratee(predicate, context); - var keys = obj.length !== +obj.length && _.keys(obj), - length = (keys || obj).length, - index, currentKey; - for (index = 0; index < length; index++) { - currentKey = keys ? keys[index] : index; + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; if (predicate(obj[currentKey], currentKey, obj)) return true; } return false; }; - // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - if (obj == null) return false; - if (obj.length !== +obj.length) obj = _.values(obj); - return _.indexOf(obj, target) >= 0; + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; }; // Invoke a method (with arguments) on every item in a collection. @@ -238,7 +273,8 @@ var args = slice.call(arguments, 2); var isFunc = _.isFunction(method); return _.map(obj, function(value) { - return (isFunc ? method : value[method]).apply(value, args); + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); }); }; @@ -250,13 +286,13 @@ // Convenience version of a common use case of `filter`: selecting only objects // containing specific `key:value` pairs. _.where = function(obj, attrs) { - return _.filter(obj, _.matches(attrs)); + return _.filter(obj, _.matcher(attrs)); }; // Convenience version of a common use case of `find`: getting the first object // containing specific `key:value` pairs. _.findWhere = function(obj, attrs) { - return _.find(obj, _.matches(attrs)); + return _.find(obj, _.matcher(attrs)); }; // Return the maximum element (or element-based computation). @@ -264,7 +300,7 @@ var result = -Infinity, lastComputed = -Infinity, value, computed; if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); + obj = isArrayLike(obj) ? obj : _.values(obj); for (var i = 0, length = obj.length; i < length; i++) { value = obj[i]; if (value > result) { @@ -272,7 +308,7 @@ } } } else { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index, list) { computed = iteratee(value, index, list); if (computed > lastComputed || computed === -Infinity && result === -Infinity) { @@ -289,7 +325,7 @@ var result = Infinity, lastComputed = Infinity, value, computed; if (iteratee == null && obj != null) { - obj = obj.length === +obj.length ? obj : _.values(obj); + obj = isArrayLike(obj) ? obj : _.values(obj); for (var i = 0, length = obj.length; i < length; i++) { value = obj[i]; if (value < result) { @@ -297,7 +333,7 @@ } } } else { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index, list) { computed = iteratee(value, index, list); if (computed < lastComputed || computed === Infinity && result === Infinity) { @@ -312,7 +348,7 @@ // Shuffle a collection, using the modern version of the // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). _.shuffle = function(obj) { - var set = obj && obj.length === +obj.length ? obj : _.values(obj); + var set = isArrayLike(obj) ? obj : _.values(obj); var length = set.length; var shuffled = Array(length); for (var index = 0, rand; index < length; index++) { @@ -328,7 +364,7 @@ // The internal `guard` argument allows it to work with `map`. _.sample = function(obj, n, guard) { if (n == null || guard) { - if (obj.length !== +obj.length) obj = _.values(obj); + if (!isArrayLike(obj)) obj = _.values(obj); return obj[_.random(obj.length - 1)]; } return _.shuffle(obj).slice(0, Math.max(0, n)); @@ -336,7 +372,7 @@ // Sort the object's values by a criterion produced by an iteratee. _.sortBy = function(obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); return _.pluck(_.map(obj, function(value, index, list) { return { value: value, @@ -358,7 +394,7 @@ var group = function(behavior) { return function(obj, iteratee, context) { var result = {}; - iteratee = _.iteratee(iteratee, context); + iteratee = cb(iteratee, context); _.each(obj, function(value, index) { var key = iteratee(value, index, obj); behavior(result, value, key); @@ -386,37 +422,24 @@ if (_.has(result, key)) result[key]++; else result[key] = 1; }); - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = _.iteratee(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = array.length; - while (low < high) { - var mid = low + high >>> 1; - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - // Safely create a real, live array from anything iterable. _.toArray = function(obj) { if (!obj) return []; if (_.isArray(obj)) return slice.call(obj); - if (obj.length === +obj.length) return _.map(obj, _.identity); + if (isArrayLike(obj)) return _.map(obj, _.identity); return _.values(obj); }; // Return the number of elements in an object. _.size = function(obj) { if (obj == null) return 0; - return obj.length === +obj.length ? obj.length : _.keys(obj).length; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; }; // Split a collection into two arrays: one whose elements all satisfy the given // predicate, and one whose elements all do not satisfy the predicate. _.partition = function(obj, predicate, context) { - predicate = _.iteratee(predicate, context); + predicate = cb(predicate, context); var pass = [], fail = []; _.each(obj, function(value, key, obj) { (predicate(value, key, obj) ? pass : fail).push(value); @@ -433,30 +456,27 @@ _.first = _.head = _.take = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[0]; - if (n < 0) return []; - return slice.call(array, 0, n); + return _.initial(array, array.length - n); }; // Returns everything but the last entry of the array. Especially useful on // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. + // the array, excluding the last N. _.initial = function(array, n, guard) { return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); }; // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. + // values in the array. _.last = function(array, n, guard) { if (array == null) return void 0; if (n == null || guard) return array[array.length - 1]; - return slice.call(array, Math.max(array.length - n, 0)); + return _.rest(array, Math.max(0, array.length - n)); }; // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. + // the rest N values in the array. _.rest = _.tail = _.drop = function(array, n, guard) { return slice.call(array, n == null || guard ? 1 : n); }; @@ -467,18 +487,20 @@ }; // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, output) { - if (shallow && _.every(input, _.isArray)) { - return concat.apply(output, input); - } - for (var i = 0, length = input.length; i < length; i++) { + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { var value = input[i]; - if (!_.isArray(value) && !_.isArguments(value)) { - if (!strict) output.push(value); - } else if (shallow) { - push.apply(output, value); - } else { - flatten(value, shallow, strict, output); + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; } } return output; @@ -486,7 +508,7 @@ // Flatten out an array, either recursively (by default), or just one level. _.flatten = function(array, shallow) { - return flatten(array, shallow, false, []); + return flatten(array, shallow, false); }; // Return a version of the array that does not contain the specified value(s). @@ -498,27 +520,26 @@ // been sorted, you have the option of using a faster algorithm. // Aliased as `unique`. _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (array == null) return []; if (!_.isBoolean(isSorted)) { context = iteratee; iteratee = isSorted; isSorted = false; } - if (iteratee != null) iteratee = _.iteratee(iteratee, context); + if (iteratee != null) iteratee = cb(iteratee, context); var result = []; var seen = []; - for (var i = 0, length = array.length; i < length; i++) { - var value = array[i]; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; if (isSorted) { - if (!i || seen !== value) result.push(value); - seen = value; + if (!i || seen !== computed) result.push(value); + seen = computed; } else if (iteratee) { - var computed = iteratee(value, i, array); - if (_.indexOf(seen, computed) < 0) { + if (!_.contains(seen, computed)) { seen.push(computed); result.push(value); } - } else if (_.indexOf(result, value) < 0) { + } else if (!_.contains(result, value)) { result.push(value); } } @@ -528,16 +549,15 @@ // Produce an array that contains the union: each distinct element from all of // the passed-in arrays. _.union = function() { - return _.uniq(flatten(arguments, true, true, [])); + return _.uniq(flatten(arguments, true, true)); }; // Produce an array that contains every item shared between all the // passed-in arrays. _.intersection = function(array) { - if (array == null) return []; var result = []; var argsLength = arguments.length; - for (var i = 0, length = array.length; i < length; i++) { + for (var i = 0, length = getLength(array); i < length; i++) { var item = array[i]; if (_.contains(result, item)) continue; for (var j = 1; j < argsLength; j++) { @@ -551,7 +571,7 @@ // Take the difference between one array and a number of other arrays. // Only the elements present in just the first array will remain. _.difference = function(array) { - var rest = flatten(slice.call(arguments, 1), true, true, []); + var rest = flatten(arguments, true, true, 1); return _.filter(array, function(value){ return !_.contains(rest, value); }); @@ -559,23 +579,28 @@ // Zip together multiple lists into a single array -- elements that share // an index go together. - _.zip = function(array) { - if (array == null) return []; - var length = _.max(arguments, 'length').length; - var results = Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(arguments, i); + _.zip = function() { + return _.unzip(arguments); + }; + + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); + + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); } - return results; + return result; }; // Converts lists into objects. Pass either a single array of `[key, value]` // pairs, or two parallel arrays of the same length -- one of keys, and one of // the corresponding values. _.object = function(list, values) { - if (list == null) return {}; var result = {}; - for (var i = 0, length = list.length; i < length; i++) { + for (var i = 0, length = getLength(list); i < length; i++) { if (values) { result[list[i]] = values[i]; } else { @@ -585,40 +610,73 @@ return result; }; + // Generator function to create the findIndex and findLastIndex functions + function createPredicateIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } + + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions + function createIndexFinder(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); + } else { + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; + } + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; + } + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + } + // Return the position of the first occurrence of an item in an array, // or -1 if the item is not included in the array. // If the array is large and already in sort order, pass `true` // for **isSorted** to use binary search. - _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, length = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted; - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } - } - for (; i < length; i++) if (array[i] === item) return i; - return -1; - }; - - _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var idx = array.length; - if (typeof from == 'number') { - idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1); - } - while (--idx >= 0) if (array[idx] === item) return idx; - return -1; - }; + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); // Generate an integer Array containing an arithmetic progression. A port of // the native Python `range()` function. See // [the Python documentation](http://docs.python.org/library/functions.html#range). _.range = function(start, stop, step) { - if (arguments.length <= 1) { + if (stop == null) { stop = start || 0; start = 0; } @@ -637,25 +695,25 @@ // Function (ahem) Functions // ------------------ - // Reusable constructor function for prototype setting. - var Ctor = function(){}; + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; // Create a function bound to a given object (assigning `this`, and arguments, // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if // available. _.bind = function(func, context) { - var args, bound; if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - args = slice.call(arguments, 2); - bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - Ctor.prototype = func.prototype; - var self = new Ctor; - Ctor.prototype = null; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (_.isObject(result)) return result; - return self; + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); }; return bound; }; @@ -665,15 +723,16 @@ // as a placeholder, allowing any combination of arguments to be pre-filled. _.partial = function(func) { var boundArgs = slice.call(arguments, 1); - return function() { - var position = 0; - var args = boundArgs.slice(); - for (var i = 0, length = args.length; i < length; i++) { - if (args[i] === _) args[i] = arguments[position++]; + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; } while (position < arguments.length) args.push(arguments[position++]); - return func.apply(this, args); + return executeBound(func, bound, this, this, args); }; + return bound; }; // Bind a number of an object's methods to that object. Remaining arguments @@ -693,7 +752,7 @@ _.memoize = function(func, hasher) { var memoize = function(key) { var cache = memoize.cache; - var address = hasher ? hasher.apply(this, arguments) : key; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); return cache[address]; }; @@ -712,9 +771,7 @@ // Defers a function, scheduling it to run after the current call stack has // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; + _.defer = _.partial(_.delay, _, 1); // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. Normally, the throttled function will run @@ -739,8 +796,10 @@ context = this; args = arguments; if (remaining <= 0 || remaining > wait) { - clearTimeout(timeout); - timeout = null; + if (timeout) { + clearTimeout(timeout); + timeout = null; + } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; @@ -761,7 +820,7 @@ var later = function() { var last = _.now() - timestamp; - if (last < wait && last > 0) { + if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; @@ -814,7 +873,7 @@ }; }; - // Returns a function that will only be executed after being called N times. + // Returns a function that will only be executed on and after the Nth call. _.after = function(times, func) { return function() { if (--times < 1) { @@ -823,15 +882,14 @@ }; }; - // Returns a function that will only be executed before being called N times. + // Returns a function that will only be executed up to (but not including) the Nth call. _.before = function(times, func) { var memo; return function() { if (--times > 0) { memo = func.apply(this, arguments); - } else { - func = null; } + if (times <= 1) func = null; return memo; }; }; @@ -843,13 +901,47 @@ // Object Functions // ---------------- - // Retrieve the names of an object's properties. + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; + + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; + + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); + + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } + + // Retrieve the names of an object's own properties. // Delegates to **ECMAScript 5**'s native `Object.keys` _.keys = function(obj) { if (!_.isObject(obj)) return []; if (nativeKeys) return nativeKeys(obj); var keys = []; for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; + + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); return keys; }; @@ -864,6 +956,21 @@ return values; }; + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; + // Convert an object into a list of `[key, value]` pairs. _.pairs = function(obj) { var keys = _.keys(obj); @@ -896,37 +1003,38 @@ }; // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - if (!_.isObject(obj)) return obj; - var source, prop; - for (var i = 1, length = arguments.length; i < length; i++) { - source = arguments[i]; - for (prop in source) { - if (hasOwnProperty.call(source, prop)) { - obj[prop] = source[prop]; - } - } + _.extend = createAssigner(_.allKeys); + + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); + + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; } - return obj; }; // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj, iteratee, context) { - var result = {}, key; + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; if (obj == null) return result; - if (_.isFunction(iteratee)) { - iteratee = createCallback(iteratee, context); - for (key in obj) { - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); } else { - var keys = concat.apply([], slice.call(arguments, 1)); - obj = new Object(obj); - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (key in obj) result[key] = obj[key]; - } + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; } return result; }; @@ -936,7 +1044,7 @@ if (_.isFunction(iteratee)) { iteratee = _.negate(iteratee); } else { - var keys = _.map(concat.apply([], slice.call(arguments, 1)), String); + var keys = _.map(flatten(arguments, false, false, 1), String); iteratee = function(value, key) { return !_.contains(keys, key); }; @@ -945,15 +1053,15 @@ }; // Fill in a given object with default properties. - _.defaults = function(obj) { - if (!_.isObject(obj)) return obj; - for (var i = 1, length = arguments.length; i < length; i++) { - var source = arguments[i]; - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - return obj; + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; }; // Create a (shallow-cloned) duplicate of an object. @@ -970,6 +1078,19 @@ return obj; }; + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; + }; + + // Internal recursive comparison function for `isEqual`. var eq = function(a, b, aStack, bStack) { // Identical objects are equal. `0 === -0`, but they aren't identical. @@ -1004,74 +1125,76 @@ // of `NaN` are not equivalent. return +a === +b; } - if (typeof a != 'object' || typeof b != 'object') return false; + + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; + + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; var length = aStack.length; while (length--) { // Linear search. Performance is inversely proportional to the number of // unique nested structures. if (aStack[length] === a) return bStack[length] === b; } - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if ( - aCtor !== bCtor && - // Handle Object.create(x) cases - 'constructor' in a && 'constructor' in b && - !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - ) { - return false; - } + // Add the first object to the stack of traversed objects. aStack.push(a); bStack.push(b); - var size, result; + // Recursively compare objects and arrays. - if (className === '[object Array]') { + if (areArrays) { // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size === b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; } } else { // Deep compare objects. var keys = _.keys(a), key; - size = keys.length; + length = keys.length; // Ensure that both objects contain the same number of properties before comparing deep equality. - result = _.keys(b).length === size; - if (result) { - while (size--) { - // Deep compare each member - key = keys[size]; - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; } } // Remove the first object from the stack of traversed objects. aStack.pop(); bStack.pop(); - return result; + return true; }; // Perform a deep comparison to check if two objects are equal. _.isEqual = function(a, b) { - return eq(a, b, [], []); + return eq(a, b); }; // Is a given array, string, or object empty? // An "empty" object has no enumerable own-properties. _.isEmpty = function(obj) { if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; }; // Is a given value a DOM element? @@ -1091,14 +1214,14 @@ return type === 'function' || type === 'object' && !!obj; }; - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) === '[object ' + name + ']'; }; }); - // Define a fallback version of the method in browsers (ahem, IE), where + // Define a fallback version of the method in browsers (ahem, IE < 9), where // there isn't any inspectable "Arguments" type. if (!_.isArguments(arguments)) { _.isArguments = function(obj) { @@ -1106,8 +1229,9 @@ }; } - // Optimize `isFunction` if appropriate. Work around an IE 11 bug. - if (typeof /./ !== 'function') { + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { _.isFunction = function(obj) { return typeof obj == 'function' || false; }; @@ -1159,6 +1283,7 @@ return value; }; + // Predicate-generating functions. Often useful outside of Underscore. _.constant = function(value) { return function() { return value; @@ -1167,30 +1292,28 @@ _.noop = function(){}; - _.property = function(key) { - return function(obj) { + _.property = property; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { return obj[key]; }; }; - // Returns a predicate for checking whether an object has a given set of `key:value` pairs. - _.matches = function(attrs) { - var pairs = _.pairs(attrs), length = pairs.length; + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); return function(obj) { - if (obj == null) return !length; - obj = new Object(obj); - for (var i = 0; i < length; i++) { - var pair = pairs[i], key = pair[0]; - if (pair[1] !== obj[key] || !(key in obj)) return false; - } - return true; + return _.isMatch(obj, attrs); }; }; // Run a function **n** times. _.times = function(n, iteratee, context) { var accum = Array(Math.max(0, n)); - iteratee = createCallback(iteratee, context, 1); + iteratee = optimizeCb(iteratee, context, 1); for (var i = 0; i < n; i++) accum[i] = iteratee(i); return accum; }; @@ -1239,10 +1362,12 @@ // If the value of the named `property` is a function then invoke it with the // `object` as context; otherwise, return it. - _.result = function(object, property) { - if (object == null) return void 0; - var value = object[property]; - return _.isFunction(value) ? object[property]() : value; + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; + } + return _.isFunction(value) ? value.call(object) : value; }; // Generate a unique integer id (unique within the entire client session). @@ -1357,8 +1482,8 @@ // underscore functions. Wrapped objects may be chained. // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; }; // Add your own custom functions to the Underscore object. @@ -1368,7 +1493,7 @@ _.prototype[name] = function() { var args = [this._wrapped]; push.apply(args, arguments); - return result.call(this, func.apply(_, args)); + return result(this, func.apply(_, args)); }; }); }; @@ -1383,7 +1508,7 @@ var obj = this._wrapped; method.apply(obj, arguments); if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); + return result(this, obj); }; }); @@ -1391,7 +1516,7 @@ _.each(['concat', 'join', 'slice'], function(name) { var method = ArrayProto[name]; _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); + return result(this, method.apply(this._wrapped, arguments)); }; }); @@ -1400,6 +1525,14 @@ return this._wrapped; }; + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; + }; + // AMD registration happens at the end for compatibility with AMD loaders // that may not enforce next-turn semantics on modules. Even though general // practice for AMD registration is to be anonymous, underscore registers diff --git a/package.json b/package.json index e2206dd9..05e6a486 100644 --- a/package.json +++ b/package.json @@ -13,24 +13,24 @@ "url": "https://github.com/jsdoc3/jsdoc" }, "dependencies": { - "async": "~0.9.0", - "bluebird": "~2.9.14", + "async": "~1.4.0", + "bluebird": "~2.9.34", "catharsis": "~0.8.7", - "escape-string-regexp": "~1.0.2", - "espree": "~2.0.3", - "js2xmlparser": "~0.1.7", - "marked": "~0.3.2", + "escape-string-regexp": "~1.0.3", + "espree": "~2.2.3", + "js2xmlparser": "~1.0.0", + "marked": "~0.3.4", "requizzle": "~0.2.0", "strip-json-comments": "~1.0.2", "taffydb": "https://github.com/hegemonic/taffydb/tarball/7d100bcee0e997ee4977e273cdce60bd8933050e", - "underscore": "~1.7.0", + "underscore": "~1.8.3", "wrench": "~1.5.8" }, "devDependencies": { - "gulp": "~3.8.5", - "gulp-eslint": "~0.13.2", - "gulp-json-editor": "~2.0.2", - "istanbul": "~0.2.16", + "gulp": "~3.9.0", + "gulp-eslint": "~0.15.0", + "gulp-json-editor": "~2.2.1", + "istanbul": "~0.3.17", "tv4": "https://github.com/hegemonic/tv4/tarball/own-properties" }, "engines": {