ethstats-server/web-app/.meteor/local/build/programs/server/packages/ejson.js.map
2015-08-14 19:22:53 +02:00

1 line
24 KiB
Plaintext

{"version":3,"sources":["ejson/ejson.js","ejson/stringify.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,G;AACA,a;AACA,yC;AACA,G;AACA,W;AACA,e;;;;AAIA,mC;AACA,G;AACA,oB;AACA,2B;AACA,kB;AACA,2E;AACA,uC;AACA,G;;AAEA,G;AACA,qB;AACA,6B;AACA,mJ;AACA,kB;AACA,Y;AACA,G;;AAEA,G;AACA,wB;AACA,6B;AACA,iE;AACA,kB;AACA,Y;AACA,G;;AAEA,G;AACA,kB;AACA,6B;AACA,gI;AACA,kB;AACA,Y;AACA,G;;AAEA,G;AACA,mB;AACA,6B;AACA,oF;AACA,kB;AACA,2D;AACA,Y;AACA,G;;;AAGA,qB;AACA,iE;AACA,+D;AACA,6C;AACA,8B;AACA,4D;AACA,sE;AACA,qD;AACA,oE;AACA,6D;AACA,gB;AACA,oE;AACA,iD;AACA,G;AACA,2C;AACA,kB;AACA,+K;AACA,oM;AACA,G;AACA,0C;AACA,+B;AACA,yD;AACA,8B;AACA,E;;AAEA,iC;AACA,+D;AACA,E;;AAEA,yB;AACA,W;AACA,oC;AACA,sD;AACA,M;AACA,iC;AACA,iC;AACA,M;AACA,iC;AACA,oC;AACA,M;AACA,mC;AACA,iC;AACA,K;AACA,I;AACA,2E;AACA,uB;AACA,oC;AACA,wD;AACA,M;AACA,4B;AACA,iC;AACA,e;AACA,uB;AACA,iB;AACA,gC;AACA,iB;AACA,U;AACA,kB;AACA,6B;AACA,M;AACA,mC;AACA,2B;AACA,K;AACA,I;AACA,a;AACA,oC;AACA,wD;AACA,M;AACA,iC;AACA,2E;AACA,sD;AACA,M;AACA,iC;AACA,2C;AACA,M;AACA,mC;AACA,wC;AACA,K;AACA,I;AACA,yB;AACA,oC;AACA,wD;AACA,M;AACA,iC;AACA,8C;AACA,qB;AACA,O;AACA,4D;AACA,6C;AACA,S;AACA,M;AACA,iC;AACA,sB;AACA,yC;AACA,+C;AACA,S;AACA,+B;AACA,M;AACA,mC;AACA,sB;AACA,iD;AACA,iD;AACA,S;AACA,oB;AACA,K;AACA,I;AACA,a;AACA,oC;AACA,8E;AACA,M;AACA,iC;AACA,sC;AACA,M;AACA,iC;AACA,2D;AACA,iC;AACA,S;AACA,wD;AACA,M;AACA,mC;AACA,+B;AACA,wC;AACA,6E;AACA,4C;AACA,kD;AACA,qC;AACA,S;AACA,K;AACA,G;AACA,E;;AAEA,sC;AACA,e;AACA,4C;AACA,yC;AACA,uC;AACA,E;;;AAGA,sD;AACA,4B;AACA,gD;AACA,0C;AACA,mB;AACA,gB;AACA,4C;AACA,iC;AACA,wB;;AAEA,+B;AACA,8B;AACA,e;;AAEA,4C;AACA,qC;AACA,2D;AACA,2B;AACA,yB;;AAEA,2C;AACA,kB;AACA,yB;AACA,mC;AACA,K;AACA,4D;AACA,+B;AACA,kC;AACA,K;AACA,a;AACA,E;;AAEA,8E;AACA,sE;AACA,yC;AACA,sD;AACA,yC;AACA,sC;AACA,yC;AACA,K;AACA,G;AACA,mB;AACA,E;;AAEA,G;AACA,mF;AACA,kB;AACA,yD;AACA,G;AACA,qC;AACA,wC;AACA,4B;AACA,mB;AACA,iC;AACA,6B;AACA,iC;AACA,G;AACA,c;AACA,E;;AAEA,sD;AACA,uD;AACA,6D;AACA,E;AACA,8B;AACA,kD;AACA,mB;AACA,gB;AACA,8C;AACA,2B;AACA,wB;;AAEA,+B;AACA,8B;AACA,e;;AAEA,qC;AACA,oC;AACA,+C;AACA,8B;AACA,2B;AACA,e;AACA,O;AACA,8D;AACA,iC;AACA,sC;AACA,K;AACA,K;AACA,a;AACA,E;;AAEA,0D;AACA,6D;;AAEA,uE;AACA,sB;AACA,4C;AACA,oD;AACA,0B;AACA,yC;AACA,iE;AACA,a;AACA,0D;AACA,6C;AACA,8C;AACA,gD;AACA,S;AACA,O;AACA,K;AACA,G;AACA,e;AACA,E;;AAEA,G;AACA,0E;AACA,kB;AACA,iE;AACA,G;AACA,uC;AACA,0C;AACA,qD;AACA,6B;AACA,mC;AACA,gB;AACA,U;AACA,mB;AACA,G;AACA,E;;AAEA,G;AACA,0C;;AAEA,kI;AACA,kB;AACA,2C;AACA,4B;AACA,2P;AACA,iG;AACA,G;AACA,4C;AACA,qC;AACA,yD;AACA,oD;AACA,U;AACA,gC;AACA,G;AACA,E;;AAEA,G;AACA,iG;AACA,kB;AACA,6D;AACA,G;AACA,+B;AACA,+B;AACA,+D;AACA,+C;AACA,E;;AAEA,G;AACA,oH;AACA,2C;AACA,kB;AACA,G;AACA,iC;AACA,+E;AACA,sC;AACA,E;;AAEA,G;AACA,2K;AACA,kB;AACA,mB;AACA,mB;AACA,4B;AACA,uP;AACA,G;AACA,yC;AACA,Q;AACA,mE;AACA,c;AACA,gB;AACA,+B;AACA,uF;AACA,4F;AACA,4E;AACA,iB;AACA,wD;AACA,iB;AACA,6C;AACA,uC;AACA,+C;AACA,8B;AACA,mB;AACA,oC;AACA,wB;AACA,qB;AACA,K;AACA,gB;AACA,G;AACA,uC;AACA,gC;AACA,uC;AACA,gC;AACA,2B;AACA,8B;AACA,mB;AACA,8B;AACA,mB;AACA,oC;AACA,6C;AACA,qB;AACA,K;AACA,gB;AACA,G;AACA,oE;AACA,4D;AACA,yB;AACA,4E;AACA,G;AACA,gD;AACA,U;AACA,0B;AACA,mB;AACA,iC;AACA,sB;AACA,O;AACA,U;AACA,sC;AACA,8B;AACA,qB;AACA,O;AACA,2B;AACA,qB;AACA,O;AACA,qD;AACA,qB;AACA,O;AACA,U;AACA,kB;AACA,O;AACA,qC;AACA,U;AACA,U;AACA,wC;AACA,2B;AACA,qB;AACA,O;AACA,gD;AACA,qB;AACA,O;AACA,U;AACA,kB;AACA,O;AACA,kC;AACA,G;AACA,E;;AAEA,G;AACA,wC;AACA,kB;AACA,sC;AACA,G;AACA,4B;AACA,U;AACA,4B;AACA,a;AACA,iB;AACA,4C;AACA,wB;AACA,iC;AACA,8E;AACA,8E;AACA,0B;AACA,a;AACA,0B;AACA,oC;AACA,wC;AACA,oB;AACA,K;AACA,e;AACA,G;AACA,wD;AACA,yC;AACA,+E;AACA,iB;AACA,a;AACA,kC;AACA,iC;AACA,e;AACA,G;AACA,0E;AACA,sC;AACA,qB;AACA,G;AACA,8B;AACA,+B;AACA,wE;AACA,G;AACA,yB;AACA,W;AACA,mC;AACA,kC;AACA,K;AACA,a;AACA,E;;AAEA,G;AACA,0E;AACA,kB;AACA,uE;AACA,G;AACA,uE;AACA,6D;AACA,uE;AACA,qE;AACA,8B;AACA,mC;;;;;;;;;;;;;;;;;;;AC5fA,qE;AACA,E;AACA,c;AACA,gB;AACA,E;AACA,oB;AACA,E;AACA,6D;;AAEA,wB;AACA,gC;AACA,C;;AAEA,wE;;AAEA,uC;;AAEA,sC;AACA,oC;AACA,sC;AACA,a;AACA,gC;AACA,c;AACA,0B;;AAEA,mD;;AAEA,yB;AACA,gB;AACA,wB;AACA,gB;AACA,sE;AACA,oD;AACA,iB;AACA,yB;AACA,+E;AACA,U;AACA,gB;AACA,6E;AACA,kC;AACA,iB;AACA,oB;AACA,K;AACA,mF;AACA,6C;AACA,iB;;AAEA,6B;AACA,mD;;AAEA,kF;AACA,6B;;AAEA,4B;AACA,uC;AACA,mF;AACA,O;;AAEA,mF;AACA,kB;;AAEA,iC;AACA,iB;AACA,+B;AACA,+F;AACA,c;AACA,0C;AACA,O;AACA,e;AACA,K;;;AAGA,qD;AACA,6B;AACA,kB;AACA,yB;AACA,+B;AACA,8D;AACA,c;AACA,gE;AACA,O;AACA,O;;;AAGA,oE;AACA,+B;;AAEA,+B;AACA,e;AACA,6B;AACA,6F;AACA,Y;AACA,wC;AACA,K;AACA,a;AACA,G;AACA,C;;AAEA,wE;;AAEA,uD;AACA,sE;AACA,iD;AACA,sB;AACA,e;AACA,oB;AACA,c;AACA,gC;AACA,0B;AACA,kD;AACA,uB;AACA,8C;AACA,uB;AACA,K;AACA,+B;AACA,G;AACA,qE;AACA,E","file":"/packages/ejson.js","sourcesContent":["/**\n * @namespace\n * @summary Namespace for EJSON functions\n */\nEJSON = {};\nEJSONTest = {};\n\n\n\n// Custom type interface definition\n/**\n * @class CustomType\n * @instanceName customType\n * @memberOf EJSON\n * @summary The interface that a class must satisfy to be able to become an\n * EJSON custom type via EJSON.addType.\n */\n\n/**\n * @function typeName\n * @memberOf EJSON.CustomType\n * @summary Return the tag used to identify this type. This must match the tag used to register this type with [`EJSON.addType`](#ejson_add_type).\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function toJSONValue\n * @memberOf EJSON.CustomType\n * @summary Serialize this instance into a JSON-compatible value.\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function clone\n * @memberOf EJSON.CustomType\n * @summary Return a value `r` such that `this.equals(r)` is true, and modifications to `r` do not affect `this` and vice versa.\n * @locus Anywhere\n * @instance\n */\n\n/**\n * @function equals\n * @memberOf EJSON.CustomType\n * @summary Return `true` if `other` has a value equal to `this`; `false` otherwise.\n * @locus Anywhere\n * @param {Object} other Another object to compare this to.\n * @instance\n */\n\n\nvar customTypes = {};\n// Add a custom type, using a method of your choice to get to and\n// from a basic JSON-able representation. The factory argument\n// is a function of JSON-able --> your object\n// The type you add must have:\n// - A toJSONValue() method, so that Meteor can serialize it\n// - a typeName() method, to show how to look it up in our type table.\n// It is okay if these methods are monkey-patched on.\n// EJSON.clone will use toJSONValue and the given factory to produce\n// a clone, but you may specify a method clone() that will be\n// used instead.\n// Similarly, EJSON.equals will use toJSONValue to make comparisons,\n// but you may provide a method equals() instead.\n/**\n * @summary Add a custom datatype to EJSON.\n * @locus Anywhere\n * @param {String} name A tag for your custom type; must be unique among custom data types defined in your project, and must match the result of your type's `typeName` method.\n * @param {Function} factory A function that deserializes a JSON-compatible value into an instance of your type. This should match the serialization performed by your type's `toJSONValue` method.\n */\nEJSON.addType = function (name, factory) {\n if (_.has(customTypes, name))\n throw new Error(\"Type \" + name + \" already present\");\n customTypes[name] = factory;\n};\n\nvar isInfOrNan = function (obj) {\n return _.isNaN(obj) || obj === Infinity || obj === -Infinity;\n};\n\nvar builtinConverters = [\n { // Date\n matchJSONValue: function (obj) {\n return _.has(obj, '$date') && _.size(obj) === 1;\n },\n matchObject: function (obj) {\n return obj instanceof Date;\n },\n toJSONValue: function (obj) {\n return {$date: obj.getTime()};\n },\n fromJSONValue: function (obj) {\n return new Date(obj.$date);\n }\n },\n { // NaN, Inf, -Inf. (These are the only objects with typeof !== 'object'\n // which we match.)\n matchJSONValue: function (obj) {\n return _.has(obj, '$InfNaN') && _.size(obj) === 1;\n },\n matchObject: isInfOrNan,\n toJSONValue: function (obj) {\n var sign;\n if (_.isNaN(obj))\n sign = 0;\n else if (obj === Infinity)\n sign = 1;\n else\n sign = -1;\n return {$InfNaN: sign};\n },\n fromJSONValue: function (obj) {\n return obj.$InfNaN/0;\n }\n },\n { // Binary\n matchJSONValue: function (obj) {\n return _.has(obj, '$binary') && _.size(obj) === 1;\n },\n matchObject: function (obj) {\n return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array\n || (obj && _.has(obj, '$Uint8ArrayPolyfill'));\n },\n toJSONValue: function (obj) {\n return {$binary: Base64.encode(obj)};\n },\n fromJSONValue: function (obj) {\n return Base64.decode(obj.$binary);\n }\n },\n { // Escaping one level\n matchJSONValue: function (obj) {\n return _.has(obj, '$escape') && _.size(obj) === 1;\n },\n matchObject: function (obj) {\n if (_.isEmpty(obj) || _.size(obj) > 2) {\n return false;\n }\n return _.any(builtinConverters, function (converter) {\n return converter.matchJSONValue(obj);\n });\n },\n toJSONValue: function (obj) {\n var newObj = {};\n _.each(obj, function (value, key) {\n newObj[key] = EJSON.toJSONValue(value);\n });\n return {$escape: newObj};\n },\n fromJSONValue: function (obj) {\n var newObj = {};\n _.each(obj.$escape, function (value, key) {\n newObj[key] = EJSON.fromJSONValue(value);\n });\n return newObj;\n }\n },\n { // Custom\n matchJSONValue: function (obj) {\n return _.has(obj, '$type') && _.has(obj, '$value') && _.size(obj) === 2;\n },\n matchObject: function (obj) {\n return EJSON._isCustomType(obj);\n },\n toJSONValue: function (obj) {\n var jsonValue = Meteor._noYieldsAllowed(function () {\n return obj.toJSONValue();\n });\n return {$type: obj.typeName(), $value: jsonValue};\n },\n fromJSONValue: function (obj) {\n var typeName = obj.$type;\n if (!_.has(customTypes, typeName))\n throw new Error(\"Custom EJSON type \" + typeName + \" is not defined\");\n var converter = customTypes[typeName];\n return Meteor._noYieldsAllowed(function () {\n return converter(obj.$value);\n });\n }\n }\n];\n\nEJSON._isCustomType = function (obj) {\n return obj &&\n typeof obj.toJSONValue === 'function' &&\n typeof obj.typeName === 'function' &&\n _.has(customTypes, obj.typeName());\n};\n\n\n// for both arrays and objects, in-place modification.\nvar adjustTypesToJSONValue =\nEJSON._adjustTypesToJSONValue = function (obj) {\n // Is it an atom that we need to adjust?\n if (obj === null)\n return null;\n var maybeChanged = toJSONValueHelper(obj);\n if (maybeChanged !== undefined)\n return maybeChanged;\n\n // Other atoms are unchanged.\n if (typeof obj !== 'object')\n return obj;\n\n // Iterate over array or object structure.\n _.each(obj, function (value, key) {\n if (typeof value !== 'object' && value !== undefined &&\n !isInfOrNan(value))\n return; // continue\n\n var changed = toJSONValueHelper(value);\n if (changed) {\n obj[key] = changed;\n return; // on to the next key\n }\n // if we get here, value is an object but not adjustable\n // at this level. recurse.\n adjustTypesToJSONValue(value);\n });\n return obj;\n};\n\n// Either return the JSON-compatible version of the argument, or undefined (if\n// the item isn't itself replaceable, but maybe some fields in it are)\nvar toJSONValueHelper = function (item) {\n for (var i = 0; i < builtinConverters.length; i++) {\n var converter = builtinConverters[i];\n if (converter.matchObject(item)) {\n return converter.toJSONValue(item);\n }\n }\n return undefined;\n};\n\n/**\n * @summary Serialize an EJSON-compatible value into its plain JSON representation.\n * @locus Anywhere\n * @param {EJSON} val A value to serialize to plain JSON.\n */\nEJSON.toJSONValue = function (item) {\n var changed = toJSONValueHelper(item);\n if (changed !== undefined)\n return changed;\n if (typeof item === 'object') {\n item = EJSON.clone(item);\n adjustTypesToJSONValue(item);\n }\n return item;\n};\n\n// for both arrays and objects. Tries its best to just\n// use the object you hand it, but may return something\n// different if the object you hand it itself needs changing.\n//\nvar adjustTypesFromJSONValue =\nEJSON._adjustTypesFromJSONValue = function (obj) {\n if (obj === null)\n return null;\n var maybeChanged = fromJSONValueHelper(obj);\n if (maybeChanged !== obj)\n return maybeChanged;\n\n // Other atoms are unchanged.\n if (typeof obj !== 'object')\n return obj;\n\n _.each(obj, function (value, key) {\n if (typeof value === 'object') {\n var changed = fromJSONValueHelper(value);\n if (value !== changed) {\n obj[key] = changed;\n return;\n }\n // if we get here, value is an object but not adjustable\n // at this level. recurse.\n adjustTypesFromJSONValue(value);\n }\n });\n return obj;\n};\n\n// Either return the argument changed to have the non-json\n// rep of itself (the Object version) or the argument itself.\n\n// DOES NOT RECURSE. For actually getting the fully-changed value, use\n// EJSON.fromJSONValue\nvar fromJSONValueHelper = function (value) {\n if (typeof value === 'object' && value !== null) {\n if (_.size(value) <= 2\n && _.all(value, function (v, k) {\n return typeof k === 'string' && k.substr(0, 1) === '$';\n })) {\n for (var i = 0; i < builtinConverters.length; i++) {\n var converter = builtinConverters[i];\n if (converter.matchJSONValue(value)) {\n return converter.fromJSONValue(value);\n }\n }\n }\n }\n return value;\n};\n\n/**\n * @summary Deserialize an EJSON value from its plain JSON representation.\n * @locus Anywhere\n * @param {JSONCompatible} val A value to deserialize into EJSON.\n */\nEJSON.fromJSONValue = function (item) {\n var changed = fromJSONValueHelper(item);\n if (changed === item && typeof item === 'object') {\n item = EJSON.clone(item);\n adjustTypesFromJSONValue(item);\n return item;\n } else {\n return changed;\n }\n};\n\n/**\n * @summary Serialize a value to a string.\n\nFor EJSON values, the serialization fully represents the value. For non-EJSON values, serializes the same way as `JSON.stringify`.\n * @locus Anywhere\n * @param {EJSON} val A value to stringify.\n * @param {Object} [options]\n * @param {Boolean | Integer | String} options.indent Indents objects and arrays for easy readability. When `true`, indents by 2 spaces; when an integer, indents by that number of spaces; and when a string, uses the string as the indentation pattern.\n * @param {Boolean} options.canonical When `true`, stringifies keys in an object in sorted order.\n */\nEJSON.stringify = function (item, options) {\n var json = EJSON.toJSONValue(item);\n if (options && (options.canonical || options.indent)) {\n return EJSON._canonicalStringify(json, options);\n } else {\n return JSON.stringify(json);\n }\n};\n\n/**\n * @summary Parse a string into an EJSON value. Throws an error if the string is not valid EJSON.\n * @locus Anywhere\n * @param {String} str A string to parse into an EJSON value.\n */\nEJSON.parse = function (item) {\n if (typeof item !== 'string')\n throw new Error(\"EJSON.parse argument should be a string\");\n return EJSON.fromJSONValue(JSON.parse(item));\n};\n\n/**\n * @summary Returns true if `x` is a buffer of binary data, as returned from [`EJSON.newBinary`](#ejson_new_binary).\n * @param {Object} x The variable to check.\n * @locus Anywhere\n */\nEJSON.isBinary = function (obj) {\n return !!((typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array) ||\n (obj && obj.$Uint8ArrayPolyfill));\n};\n\n/**\n * @summary Return true if `a` and `b` are equal to each other. Return false otherwise. Uses the `equals` method on `a` if present, otherwise performs a deep comparison.\n * @locus Anywhere\n * @param {EJSON} a\n * @param {EJSON} b\n * @param {Object} [options]\n * @param {Boolean} options.keyOrderSensitive Compare in key sensitive order, if supported by the JavaScript implementation. For example, `{a: 1, b: 2}` is equal to `{b: 2, a: 1}` only when `keyOrderSensitive` is `false`. The default is `false`.\n */\nEJSON.equals = function (a, b, options) {\n var i;\n var keyOrderSensitive = !!(options && options.keyOrderSensitive);\n if (a === b)\n return true;\n if (_.isNaN(a) && _.isNaN(b))\n return true; // This differs from the IEEE spec for NaN equality, b/c we don't want\n // anything ever with a NaN to be poisoned from becoming equal to anything.\n if (!a || !b) // if either one is falsy, they'd have to be === to be equal\n return false;\n if (!(typeof a === 'object' && typeof b === 'object'))\n return false;\n if (a instanceof Date && b instanceof Date)\n return a.valueOf() === b.valueOf();\n if (EJSON.isBinary(a) && EJSON.isBinary(b)) {\n if (a.length !== b.length)\n return false;\n for (i = 0; i < a.length; i++) {\n if (a[i] !== b[i])\n return false;\n }\n return true;\n }\n if (typeof (a.equals) === 'function')\n return a.equals(b, options);\n if (typeof (b.equals) === 'function')\n return b.equals(a, options);\n if (a instanceof Array) {\n if (!(b instanceof Array))\n return false;\n if (a.length !== b.length)\n return false;\n for (i = 0; i < a.length; i++) {\n if (!EJSON.equals(a[i], b[i], options))\n return false;\n }\n return true;\n }\n // fallback for custom types that don't implement their own equals\n switch (EJSON._isCustomType(a) + EJSON._isCustomType(b)) {\n case 1: return false;\n case 2: return EJSON.equals(EJSON.toJSONValue(a), EJSON.toJSONValue(b));\n }\n // fall back to structural equality of objects\n var ret;\n if (keyOrderSensitive) {\n var bKeys = [];\n _.each(b, function (val, x) {\n bKeys.push(x);\n });\n i = 0;\n ret = _.all(a, function (val, x) {\n if (i >= bKeys.length) {\n return false;\n }\n if (x !== bKeys[i]) {\n return false;\n }\n if (!EJSON.equals(val, b[bKeys[i]], options)) {\n return false;\n }\n i++;\n return true;\n });\n return ret && i === bKeys.length;\n } else {\n i = 0;\n ret = _.all(a, function (val, key) {\n if (!_.has(b, key)) {\n return false;\n }\n if (!EJSON.equals(val, b[key], options)) {\n return false;\n }\n i++;\n return true;\n });\n return ret && _.size(b) === i;\n }\n};\n\n/**\n * @summary Return a deep copy of `val`.\n * @locus Anywhere\n * @param {EJSON} val A value to copy.\n */\nEJSON.clone = function (v) {\n var ret;\n if (typeof v !== \"object\")\n return v;\n if (v === null)\n return null; // null has typeof \"object\"\n if (v instanceof Date)\n return new Date(v.getTime());\n // RegExps are not really EJSON elements (eg we don't define a serialization\n // for them), but they're immutable anyway, so we can support them in clone.\n if (v instanceof RegExp)\n return v;\n if (EJSON.isBinary(v)) {\n ret = EJSON.newBinary(v.length);\n for (var i = 0; i < v.length; i++) {\n ret[i] = v[i];\n }\n return ret;\n }\n // XXX: Use something better than underscore's isArray\n if (_.isArray(v) || _.isArguments(v)) {\n // For some reason, _.map doesn't work in this context on Opera (weird test\n // failures).\n ret = [];\n for (i = 0; i < v.length; i++)\n ret[i] = EJSON.clone(v[i]);\n return ret;\n }\n // handle general user-defined typed Objects if they have a clone method\n if (typeof v.clone === 'function') {\n return v.clone();\n }\n // handle other custom types\n if (EJSON._isCustomType(v)) {\n return EJSON.fromJSONValue(EJSON.clone(EJSON.toJSONValue(v)), true);\n }\n // handle other objects\n ret = {};\n _.each(v, function (value, key) {\n ret[key] = EJSON.clone(value);\n });\n return ret;\n};\n\n/**\n * @summary Allocate a new buffer of binary data that EJSON can serialize.\n * @locus Anywhere\n * @param {Number} size The number of bytes of binary data to allocate.\n */\n// EJSON.newBinary is the public documented API for this functionality,\n// but the implementation is in the 'base64' package to avoid\n// introducing a circular dependency. (If the implementation were here,\n// then 'base64' would have to use EJSON.newBinary, and 'ejson' would\n// also have to use 'base64'.)\nEJSON.newBinary = Base64.newBinary;\n","// Based on json2.js from https://github.com/douglascrockford/JSON-js\n//\n// json2.js\n// 2012-10-08\n//\n// Public Domain.\n//\n// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\nfunction quote(string) {\n return JSON.stringify(string);\n}\n\nvar str = function (key, holder, singleIndent, outerIndent, canonical) {\n\n // Produce a string from holder[key].\n\n var i; // The loop counter.\n var k; // The member key.\n var v; // The member value.\n var length;\n var innerIndent = outerIndent;\n var partial;\n var value = holder[key];\n\n // What happens next depends on the value's type.\n\n switch (typeof value) {\n case 'string':\n return quote(value);\n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null';\n case 'boolean':\n return String(value);\n // If the type is 'object', we might be dealing with an object or an array or\n // null.\n case 'object':\n // Due to a specification blunder in ECMAScript, typeof null is 'object',\n // so watch out for that case.\n if (!value) {\n return 'null';\n }\n // Make an array to hold the partial results of stringifying this object value.\n innerIndent = outerIndent + singleIndent;\n partial = [];\n\n // Is the value an array?\n if (_.isArray(value) || _.isArguments(value)) {\n\n // The value is an array. Stringify every element. Use null as a placeholder\n // for non-JSON values.\n\n length = value.length;\n for (i = 0; i < length; i += 1) {\n partial[i] = str(i, value, singleIndent, innerIndent, canonical) || 'null';\n }\n\n // Join all of the elements together, separated with commas, and wrap them in\n // brackets.\n\n if (partial.length === 0) {\n v = '[]';\n } else if (innerIndent) {\n v = '[\\n' + innerIndent + partial.join(',\\n' + innerIndent) + '\\n' + outerIndent + ']';\n } else {\n v = '[' + partial.join(',') + ']';\n }\n return v;\n }\n\n\n // Iterate through all of the keys in the object.\n var keys = _.keys(value);\n if (canonical)\n keys = keys.sort();\n _.each(keys, function (k) {\n v = str(k, value, singleIndent, innerIndent, canonical);\n if (v) {\n partial.push(quote(k) + (innerIndent ? ': ' : ':') + v);\n }\n });\n\n\n // Join all of the member texts together, separated with commas,\n // and wrap them in braces.\n\n if (partial.length === 0) {\n v = '{}';\n } else if (innerIndent) {\n v = '{\\n' + innerIndent + partial.join(',\\n' + innerIndent) + '\\n' + outerIndent + '}';\n } else {\n v = '{' + partial.join(',') + '}';\n }\n return v;\n }\n}\n\n// If the JSON object does not yet have a stringify method, give it one.\n\nEJSON._canonicalStringify = function (value, options) {\n // Make a fake root object containing our value under the key of ''.\n // Return the result of stringifying the value.\n options = _.extend({\n indent: \"\",\n canonical: false\n }, options);\n if (options.indent === true) {\n options.indent = \" \";\n } else if (typeof options.indent === 'number') {\n var newIndent = \"\";\n for (var i = 0; i < options.indent; i++) {\n newIndent += ' ';\n }\n options.indent = newIndent;\n }\n return str('', {'': value}, options.indent, \"\", options.canonical);\n};\n"]}