--- /dev/null
+/*!\r
+ * Nodeunit\r
+ * https://github.com/caolan/nodeunit\r
+ * Copyright (c) 2010 Caolan McMahon\r
+ * MIT Licensed\r
+ *\r
+ * json2.js\r
+ * http://www.JSON.org/json2.js\r
+ * Public Domain.\r
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\r
+ */\r
+nodeunit = (function(){\r
+/*\r
+ http://www.JSON.org/json2.js\r
+ 2010-11-17\r
+\r
+ Public Domain.\r
+\r
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\r
+\r
+ See http://www.JSON.org/js.html\r
+\r
+\r
+ This code should be minified before deployment.\r
+ See http://javascript.crockford.com/jsmin.html\r
+\r
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\r
+ NOT CONTROL.\r
+\r
+\r
+ This file creates a global JSON object containing two methods: stringify\r
+ and parse.\r
+\r
+ JSON.stringify(value, replacer, space)\r
+ value any JavaScript value, usually an object or array.\r
+\r
+ replacer an optional parameter that determines how object\r
+ values are stringified for objects. It can be a\r
+ function or an array of strings.\r
+\r
+ space an optional parameter that specifies the indentation\r
+ of nested structures. If it is omitted, the text will\r
+ be packed without extra whitespace. If it is a number,\r
+ it will specify the number of spaces to indent at each\r
+ level. If it is a string (such as '\t' or ' '),\r
+ it contains the characters used to indent at each level.\r
+\r
+ This method produces a JSON text from a JavaScript value.\r
+\r
+ When an object value is found, if the object contains a toJSON\r
+ method, its toJSON method will be called and the result will be\r
+ stringified. A toJSON method does not serialize: it returns the\r
+ value represented by the name/value pair that should be serialized,\r
+ or undefined if nothing should be serialized. The toJSON method\r
+ will be passed the key associated with the value, and this will be\r
+ bound to the value\r
+\r
+ For example, this would serialize Dates as ISO strings.\r
+\r
+ Date.prototype.toJSON = function (key) {\r
+ function f(n) {\r
+ // Format integers to have at least two digits.\r
+ return n < 10 ? '0' + n : n;\r
+ }\r
+\r
+ return this.getUTCFullYear() + '-' +\r
+ f(this.getUTCMonth() + 1) + '-' +\r
+ f(this.getUTCDate()) + 'T' +\r
+ f(this.getUTCHours()) + ':' +\r
+ f(this.getUTCMinutes()) + ':' +\r
+ f(this.getUTCSeconds()) + 'Z';\r
+ };\r
+\r
+ You can provide an optional replacer method. It will be passed the\r
+ key and value of each member, with this bound to the containing\r
+ object. The value that is returned from your method will be\r
+ serialized. If your method returns undefined, then the member will\r
+ be excluded from the serialization.\r
+\r
+ If the replacer parameter is an array of strings, then it will be\r
+ used to select the members to be serialized. It filters the results\r
+ such that only members with keys listed in the replacer array are\r
+ stringified.\r
+\r
+ Values that do not have JSON representations, such as undefined or\r
+ functions, will not be serialized. Such values in objects will be\r
+ dropped; in arrays they will be replaced with null. You can use\r
+ a replacer function to replace those with JSON values.\r
+ JSON.stringify(undefined) returns undefined.\r
+\r
+ The optional space parameter produces a stringification of the\r
+ value that is filled with line breaks and indentation to make it\r
+ easier to read.\r
+\r
+ If the space parameter is a non-empty string, then that string will\r
+ be used for indentation. If the space parameter is a number, then\r
+ the indentation will be that many spaces.\r
+\r
+ Example:\r
+\r
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);\r
+ // text is '["e",{"pluribus":"unum"}]'\r
+\r
+\r
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');\r
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'\r
+\r
+ text = JSON.stringify([new Date()], function (key, value) {\r
+ return this[key] instanceof Date ?\r
+ 'Date(' + this[key] + ')' : value;\r
+ });\r
+ // text is '["Date(---current time---)"]'\r
+\r
+\r
+ JSON.parse(text, reviver)\r
+ This method parses a JSON text to produce an object or array.\r
+ It can throw a SyntaxError exception.\r
+\r
+ The optional reviver parameter is a function that can filter and\r
+ transform the results. It receives each of the keys and values,\r
+ and its return value is used instead of the original value.\r
+ If it returns what it received, then the structure is not modified.\r
+ If it returns undefined then the member is deleted.\r
+\r
+ Example:\r
+\r
+ // Parse the text. Values that look like ISO date strings will\r
+ // be converted to Date objects.\r
+\r
+ myData = JSON.parse(text, function (key, value) {\r
+ var a;\r
+ if (typeof value === 'string') {\r
+ a =\r
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);\r
+ if (a) {\r
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],\r
+ +a[5], +a[6]));\r
+ }\r
+ }\r
+ return value;\r
+ });\r
+\r
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {\r
+ var d;\r
+ if (typeof value === 'string' &&\r
+ value.slice(0, 5) === 'Date(' &&\r
+ value.slice(-1) === ')') {\r
+ d = new Date(value.slice(5, -1));\r
+ if (d) {\r
+ return d;\r
+ }\r
+ }\r
+ return value;\r
+ });\r
+\r
+\r
+ This is a reference implementation. You are free to copy, modify, or\r
+ redistribute.\r
+*/\r
+\r
+/*jslint evil: true, strict: false, regexp: false */\r
+\r
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,\r
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,\r
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,\r
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,\r
+ test, toJSON, toString, valueOf\r
+*/\r
+\r
+\r
+// Create a JSON object only if one does not already exist. We create the\r
+// methods in a closure to avoid creating global variables.\r
+\r
+var JSON = {};\r
+\r
+(function () {\r
+ "use strict";\r
+\r
+ function f(n) {\r
+ // Format integers to have at least two digits.\r
+ return n < 10 ? '0' + n : n;\r
+ }\r
+\r
+ if (typeof Date.prototype.toJSON !== 'function') {\r
+\r
+ Date.prototype.toJSON = function (key) {\r
+\r
+ return isFinite(this.valueOf()) ?\r
+ this.getUTCFullYear() + '-' +\r
+ f(this.getUTCMonth() + 1) + '-' +\r
+ f(this.getUTCDate()) + 'T' +\r
+ f(this.getUTCHours()) + ':' +\r
+ f(this.getUTCMinutes()) + ':' +\r
+ f(this.getUTCSeconds()) + 'Z' : null;\r
+ };\r
+\r
+ String.prototype.toJSON =\r
+ Number.prototype.toJSON =\r
+ Boolean.prototype.toJSON = function (key) {\r
+ return this.valueOf();\r
+ };\r
+ }\r
+\r
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,\r
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,\r
+ gap,\r
+ indent,\r
+ meta = { // table of character substitutions\r
+ '\b': '\\b',\r
+ '\t': '\\t',\r
+ '\n': '\\n',\r
+ '\f': '\\f',\r
+ '\r': '\\r',\r
+ '"' : '\\"',\r
+ '\\': '\\\\'\r
+ },\r
+ rep;\r
+\r
+\r
+ function quote(string) {\r
+\r
+// If the string contains no control characters, no quote characters, and no\r
+// backslash characters, then we can safely slap some quotes around it.\r
+// Otherwise we must also replace the offending characters with safe escape\r
+// sequences.\r
+\r
+ escapable.lastIndex = 0;\r
+ return escapable.test(string) ?\r
+ '"' + string.replace(escapable, function (a) {\r
+ var c = meta[a];\r
+ return typeof c === 'string' ? c :\r
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\r
+ }) + '"' :\r
+ '"' + string + '"';\r
+ }\r
+\r
+\r
+ function str(key, holder) {\r
+\r
+// Produce a string from holder[key].\r
+\r
+ var i, // The loop counter.\r
+ k, // The member key.\r
+ v, // The member value.\r
+ length,\r
+ mind = gap,\r
+ partial,\r
+ value = holder[key];\r
+\r
+// If the value has a toJSON method, call it to obtain a replacement value.\r
+\r
+ if (value && typeof value === 'object' &&\r
+ typeof value.toJSON === 'function') {\r
+ value = value.toJSON(key);\r
+ }\r
+\r
+// If we were called with a replacer function, then call the replacer to\r
+// obtain a replacement value.\r
+\r
+ if (typeof rep === 'function') {\r
+ value = rep.call(holder, key, value);\r
+ }\r
+\r
+// What happens next depends on the value's type.\r
+\r
+ switch (typeof value) {\r
+ case 'string':\r
+ return quote(value);\r
+\r
+ case 'number':\r
+\r
+// JSON numbers must be finite. Encode non-finite numbers as null.\r
+\r
+ return isFinite(value) ? String(value) : 'null';\r
+\r
+ case 'boolean':\r
+ case 'null':\r
+\r
+// If the value is a boolean or null, convert it to a string. Note:\r
+// typeof null does not produce 'null'. The case is included here in\r
+// the remote chance that this gets fixed someday.\r
+\r
+ return String(value);\r
+\r
+// If the type is 'object', we might be dealing with an object or an array or\r
+// null.\r
+\r
+ case 'object':\r
+\r
+// Due to a specification blunder in ECMAScript, typeof null is 'object',\r
+// so watch out for that case.\r
+\r
+ if (!value) {\r
+ return 'null';\r
+ }\r
+\r
+// Make an array to hold the partial results of stringifying this object value.\r
+\r
+ gap += indent;\r
+ partial = [];\r
+\r
+// Is the value an array?\r
+\r
+ if (Object.prototype.toString.apply(value) === '[object Array]') {\r
+\r
+// The value is an array. Stringify every element. Use null as a placeholder\r
+// for non-JSON values.\r
+\r
+ length = value.length;\r
+ for (i = 0; i < length; i += 1) {\r
+ partial[i] = str(i, value) || 'null';\r
+ }\r
+\r
+// Join all of the elements together, separated with commas, and wrap them in\r
+// brackets.\r
+\r
+ v = partial.length === 0 ? '[]' :\r
+ gap ? '[\n' + gap +\r
+ partial.join(',\n' + gap) + '\n' +\r
+ mind + ']' :\r
+ '[' + partial.join(',') + ']';\r
+ gap = mind;\r
+ return v;\r
+ }\r
+\r
+// If the replacer is an array, use it to select the members to be stringified.\r
+\r
+ if (rep && typeof rep === 'object') {\r
+ length = rep.length;\r
+ for (i = 0; i < length; i += 1) {\r
+ k = rep[i];\r
+ if (typeof k === 'string') {\r
+ v = str(k, value);\r
+ if (v) {\r
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+\r
+// Otherwise, iterate through all of the keys in the object.\r
+\r
+ for (k in value) {\r
+ if (Object.hasOwnProperty.call(value, k)) {\r
+ v = str(k, value);\r
+ if (v) {\r
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+// Join all of the member texts together, separated with commas,\r
+// and wrap them in braces.\r
+\r
+ v = partial.length === 0 ? '{}' :\r
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +\r
+ mind + '}' : '{' + partial.join(',') + '}';\r
+ gap = mind;\r
+ return v;\r
+ }\r
+ }\r
+\r
+// If the JSON object does not yet have a stringify method, give it one.\r
+\r
+ if (typeof JSON.stringify !== 'function') {\r
+ JSON.stringify = function (value, replacer, space) {\r
+\r
+// The stringify method takes a value and an optional replacer, and an optional\r
+// space parameter, and returns a JSON text. The replacer can be a function\r
+// that can replace values, or an array of strings that will select the keys.\r
+// A default replacer method can be provided. Use of the space parameter can\r
+// produce text that is more easily readable.\r
+\r
+ var i;\r
+ gap = '';\r
+ indent = '';\r
+\r
+// If the space parameter is a number, make an indent string containing that\r
+// many spaces.\r
+\r
+ if (typeof space === 'number') {\r
+ for (i = 0; i < space; i += 1) {\r
+ indent += ' ';\r
+ }\r
+\r
+// If the space parameter is a string, it will be used as the indent string.\r
+\r
+ } else if (typeof space === 'string') {\r
+ indent = space;\r
+ }\r
+\r
+// If there is a replacer, it must be a function or an array.\r
+// Otherwise, throw an error.\r
+\r
+ rep = replacer;\r
+ if (replacer && typeof replacer !== 'function' &&\r
+ (typeof replacer !== 'object' ||\r
+ typeof replacer.length !== 'number')) {\r
+ throw new Error('JSON.stringify');\r
+ }\r
+\r
+// Make a fake root object containing our value under the key of ''.\r
+// Return the result of stringifying the value.\r
+\r
+ return str('', {'': value});\r
+ };\r
+ }\r
+\r
+\r
+// If the JSON object does not yet have a parse method, give it one.\r
+\r
+ if (typeof JSON.parse !== 'function') {\r
+ JSON.parse = function (text, reviver) {\r
+\r
+// The parse method takes a text and an optional reviver function, and returns\r
+// a JavaScript value if the text is a valid JSON text.\r
+\r
+ var j;\r
+\r
+ function walk(holder, key) {\r
+\r
+// The walk method is used to recursively walk the resulting structure so\r
+// that modifications can be made.\r
+\r
+ var k, v, value = holder[key];\r
+ if (value && typeof value === 'object') {\r
+ for (k in value) {\r
+ if (Object.hasOwnProperty.call(value, k)) {\r
+ v = walk(value, k);\r
+ if (v !== undefined) {\r
+ value[k] = v;\r
+ } else {\r
+ delete value[k];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return reviver.call(holder, key, value);\r
+ }\r
+\r
+\r
+// Parsing happens in four stages. In the first stage, we replace certain\r
+// Unicode characters with escape sequences. JavaScript handles many characters\r
+// incorrectly, either silently deleting them, or treating them as line endings.\r
+\r
+ text = String(text);\r
+ cx.lastIndex = 0;\r
+ if (cx.test(text)) {\r
+ text = text.replace(cx, function (a) {\r
+ return '\\u' +\r
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\r
+ });\r
+ }\r
+\r
+// In the second stage, we run the text against regular expressions that look\r
+// for non-JSON patterns. We are especially concerned with '()' and 'new'\r
+// because they can cause invocation, and '=' because it can cause mutation.\r
+// But just to be safe, we want to reject all unexpected forms.\r
+\r
+// We split the second stage into 4 regexp operations in order to work around\r
+// crippling inefficiencies in IE's and Safari's regexp engines. First we\r
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we\r
+// replace all simple value tokens with ']' characters. Third, we delete all\r
+// open brackets that follow a colon or comma or that begin the text. Finally,\r
+// we look to see that the remaining characters are only whitespace or ']' or\r
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\r
+\r
+ if (/^[\],:{}\s]*$/\r
+.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')\r
+.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')\r
+.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {\r
+\r
+// In the third stage we use the eval function to compile the text into a\r
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity\r
+// in JavaScript: it can begin a block or an object literal. We wrap the text\r
+// in parens to eliminate the ambiguity.\r
+\r
+ j = eval('(' + text + ')');\r
+\r
+// In the optional fourth stage, we recursively walk the new structure, passing\r
+// each name/value pair to a reviver function for possible transformation.\r
+\r
+ return typeof reviver === 'function' ?\r
+ walk({'': j}, '') : j;\r
+ }\r
+\r
+// If the text is not JSON parseable, then a SyntaxError is thrown.\r
+\r
+ throw new SyntaxError('JSON.parse');\r
+ };\r
+ }\r
+}());\r
+var assert = this.assert = {};\r
+var types = {};\r
+var core = {};\r
+var nodeunit = {};\r
+var reporter = {};\r
+/*global setTimeout: false, console: false */\r
+(function () {\r
+\r
+ var async = {};\r
+\r
+ // global on the server, window in the browser\r
+ var root = this,\r
+ previous_async = root.async;\r
+\r
+ if (typeof module !== 'undefined' && module.exports) {\r
+ module.exports = async;\r
+ }\r
+ else {\r
+ root.async = async;\r
+ }\r
+\r
+ async.noConflict = function () {\r
+ root.async = previous_async;\r
+ return async;\r
+ };\r
+\r
+ //// cross-browser compatiblity functions ////\r
+\r
+ var _forEach = function (arr, iterator) {\r
+ if (arr.forEach) {\r
+ return arr.forEach(iterator);\r
+ }\r
+ for (var i = 0; i < arr.length; i += 1) {\r
+ iterator(arr[i], i, arr);\r
+ }\r
+ };\r
+\r
+ var _map = function (arr, iterator) {\r
+ if (arr.map) {\r
+ return arr.map(iterator);\r
+ }\r
+ var results = [];\r
+ _forEach(arr, function (x, i, a) {\r
+ results.push(iterator(x, i, a));\r
+ });\r
+ return results;\r
+ };\r
+\r
+ var _reduce = function (arr, iterator, memo) {\r
+ if (arr.reduce) {\r
+ return arr.reduce(iterator, memo);\r
+ }\r
+ _forEach(arr, function (x, i, a) {\r
+ memo = iterator(memo, x, i, a);\r
+ });\r
+ return memo;\r
+ };\r
+\r
+ var _keys = function (obj) {\r
+ if (Object.keys) {\r
+ return Object.keys(obj);\r
+ }\r
+ var keys = [];\r
+ for (var k in obj) {\r
+ if (obj.hasOwnProperty(k)) {\r
+ keys.push(k);\r
+ }\r
+ }\r
+ return keys;\r
+ };\r
+\r
+ var _indexOf = function (arr, item) {\r
+ if (arr.indexOf) {\r
+ return arr.indexOf(item);\r
+ }\r
+ for (var i = 0; i < arr.length; i += 1) {\r
+ if (arr[i] === item) {\r
+ return i;\r
+ }\r
+ }\r
+ return -1;\r
+ };\r
+\r
+ //// exported async module functions ////\r
+\r
+ //// nextTick implementation with browser-compatible fallback ////\r
+ if (typeof process === 'undefined' || !(process.nextTick)) {\r
+ async.nextTick = function (fn) {\r
+ setTimeout(fn, 0);\r
+ };\r
+ }\r
+ else {\r
+ async.nextTick = process.nextTick;\r
+ }\r
+\r
+ async.forEach = function (arr, iterator, callback) {\r
+ if (!arr.length) {\r
+ return callback();\r
+ }\r
+ var completed = 0;\r
+ _forEach(arr, function (x) {\r
+ iterator(x, function (err) {\r
+ if (err) {\r
+ callback(err);\r
+ callback = function () {};\r
+ }\r
+ else {\r
+ completed += 1;\r
+ if (completed === arr.length) {\r
+ callback();\r
+ }\r
+ }\r
+ });\r
+ });\r
+ };\r
+\r
+ async.forEachSeries = function (arr, iterator, callback) {\r
+ if (!arr.length) {\r
+ return callback();\r
+ }\r
+ var completed = 0;\r
+ var iterate = function () {\r
+ iterator(arr[completed], function (err) {\r
+ if (err) {\r
+ callback(err);\r
+ callback = function () {};\r
+ }\r
+ else {\r
+ completed += 1;\r
+ if (completed === arr.length) {\r
+ callback();\r
+ }\r
+ else {\r
+ iterate();\r
+ }\r
+ }\r
+ });\r
+ };\r
+ iterate();\r
+ };\r
+\r
+\r
+ var doParallel = function (fn) {\r
+ return function () {\r
+ var args = Array.prototype.slice.call(arguments);\r
+ return fn.apply(null, [async.forEach].concat(args));\r
+ };\r
+ };\r
+ var doSeries = function (fn) {\r
+ return function () {\r
+ var args = Array.prototype.slice.call(arguments);\r
+ return fn.apply(null, [async.forEachSeries].concat(args));\r
+ };\r
+ };\r
+\r
+\r
+ var _asyncMap = function (eachfn, arr, iterator, callback) {\r
+ var results = [];\r
+ arr = _map(arr, function (x, i) {\r
+ return {index: i, value: x};\r
+ });\r
+ eachfn(arr, function (x, callback) {\r
+ iterator(x.value, function (err, v) {\r
+ results[x.index] = v;\r
+ callback(err);\r
+ });\r
+ }, function (err) {\r
+ callback(err, results);\r
+ });\r
+ };\r
+ async.map = doParallel(_asyncMap);\r
+ async.mapSeries = doSeries(_asyncMap);\r
+\r
+\r
+ // reduce only has a series version, as doing reduce in parallel won't\r
+ // work in many situations.\r
+ async.reduce = function (arr, memo, iterator, callback) {\r
+ async.forEachSeries(arr, function (x, callback) {\r
+ iterator(memo, x, function (err, v) {\r
+ memo = v;\r
+ callback(err);\r
+ });\r
+ }, function (err) {\r
+ callback(err, memo);\r
+ });\r
+ };\r
+ // inject alias\r
+ async.inject = async.reduce;\r
+ // foldl alias\r
+ async.foldl = async.reduce;\r
+\r
+ async.reduceRight = function (arr, memo, iterator, callback) {\r
+ var reversed = _map(arr, function (x) {\r
+ return x;\r
+ }).reverse();\r
+ async.reduce(reversed, memo, iterator, callback);\r
+ };\r
+ // foldr alias\r
+ async.foldr = async.reduceRight;\r
+\r
+ var _filter = function (eachfn, arr, iterator, callback) {\r
+ var results = [];\r
+ arr = _map(arr, function (x, i) {\r
+ return {index: i, value: x};\r
+ });\r
+ eachfn(arr, function (x, callback) {\r
+ iterator(x.value, function (v) {\r
+ if (v) {\r
+ results.push(x);\r
+ }\r
+ callback();\r
+ });\r
+ }, function (err) {\r
+ callback(_map(results.sort(function (a, b) {\r
+ return a.index - b.index;\r
+ }), function (x) {\r
+ return x.value;\r
+ }));\r
+ });\r
+ };\r
+ async.filter = doParallel(_filter);\r
+ async.filterSeries = doSeries(_filter);\r
+ // select alias\r
+ async.select = async.filter;\r
+ async.selectSeries = async.filterSeries;\r
+\r
+ var _reject = function (eachfn, arr, iterator, callback) {\r
+ var results = [];\r
+ arr = _map(arr, function (x, i) {\r
+ return {index: i, value: x};\r
+ });\r
+ eachfn(arr, function (x, callback) {\r
+ iterator(x.value, function (v) {\r
+ if (!v) {\r
+ results.push(x);\r
+ }\r
+ callback();\r
+ });\r
+ }, function (err) {\r
+ callback(_map(results.sort(function (a, b) {\r
+ return a.index - b.index;\r
+ }), function (x) {\r
+ return x.value;\r
+ }));\r
+ });\r
+ };\r
+ async.reject = doParallel(_reject);\r
+ async.rejectSeries = doSeries(_reject);\r
+\r
+ var _detect = function (eachfn, arr, iterator, main_callback) {\r
+ eachfn(arr, function (x, callback) {\r
+ iterator(x, function (result) {\r
+ if (result) {\r
+ main_callback(x);\r
+ }\r
+ else {\r
+ callback();\r
+ }\r
+ });\r
+ }, function (err) {\r
+ main_callback();\r
+ });\r
+ };\r
+ async.detect = doParallel(_detect);\r
+ async.detectSeries = doSeries(_detect);\r
+\r
+ async.some = function (arr, iterator, main_callback) {\r
+ async.forEach(arr, function (x, callback) {\r
+ iterator(x, function (v) {\r
+ if (v) {\r
+ main_callback(true);\r
+ main_callback = function () {};\r
+ }\r
+ callback();\r
+ });\r
+ }, function (err) {\r
+ main_callback(false);\r
+ });\r
+ };\r
+ // any alias\r
+ async.any = async.some;\r
+\r
+ async.every = function (arr, iterator, main_callback) {\r
+ async.forEach(arr, function (x, callback) {\r
+ iterator(x, function (v) {\r
+ if (!v) {\r
+ main_callback(false);\r
+ main_callback = function () {};\r
+ }\r
+ callback();\r
+ });\r
+ }, function (err) {\r
+ main_callback(true);\r
+ });\r
+ };\r
+ // all alias\r
+ async.all = async.every;\r
+\r
+ async.sortBy = function (arr, iterator, callback) {\r
+ async.map(arr, function (x, callback) {\r
+ iterator(x, function (err, criteria) {\r
+ if (err) {\r
+ callback(err);\r
+ }\r
+ else {\r
+ callback(null, {value: x, criteria: criteria});\r
+ }\r
+ });\r
+ }, function (err, results) {\r
+ if (err) {\r
+ return callback(err);\r
+ }\r
+ else {\r
+ var fn = function (left, right) {\r
+ var a = left.criteria, b = right.criteria;\r
+ return a < b ? -1 : a > b ? 1 : 0;\r
+ };\r
+ callback(null, _map(results.sort(fn), function (x) {\r
+ return x.value;\r
+ }));\r
+ }\r
+ });\r
+ };\r
+\r
+ async.auto = function (tasks, callback) {\r
+ callback = callback || function () {};\r
+ var keys = _keys(tasks);\r
+ if (!keys.length) {\r
+ return callback(null);\r
+ }\r
+\r
+ var completed = [];\r
+\r
+ var listeners = [];\r
+ var addListener = function (fn) {\r
+ listeners.unshift(fn);\r
+ };\r
+ var removeListener = function (fn) {\r
+ for (var i = 0; i < listeners.length; i += 1) {\r
+ if (listeners[i] === fn) {\r
+ listeners.splice(i, 1);\r
+ return;\r
+ }\r
+ }\r
+ };\r
+ var taskComplete = function () {\r
+ _forEach(listeners, function (fn) {\r
+ fn();\r
+ });\r
+ };\r
+\r
+ addListener(function () {\r
+ if (completed.length === keys.length) {\r
+ callback(null);\r
+ }\r
+ });\r
+\r
+ _forEach(keys, function (k) {\r
+ var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];\r
+ var taskCallback = function (err) {\r
+ if (err) {\r
+ callback(err);\r
+ // stop subsequent errors hitting callback multiple times\r
+ callback = function () {};\r
+ }\r
+ else {\r
+ completed.push(k);\r
+ taskComplete();\r
+ }\r
+ };\r
+ var requires = task.slice(0, Math.abs(task.length - 1)) || [];\r
+ var ready = function () {\r
+ return _reduce(requires, function (a, x) {\r
+ return (a && _indexOf(completed, x) !== -1);\r
+ }, true);\r
+ };\r
+ if (ready()) {\r
+ task[task.length - 1](taskCallback);\r
+ }\r
+ else {\r
+ var listener = function () {\r
+ if (ready()) {\r
+ removeListener(listener);\r
+ task[task.length - 1](taskCallback);\r
+ }\r
+ };\r
+ addListener(listener);\r
+ }\r
+ });\r
+ };\r
+\r
+ async.waterfall = function (tasks, callback) {\r
+ if (!tasks.length) {\r
+ return callback();\r
+ }\r
+ callback = callback || function () {};\r
+ var wrapIterator = function (iterator) {\r
+ return function (err) {\r
+ if (err) {\r
+ callback(err);\r
+ callback = function () {};\r
+ }\r
+ else {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ var next = iterator.next();\r
+ if (next) {\r
+ args.push(wrapIterator(next));\r
+ }\r
+ else {\r
+ args.push(callback);\r
+ }\r
+ async.nextTick(function () {\r
+ iterator.apply(null, args);\r
+ });\r
+ }\r
+ };\r
+ };\r
+ wrapIterator(async.iterator(tasks))();\r
+ };\r
+\r
+ async.parallel = function (tasks, callback) {\r
+ callback = callback || function () {};\r
+ if (tasks.constructor === Array) {\r
+ async.map(tasks, function (fn, callback) {\r
+ if (fn) {\r
+ fn(function (err) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ if (args.length <= 1) {\r
+ args = args[0];\r
+ }\r
+ callback.call(null, err, args || null);\r
+ });\r
+ }\r
+ }, callback);\r
+ }\r
+ else {\r
+ var results = {};\r
+ async.forEach(_keys(tasks), function (k, callback) {\r
+ tasks[k](function (err) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ if (args.length <= 1) {\r
+ args = args[0];\r
+ }\r
+ results[k] = args;\r
+ callback(err);\r
+ });\r
+ }, function (err) {\r
+ callback(err, results);\r
+ });\r
+ }\r
+ };\r
+\r
+ async.series = function (tasks, callback) {\r
+ callback = callback || function () {};\r
+ if (tasks.constructor === Array) {\r
+ async.mapSeries(tasks, function (fn, callback) {\r
+ if (fn) {\r
+ fn(function (err) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ if (args.length <= 1) {\r
+ args = args[0];\r
+ }\r
+ callback.call(null, err, args || null);\r
+ });\r
+ }\r
+ }, callback);\r
+ }\r
+ else {\r
+ var results = {};\r
+ async.forEachSeries(_keys(tasks), function (k, callback) {\r
+ tasks[k](function (err) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ if (args.length <= 1) {\r
+ args = args[0];\r
+ }\r
+ results[k] = args;\r
+ callback(err);\r
+ });\r
+ }, function (err) {\r
+ callback(err, results);\r
+ });\r
+ }\r
+ };\r
+\r
+ async.iterator = function (tasks) {\r
+ var makeCallback = function (index) {\r
+ var fn = function () {\r
+ if (tasks.length) {\r
+ tasks[index].apply(null, arguments);\r
+ }\r
+ return fn.next();\r
+ };\r
+ fn.next = function () {\r
+ return (index < tasks.length - 1) ? makeCallback(index + 1): null;\r
+ };\r
+ return fn;\r
+ };\r
+ return makeCallback(0);\r
+ };\r
+\r
+ async.apply = function (fn) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ return function () {\r
+ return fn.apply(\r
+ null, args.concat(Array.prototype.slice.call(arguments))\r
+ );\r
+ };\r
+ };\r
+\r
+ var _concat = function (eachfn, arr, fn, callback) {\r
+ var r = [];\r
+ eachfn(arr, function (x, cb) {\r
+ fn(x, function (err, y) {\r
+ r = r.concat(y || []);\r
+ cb(err);\r
+ });\r
+ }, function (err) {\r
+ callback(err, r);\r
+ });\r
+ };\r
+ async.concat = doParallel(_concat);\r
+ async.concatSeries = doSeries(_concat);\r
+\r
+ async.whilst = function (test, iterator, callback) {\r
+ if (test()) {\r
+ iterator(function (err) {\r
+ if (err) {\r
+ return callback(err);\r
+ }\r
+ async.whilst(test, iterator, callback);\r
+ });\r
+ }\r
+ else {\r
+ callback();\r
+ }\r
+ };\r
+\r
+ async.until = function (test, iterator, callback) {\r
+ if (!test()) {\r
+ iterator(function (err) {\r
+ if (err) {\r
+ return callback(err);\r
+ }\r
+ async.until(test, iterator, callback);\r
+ });\r
+ }\r
+ else {\r
+ callback();\r
+ }\r
+ };\r
+\r
+ async.queue = function (worker, concurrency) {\r
+ var workers = 0;\r
+ var tasks = [];\r
+ var q = {\r
+ concurrency: concurrency,\r
+ push: function (data, callback) {\r
+ tasks.push({data: data, callback: callback});\r
+ async.nextTick(q.process);\r
+ },\r
+ process: function () {\r
+ if (workers < q.concurrency && tasks.length) {\r
+ var task = tasks.splice(0, 1)[0];\r
+ workers += 1;\r
+ worker(task.data, function () {\r
+ workers -= 1;\r
+ if (task.callback) {\r
+ task.callback.apply(task, arguments);\r
+ }\r
+ q.process();\r
+ });\r
+ }\r
+ },\r
+ length: function () {\r
+ return tasks.length;\r
+ }\r
+ };\r
+ return q;\r
+ };\r
+\r
+ var _console_fn = function (name) {\r
+ return function (fn) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ fn.apply(null, args.concat([function (err) {\r
+ var args = Array.prototype.slice.call(arguments, 1);\r
+ if (typeof console !== 'undefined') {\r
+ if (err) {\r
+ if (console.error) {\r
+ console.error(err);\r
+ }\r
+ }\r
+ else if (console[name]) {\r
+ _forEach(args, function (x) {\r
+ console[name](x);\r
+ });\r
+ }\r
+ }\r
+ }]));\r
+ };\r
+ };\r
+ async.log = _console_fn('log');\r
+ async.dir = _console_fn('dir');\r
+ /*async.info = _console_fn('info');\r
+ async.warn = _console_fn('warn');\r
+ async.error = _console_fn('error');*/\r
+\r
+ async.memoize = function (fn, hasher) {\r
+ var memo = {};\r
+ hasher = hasher || function (x) {\r
+ return x;\r
+ };\r
+ return function () {\r
+ var args = Array.prototype.slice.call(arguments);\r
+ var callback = args.pop();\r
+ var key = hasher.apply(null, args);\r
+ if (key in memo) {\r
+ callback.apply(null, memo[key]);\r
+ }\r
+ else {\r
+ fn.apply(null, args.concat([function () {\r
+ memo[key] = arguments;\r
+ callback.apply(null, arguments);\r
+ }]));\r
+ }\r
+ };\r
+ };\r
+\r
+}());\r
+(function(exports){\r
+/**\r
+ * This file is based on the node.js assert module, but with some small\r
+ * changes for browser-compatibility\r
+ * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\r
+ */\r
+\r
+\r
+/**\r
+ * Added for browser compatibility\r
+ */\r
+\r
+var _keys = function(obj){\r
+ if(Object.keys) return Object.keys(obj);\r
+ if (typeof obj != 'object' && typeof obj != 'function') {\r
+ throw new TypeError('-');\r
+ }\r
+ var keys = [];\r
+ for(var k in obj){\r
+ if(obj.hasOwnProperty(k)) keys.push(k);\r
+ }\r
+ return keys;\r
+};\r
+\r
+\r
+\r
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\r
+//\r
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\r
+//\r
+// Originally from narwhal.js (http://narwhaljs.org)\r
+// Copyright (c) 2009 Thomas Robinson <280north.com>\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining a copy\r
+// of this software and associated documentation files (the 'Software'), to\r
+// deal in the Software without restriction, including without limitation the\r
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\r
+// sell copies of the Software, and to permit persons to whom the Software is\r
+// furnished to do so, subject to the following conditions:\r
+//\r
+// The above copyright notice and this permission notice shall be included in\r
+// all copies or substantial portions of the Software.\r
+//\r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+\r
+\r
+var pSlice = Array.prototype.slice;\r
+\r
+// 1. The assert module provides functions that throw\r
+// AssertionError's when particular conditions are not met. The\r
+// assert module must conform to the following interface.\r
+\r
+var assert = exports;\r
+\r
+// 2. The AssertionError is defined in assert.\r
+// new assert.AssertionError({message: message, actual: actual, expected: expected})\r
+\r
+assert.AssertionError = function AssertionError (options) {\r
+ this.name = "AssertionError";\r
+ this.message = options.message;\r
+ this.actual = options.actual;\r
+ this.expected = options.expected;\r
+ this.operator = options.operator;\r
+ var stackStartFunction = options.stackStartFunction || fail;\r
+\r
+ if (Error.captureStackTrace) {\r
+ Error.captureStackTrace(this, stackStartFunction);\r
+ }\r
+};\r
+// code from util.inherits in node\r
+assert.AssertionError.super_ = Error;\r
+\r
+\r
+// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call\r
+// TODO: test what effect this may have\r
+var ctor = function () { this.constructor = assert.AssertionError; };\r
+ctor.prototype = Error.prototype;\r
+assert.AssertionError.prototype = new ctor();\r
+\r
+\r
+assert.AssertionError.prototype.toString = function() {\r
+ if (this.message) {\r
+ return [this.name+":", this.message].join(' ');\r
+ } else {\r
+ return [ this.name+":"\r
+ , JSON.stringify(this.expected )\r
+ , this.operator\r
+ , JSON.stringify(this.actual)\r
+ ].join(" ");\r
+ }\r
+};\r
+\r
+// assert.AssertionError instanceof Error\r
+\r
+assert.AssertionError.__proto__ = Error.prototype;\r
+\r
+// At present only the three keys mentioned above are used and\r
+// understood by the spec. Implementations or sub modules can pass\r
+// other keys to the AssertionError's constructor - they will be\r
+// ignored.\r
+\r
+// 3. All of the following functions must throw an AssertionError\r
+// when a corresponding condition is not met, with a message that\r
+// may be undefined if not provided. All assertion methods provide\r
+// both the actual and expected values to the assertion error for\r
+// display purposes.\r
+\r
+function fail(actual, expected, message, operator, stackStartFunction) {\r
+ throw new assert.AssertionError({\r
+ message: message,\r
+ actual: actual,\r
+ expected: expected,\r
+ operator: operator,\r
+ stackStartFunction: stackStartFunction\r
+ });\r
+}\r
+\r
+// EXTENSION! allows for well behaved errors defined elsewhere.\r
+assert.fail = fail;\r
+\r
+// 4. Pure assertion tests whether a value is truthy, as determined\r
+// by !!guard.\r
+// assert.ok(guard, message_opt);\r
+// This statement is equivalent to assert.equal(true, guard,\r
+// message_opt);. To test strictly for the value true, use\r
+// assert.strictEqual(true, guard, message_opt);.\r
+\r
+assert.ok = function ok(value, message) {\r
+ if (!!!value) fail(value, true, message, "==", assert.ok);\r
+};\r
+\r
+// 5. The equality assertion tests shallow, coercive equality with\r
+// ==.\r
+// assert.equal(actual, expected, message_opt);\r
+\r
+assert.equal = function equal(actual, expected, message) {\r
+ if (actual != expected) fail(actual, expected, message, "==", assert.equal);\r
+};\r
+\r
+// 6. The non-equality assertion tests for whether two objects are not equal\r
+// with != assert.notEqual(actual, expected, message_opt);\r
+\r
+assert.notEqual = function notEqual(actual, expected, message) {\r
+ if (actual == expected) {\r
+ fail(actual, expected, message, "!=", assert.notEqual);\r
+ }\r
+};\r
+\r
+// 7. The equivalence assertion tests a deep equality relation.\r
+// assert.deepEqual(actual, expected, message_opt);\r
+\r
+assert.deepEqual = function deepEqual(actual, expected, message) {\r
+ if (!_deepEqual(actual, expected)) {\r
+ fail(actual, expected, message, "deepEqual", assert.deepEqual);\r
+ }\r
+};\r
+\r
+var Buffer = null;\r
+if (typeof require !== 'undefined' && typeof process !== 'undefined') {\r
+ try {\r
+ Buffer = require('buffer').Buffer;\r
+ }\r
+ catch (e) {\r
+ // May be a CommonJS environment other than Node.js\r
+ Buffer = null;\r
+ }\r
+}\r
+\r
+function _deepEqual(actual, expected) {\r
+ // 7.1. All identical values are equivalent, as determined by ===.\r
+ if (actual === expected) {\r
+ return true;\r
+ // 7.2. If the expected value is a Date object, the actual value is\r
+ // equivalent if it is also a Date object that refers to the same time.\r
+ } else if (actual instanceof Date && expected instanceof Date) {\r
+ return actual.getTime() === expected.getTime();\r
+\r
+ // 7.2.1 If the expcted value is a RegExp object, the actual value is\r
+ // equivalent if it is also a RegExp object that refers to the same source and options\r
+ } else if (actual instanceof RegExp && expected instanceof RegExp) {\r
+ return actual.source === expected.source &&\r
+ actual.global === expected.global &&\r
+ actual.ignoreCase === expected.ignoreCase &&\r
+ actual.multiline === expected.multiline;\r
+\r
+ } else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) {\r
+ return (function() {\r
+ var i, len;\r
+\r
+ for (i = 0, len = expected.length; i < len; i++) {\r
+ if (actual[i] !== expected[i]) {\r
+ return false;\r
+ }\r
+ }\r
+ return actual.length === expected.length;\r
+ })();\r
+ // 7.3. Other pairs that do not both pass typeof value == "object",\r
+ // equivalence is determined by ==.\r
+ } else if (typeof actual != 'object' && typeof expected != 'object') {\r
+ return actual == expected;\r
+\r
+ // 7.4. For all other Object pairs, including Array objects, equivalence is\r
+ // determined by having the same number of owned properties (as verified\r
+ // with Object.prototype.hasOwnProperty.call), the same set of keys\r
+ // (although not necessarily the same order), equivalent values for every\r
+ // corresponding key, and an identical "prototype" property. Note: this\r
+ // accounts for both named and indexed properties on Arrays.\r
+ } else {\r
+ return objEquiv(actual, expected);\r
+ }\r
+}\r
+\r
+function isUndefinedOrNull (value) {\r
+ return value === null || value === undefined;\r
+}\r
+\r
+function isArguments (object) {\r
+ return Object.prototype.toString.call(object) == '[object Arguments]';\r
+}\r
+\r
+function objEquiv (a, b) {\r
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b))\r
+ return false;\r
+ // an identical "prototype" property.\r
+ if (a.prototype !== b.prototype) return false;\r
+ //~~~I've managed to break Object.keys through screwy arguments passing.\r
+ // Converting to array solves the problem.\r
+ if (isArguments(a)) {\r
+ if (!isArguments(b)) {\r
+ return false;\r
+ }\r
+ a = pSlice.call(a);\r
+ b = pSlice.call(b);\r
+ return _deepEqual(a, b);\r
+ }\r
+ try{\r
+ var ka = _keys(a),\r
+ kb = _keys(b),\r
+ key, i;\r
+ } catch (e) {//happens when one is a string literal and the other isn't\r
+ return false;\r
+ }\r
+ // having the same number of owned properties (keys incorporates hasOwnProperty)\r
+ if (ka.length != kb.length)\r
+ return false;\r
+ //the same set of keys (although not necessarily the same order),\r
+ ka.sort();\r
+ kb.sort();\r
+ //~~~cheap key test\r
+ for (i = ka.length - 1; i >= 0; i--) {\r
+ if (ka[i] != kb[i])\r
+ return false;\r
+ }\r
+ //equivalent values for every corresponding key, and\r
+ //~~~possibly expensive deep test\r
+ for (i = ka.length - 1; i >= 0; i--) {\r
+ key = ka[i];\r
+ if (!_deepEqual(a[key], b[key] ))\r
+ return false;\r
+ }\r
+ return true;\r
+}\r
+\r
+// 8. The non-equivalence assertion tests for any deep inequality.\r
+// assert.notDeepEqual(actual, expected, message_opt);\r
+\r
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {\r
+ if (_deepEqual(actual, expected)) {\r
+ fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);\r
+ }\r
+};\r
+\r
+// 9. The strict equality assertion tests strict equality, as determined by ===.\r
+// assert.strictEqual(actual, expected, message_opt);\r
+\r
+assert.strictEqual = function strictEqual(actual, expected, message) {\r
+ if (actual !== expected) {\r
+ fail(actual, expected, message, "===", assert.strictEqual);\r
+ }\r
+};\r
+\r
+// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.\r
+// assert.notStrictEqual(actual, expected, message_opt);\r
+\r
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {\r
+ if (actual === expected) {\r
+ fail(actual, expected, message, "!==", assert.notStrictEqual);\r
+ }\r
+};\r
+\r
+function expectedException(actual, expected) {\r
+ if (!actual || !expected) {\r
+ return false;\r
+ }\r
+\r
+ if (expected instanceof RegExp) {\r
+ return expected.test(actual.message || actual);\r
+ } else if (actual instanceof expected) {\r
+ return true;\r
+ } else if (expected.call({}, actual) === true) {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+function _throws(shouldThrow, block, expected, message) {\r
+ var actual;\r
+\r
+ if (typeof expected === 'string') {\r
+ message = expected;\r
+ expected = null;\r
+ }\r
+\r
+ try {\r
+ block();\r
+ } catch (e) {\r
+ actual = e;\r
+ }\r
+\r
+ message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\r
+ (message ? ' ' + message : '.');\r
+\r
+ if (shouldThrow && !actual) {\r
+ fail('Missing expected exception' + message);\r
+ }\r
+\r
+ if (!shouldThrow && expectedException(actual, expected)) {\r
+ fail('Got unwanted exception' + message);\r
+ }\r
+\r
+ if ((shouldThrow && actual && expected &&\r
+ !expectedException(actual, expected)) || (!shouldThrow && actual)) {\r
+ throw actual;\r
+ }\r
+}\r
+\r
+// 11. Expected to throw an error:\r
+// assert.throws(block, Error_opt, message_opt);\r
+\r
+assert.throws = function(block, /*optional*/error, /*optional*/message) {\r
+ _throws.apply(this, [true].concat(pSlice.call(arguments)));\r
+};\r
+\r
+// EXTENSION! This is annoying to write outside this module.\r
+assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {\r
+ _throws.apply(this, [false].concat(pSlice.call(arguments)));\r
+};\r
+\r
+assert.ifError = function (err) { if (err) {throw err;}};\r
+})(assert);\r
+(function(exports){\r
+/*!\r
+ * Nodeunit\r
+ * Copyright (c) 2010 Caolan McMahon\r
+ * MIT Licensed\r
+ *\r
+ * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\r
+ * Only code on that line will be removed, it's mostly to avoid requiring code\r
+ * that is node specific\r
+ */\r
+\r
+/**\r
+ * Module dependencies\r
+ */\r
+\r
+\r
+\r
+/**\r
+ * Creates assertion objects representing the result of an assert call.\r
+ * Accepts an object or AssertionError as its argument.\r
+ *\r
+ * @param {object} obj\r
+ * @api public\r
+ */\r
+\r
+exports.assertion = function (obj) {\r
+ return {\r
+ method: obj.method || '',\r
+ message: obj.message || (obj.error && obj.error.message) || '',\r
+ error: obj.error,\r
+ passed: function () {\r
+ return !this.error;\r
+ },\r
+ failed: function () {\r
+ return Boolean(this.error);\r
+ }\r
+ };\r
+};\r
+\r
+/**\r
+ * Creates an assertion list object representing a group of assertions.\r
+ * Accepts an array of assertion objects.\r
+ *\r
+ * @param {Array} arr\r
+ * @param {Number} duration\r
+ * @api public\r
+ */\r
+\r
+exports.assertionList = function (arr, duration) {\r
+ var that = arr || [];\r
+ that.failures = function () {\r
+ var failures = 0;\r
+ for (var i = 0; i < this.length; i += 1) {\r
+ if (this[i].failed()) {\r
+ failures += 1;\r
+ }\r
+ }\r
+ return failures;\r
+ };\r
+ that.passes = function () {\r
+ return that.length - that.failures();\r
+ };\r
+ that.duration = duration || 0;\r
+ return that;\r
+};\r
+\r
+/**\r
+ * Create a wrapper function for assert module methods. Executes a callback\r
+ * after it's complete with an assertion object representing the result.\r
+ *\r
+ * @param {Function} callback\r
+ * @api private\r
+ */\r
+\r
+var assertWrapper = function (callback) {\r
+ return function (new_method, assert_method, arity) {\r
+ return function () {\r
+ var message = arguments[arity - 1];\r
+ var a = exports.assertion({method: new_method, message: message});\r
+ try {\r
+ assert[assert_method].apply(null, arguments);\r
+ }\r
+ catch (e) {\r
+ a.error = e;\r
+ }\r
+ callback(a);\r
+ };\r
+ };\r
+};\r
+\r
+/**\r
+ * Creates the 'test' object that gets passed to every test function.\r
+ * Accepts the name of the test function as its first argument, followed by\r
+ * the start time in ms, the options object and a callback function.\r
+ *\r
+ * @param {String} name\r
+ * @param {Number} start\r
+ * @param {Object} options\r
+ * @param {Function} callback\r
+ * @api public\r
+ */\r
+\r
+exports.test = function (name, start, options, callback) {\r
+ var expecting;\r
+ var a_list = [];\r
+\r
+ var wrapAssert = assertWrapper(function (a) {\r
+ a_list.push(a);\r
+ if (options.log) {\r
+ async.nextTick(function () {\r
+ options.log(a);\r
+ });\r
+ }\r
+ });\r
+\r
+ var test = {\r
+ done: function (err) {\r
+ if (expecting !== undefined && expecting !== a_list.length) {\r
+ var e = new Error(\r
+ 'Expected ' + expecting + ' assertions, ' +\r
+ a_list.length + ' ran'\r
+ );\r
+ var a1 = exports.assertion({method: 'expect', error: e});\r
+ a_list.push(a1);\r
+ if (options.log) {\r
+ async.nextTick(function () {\r
+ options.log(a1);\r
+ });\r
+ }\r
+ }\r
+ if (err) {\r
+ var a2 = exports.assertion({error: err});\r
+ a_list.push(a2);\r
+ if (options.log) {\r
+ async.nextTick(function () {\r
+ options.log(a2);\r
+ });\r
+ }\r
+ }\r
+ var end = new Date().getTime();\r
+ async.nextTick(function () {\r
+ var assertion_list = exports.assertionList(a_list, end - start);\r
+ options.testDone(name, assertion_list);\r
+ callback(null, a_list);\r
+ });\r
+ },\r
+ ok: wrapAssert('ok', 'ok', 2),\r
+ same: wrapAssert('same', 'deepEqual', 3),\r
+ equals: wrapAssert('equals', 'equal', 3),\r
+ expect: function (num) {\r
+ expecting = num;\r
+ },\r
+ _assertion_list: a_list\r
+ };\r
+ // add all functions from the assert module\r
+ for (var k in assert) {\r
+ if (assert.hasOwnProperty(k)) {\r
+ test[k] = wrapAssert(k, k, assert[k].length);\r
+ }\r
+ }\r
+ return test;\r
+};\r
+\r
+/**\r
+ * Ensures an options object has all callbacks, adding empty callback functions\r
+ * if any are missing.\r
+ *\r
+ * @param {Object} opt\r
+ * @return {Object}\r
+ * @api public\r
+ */\r
+\r
+exports.options = function (opt) {\r
+ var optionalCallback = function (name) {\r
+ opt[name] = opt[name] || function () {};\r
+ };\r
+\r
+ optionalCallback('moduleStart');\r
+ optionalCallback('moduleDone');\r
+ optionalCallback('testStart');\r
+ optionalCallback('testDone');\r
+ //optionalCallback('log');\r
+\r
+ // 'done' callback is not optional.\r
+\r
+ return opt;\r
+};\r
+})(types);\r
+(function(exports){\r
+/*!\r
+ * Nodeunit\r
+ * Copyright (c) 2010 Caolan McMahon\r
+ * MIT Licensed\r
+ *\r
+ * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\r
+ * Only code on that line will be removed, it's mostly to avoid requiring code\r
+ * that is node specific\r
+ */\r
+\r
+/**\r
+ * Module dependencies\r
+ */\r
+\r
+\r
+\r
+/**\r
+ * Added for browser compatibility\r
+ */\r
+\r
+var _keys = function (obj) {\r
+ if (Object.keys) {\r
+ return Object.keys(obj);\r
+ }\r
+ var keys = [];\r
+ for (var k in obj) {\r
+ if (obj.hasOwnProperty(k)) {\r
+ keys.push(k);\r
+ }\r
+ }\r
+ return keys;\r
+};\r
+\r
+\r
+var _copy = function (obj) {\r
+ var nobj = {};\r
+ var keys = _keys(obj);\r
+ for (var i = 0; i < keys.length; i += 1) {\r
+ nobj[keys[i]] = obj[keys[i]];\r
+ }\r
+ return nobj;\r
+};\r
+\r
+\r
+/**\r
+ * Runs a test function (fn) from a loaded module. After the test function\r
+ * calls test.done(), the callback is executed with an assertionList as its\r
+ * second argument.\r
+ *\r
+ * @param {String} name\r
+ * @param {Function} fn\r
+ * @param {Object} opt\r
+ * @param {Function} callback\r
+ * @api public\r
+ */\r
+\r
+exports.runTest = function (name, fn, opt, callback) {\r
+ var options = types.options(opt);\r
+\r
+ options.testStart(name);\r
+ var start = new Date().getTime();\r
+ var test = types.test(name, start, options, callback);\r
+\r
+ try {\r
+ fn(test);\r
+ }\r
+ catch (e) {\r
+ test.done(e);\r
+ }\r
+};\r
+\r
+/**\r
+ * Takes an object containing test functions or other test suites as properties\r
+ * and runs each in series. After all tests have completed, the callback is\r
+ * called with a list of all assertions as the second argument.\r
+ *\r
+ * If a name is passed to this function it is prepended to all test and suite\r
+ * names that run within it.\r
+ *\r
+ * @param {String} name\r
+ * @param {Object} suite\r
+ * @param {Object} opt\r
+ * @param {Function} callback\r
+ * @api public\r
+ */\r
+\r
+exports.runSuite = function (name, suite, opt, callback) {\r
+ suite = wrapGroup(suite);\r
+ var keys = _keys(suite);\r
+\r
+ async.concatSeries(keys, function (k, cb) {\r
+ var prop = suite[k], _name;\r
+\r
+ _name = name ? [].concat(name, k) : [k];\r
+ _name.toString = function () {\r
+ // fallback for old one\r
+ return this.join(' - ');\r
+ };\r
+\r
+ if (typeof prop === 'function') {\r
+ var in_name = false,\r
+ in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false;\r
+ for (var i = 0; i < _name.length; i += 1) {\r
+ if (_name[i] === opt.testspec) {\r
+ in_name = true;\r
+ }\r
+ }\r
+\r
+ if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) {\r
+ if (opt.moduleStart) {\r
+ opt.moduleStart();\r
+ }\r
+ exports.runTest(_name, suite[k], opt, cb);\r
+ }\r
+ else {\r
+ return cb();\r
+ }\r
+ }\r
+ else {\r
+ exports.runSuite(_name, suite[k], opt, cb);\r
+ }\r
+ }, callback);\r
+};\r
+\r
+/**\r
+ * Run each exported test function or test suite from a loaded module.\r
+ *\r
+ * @param {String} name\r
+ * @param {Object} mod\r
+ * @param {Object} opt\r
+ * @param {Function} callback\r
+ * @api public\r
+ */\r
+\r
+exports.runModule = function (name, mod, opt, callback) {\r
+ var options = _copy(types.options(opt));\r
+\r
+ var _run = false;\r
+ var _moduleStart = options.moduleStart;\r
+\r
+ mod = wrapGroup(mod);\r
+\r
+ function run_once() {\r
+ if (!_run) {\r
+ _run = true;\r
+ _moduleStart(name);\r
+ }\r
+ }\r
+ options.moduleStart = run_once;\r
+\r
+ var start = new Date().getTime();\r
+\r
+ exports.runSuite(null, mod, options, function (err, a_list) {\r
+ var end = new Date().getTime();\r
+ var assertion_list = types.assertionList(a_list, end - start);\r
+ options.moduleDone(name, assertion_list);\r
+ if (nodeunit.complete) {\r
+ nodeunit.complete(name, assertion_list);\r
+ }\r
+ callback(null, a_list);\r
+ });\r
+};\r
+\r
+/**\r
+ * Treats an object literal as a list of modules keyed by name. Runs each\r
+ * module and finished with calling 'done'. You can think of this as a browser\r
+ * safe alternative to runFiles in the nodeunit module.\r
+ *\r
+ * @param {Object} modules\r
+ * @param {Object} opt\r
+ * @api public\r
+ */\r
+\r
+// TODO: add proper unit tests for this function\r
+exports.runModules = function (modules, opt) {\r
+ var all_assertions = [];\r
+ var options = types.options(opt);\r
+ var start = new Date().getTime();\r
+\r
+ async.concatSeries(_keys(modules), function (k, cb) {\r
+ exports.runModule(k, modules[k], options, cb);\r
+ },\r
+ function (err, all_assertions) {\r
+ var end = new Date().getTime();\r
+ options.done(types.assertionList(all_assertions, end - start));\r
+ });\r
+};\r
+\r
+\r
+/**\r
+ * Wraps a test function with setUp and tearDown functions.\r
+ * Used by testCase.\r
+ *\r
+ * @param {Function} setUp\r
+ * @param {Function} tearDown\r
+ * @param {Function} fn\r
+ * @api private\r
+ */\r
+\r
+var wrapTest = function (setUp, tearDown, fn) {\r
+ return function (test) {\r
+ var context = {};\r
+ if (tearDown) {\r
+ var done = test.done;\r
+ test.done = function (err) {\r
+ try {\r
+ tearDown.call(context, function (err2) {\r
+ if (err && err2) {\r
+ test._assertion_list.push(\r
+ types.assertion({error: err})\r
+ );\r
+ return done(err2);\r
+ }\r
+ done(err || err2);\r
+ });\r
+ }\r
+ catch (e) {\r
+ done(e);\r
+ }\r
+ };\r
+ }\r
+ if (setUp) {\r
+ setUp.call(context, function (err) {\r
+ if (err) {\r
+ return test.done(err);\r
+ }\r
+ fn.call(context, test);\r
+ });\r
+ }\r
+ else {\r
+ fn.call(context, test);\r
+ }\r
+ };\r
+};\r
+\r
+\r
+/**\r
+ * Returns a serial callback from two functions.\r
+ *\r
+ * @param {Function} funcFirst\r
+ * @param {Function} funcSecond\r
+ * @api private\r
+ */\r
+\r
+var getSerialCallback = function (fns) {\r
+ if (!fns.length) {\r
+ return null;\r
+ }\r
+ return function (callback) {\r
+ var that = this;\r
+ var bound_fns = [];\r
+ for (var i = 0, len = fns.length; i < len; i++) {\r
+ (function (j) {\r
+ bound_fns.push(function () {\r
+ return fns[j].apply(that, arguments);\r
+ });\r
+ })(i);\r
+ }\r
+ return async.series(bound_fns, callback);\r
+ };\r
+};\r
+\r
+\r
+/**\r
+ * Wraps a group of tests with setUp and tearDown functions.\r
+ * Used by testCase.\r
+ *\r
+ * @param {Object} group\r
+ * @param {Array} setUps - parent setUp functions\r
+ * @param {Array} tearDowns - parent tearDown functions\r
+ * @api private\r
+ */\r
+\r
+var wrapGroup = function (group, setUps, tearDowns) {\r
+ var tests = {};\r
+\r
+ var setUps = setUps ? setUps.slice(): [];\r
+ var tearDowns = tearDowns ? tearDowns.slice(): [];\r
+\r
+ if (group.setUp) {\r
+ setUps.push(group.setUp);\r
+ delete group.setUp;\r
+ }\r
+ if (group.tearDown) {\r
+ tearDowns.unshift(group.tearDown);\r
+ delete group.tearDown;\r
+ }\r
+\r
+ var keys = _keys(group);\r
+\r
+ for (var i = 0; i < keys.length; i += 1) {\r
+ var k = keys[i];\r
+ if (typeof group[k] === 'function') {\r
+ tests[k] = wrapTest(\r
+ getSerialCallback(setUps),\r
+ getSerialCallback(tearDowns),\r
+ group[k]\r
+ );\r
+ }\r
+ else if (typeof group[k] === 'object') {\r
+ tests[k] = wrapGroup(group[k], setUps, tearDowns);\r
+ }\r
+ }\r
+ return tests;\r
+};\r
+\r
+\r
+/**\r
+ * Backwards compatibility for test suites using old testCase API\r
+ */\r
+\r
+exports.testCase = function (suite) {\r
+ return suite;\r
+};\r
+})(core);\r
+(function(exports){\r
+/*!\r
+ * Nodeunit\r
+ * Copyright (c) 2010 Caolan McMahon\r
+ * MIT Licensed\r
+ *\r
+ * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\r
+ * Only code on that line will be removed, its mostly to avoid requiring code\r
+ * that is node specific\r
+ */\r
+\r
+\r
+/**\r
+ * NOTE: this test runner is not listed in index.js because it cannot be\r
+ * used with the command-line tool, only inside the browser.\r
+ */\r
+\r
+\r
+/**\r
+ * Reporter info string\r
+ */\r
+\r
+exports.info = "Browser-based test reporter";\r
+\r
+\r
+/**\r
+ * Run all tests within each module, reporting the results\r
+ *\r
+ * @param {Array} files\r
+ * @api public\r
+ */\r
+\r
+exports.run = function (modules, options) {\r
+ var start = new Date().getTime(), div;\r
+ options = options || {};\r
+ div = options.div || document.body;\r
+\r
+ function setText(el, txt) {\r
+ if ('innerText' in el) {\r
+ el.innerText = txt;\r
+ }\r
+ else if ('textContent' in el){\r
+ el.textContent = txt;\r
+ }\r
+ }\r
+\r
+ function getOrCreate(tag, id) {\r
+ var el = document.getElementById(id);\r
+ if (!el) {\r
+ el = document.createElement(tag);\r
+ el.id = id;\r
+ div.appendChild(el);\r
+ }\r
+ return el;\r
+ };\r
+\r
+ var header = getOrCreate('h1', 'nodeunit-header');\r
+ var banner = getOrCreate('h2', 'nodeunit-banner');\r
+ var userAgent = getOrCreate('h2', 'nodeunit-userAgent');\r
+ var tests = getOrCreate('ol', 'nodeunit-tests');\r
+ var result = getOrCreate('p', 'nodeunit-testresult');\r
+\r
+ setText(userAgent, navigator.userAgent);\r
+\r
+ nodeunit.runModules(modules, {\r
+ moduleStart: function (name) {\r
+ /*var mheading = document.createElement('h2');\r
+ mheading.innerText = name;\r
+ results.appendChild(mheading);\r
+ module = document.createElement('ol');\r
+ results.appendChild(module);*/\r
+ },\r
+ testDone: function (name, assertions) {\r
+ var test = document.createElement('li');\r
+ var strong = document.createElement('strong');\r
+ strong.innerHTML = name + ' <b style="color: black;">(' +\r
+ '<b class="fail">' + assertions.failures() + '</b>, ' +\r
+ '<b class="pass">' + assertions.passes() + '</b>, ' +\r
+ assertions.length +\r
+ ')</b>';\r
+ test.className = assertions.failures() ? 'fail': 'pass';\r
+ test.appendChild(strong);\r
+\r
+ var aList = document.createElement('ol');\r
+ aList.style.display = 'none';\r
+ test.onclick = function () {\r
+ var d = aList.style.display;\r
+ aList.style.display = (d == 'none') ? 'block': 'none';\r
+ };\r
+ for (var i=0; i<assertions.length; i++) {\r
+ var li = document.createElement('li');\r
+ var a = assertions[i];\r
+ if (a.failed()) {\r
+ li.innerHTML = (a.message || a.method || 'no message') +\r
+ '<pre>' + (a.error.stack || a.error) + '</pre>';\r
+ li.className = 'fail';\r
+ }\r
+ else {\r
+ li.innerHTML = a.message || a.method || 'no message';\r
+ li.className = 'pass';\r
+ }\r
+ aList.appendChild(li);\r
+ }\r
+ test.appendChild(aList);\r
+ tests.appendChild(test);\r
+ },\r
+ done: function (assertions) {\r
+ var end = new Date().getTime();\r
+ var duration = end - start;\r
+\r
+ var failures = assertions.failures();\r
+ banner.className = failures ? 'fail': 'pass';\r
+\r
+ result.innerHTML = 'Tests completed in ' + duration +\r
+ ' milliseconds.<br/><span class="passed">' +\r
+ assertions.passes() + '</span> assertions of ' +\r
+ '<span class="all">' + assertions.length + '<span> passed, ' +\r
+ assertions.failures() + ' failed.';\r
+ }\r
+ });\r
+};\r
+})(reporter);\r
+nodeunit = core;\r
+nodeunit.assert = assert;\r
+nodeunit.reporter = reporter;\r
+nodeunit.run = reporter.run;\r
+return nodeunit; })();\r