services/sync/tps/extensions/mozmill/resource/stdlib/json2.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/services/sync/tps/extensions/mozmill/resource/stdlib/json2.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,469 @@
     1.4 +/*
     1.5 +    http://www.JSON.org/json2.js
     1.6 +    2008-05-25
     1.7 +
     1.8 +    Public Domain.
     1.9 +
    1.10 +    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
    1.11 +
    1.12 +    See http://www.JSON.org/js.html
    1.13 +
    1.14 +    This file creates a global JSON object containing two methods: stringify
    1.15 +    and parse.
    1.16 +
    1.17 +        JSON.stringify(value, replacer, space)
    1.18 +            value       any JavaScript value, usually an object or array.
    1.19 +
    1.20 +            replacer    an optional parameter that determines how object
    1.21 +                        values are stringified for objects without a toJSON
    1.22 +                        method. It can be a function or an array.
    1.23 +
    1.24 +            space       an optional parameter that specifies the indentation
    1.25 +                        of nested structures. If it is omitted, the text will
    1.26 +                        be packed without extra whitespace. If it is a number,
    1.27 +                        it will specify the number of spaces to indent at each
    1.28 +                        level. If it is a string (such as '\t' or ' '),
    1.29 +                        it contains the characters used to indent at each level.
    1.30 +
    1.31 +            This method produces a JSON text from a JavaScript value.
    1.32 +
    1.33 +            When an object value is found, if the object contains a toJSON
    1.34 +            method, its toJSON method will be called and the result will be
    1.35 +            stringified. A toJSON method does not serialize: it returns the
    1.36 +            value represented by the name/value pair that should be serialized,
    1.37 +            or undefined if nothing should be serialized. The toJSON method
    1.38 +            will be passed the key associated with the value, and this will be
    1.39 +            bound to the object holding the key.
    1.40 +
    1.41 +            For example, this would serialize Dates as ISO strings.
    1.42 +
    1.43 +                Date.prototype.toJSON = function (key) {
    1.44 +                    function f(n) {
    1.45 +                        // Format integers to have at least two digits.
    1.46 +                        return n < 10 ? '0' + n : n;
    1.47 +                    }
    1.48 +
    1.49 +                    return this.getUTCFullYear()   + '-' +
    1.50 +                         f(this.getUTCMonth() + 1) + '-' +
    1.51 +                         f(this.getUTCDate())      + 'T' +
    1.52 +                         f(this.getUTCHours())     + ':' +
    1.53 +                         f(this.getUTCMinutes())   + ':' +
    1.54 +                         f(this.getUTCSeconds())   + 'Z';
    1.55 +                };
    1.56 +
    1.57 +            You can provide an optional replacer method. It will be passed the
    1.58 +            key and value of each member, with this bound to the containing
    1.59 +            object. The value that is returned from your method will be
    1.60 +            serialized. If your method returns undefined, then the member will
    1.61 +            be excluded from the serialization.
    1.62 +
    1.63 +            If the replacer parameter is an array, then it will be used to
    1.64 +            select the members to be serialized. It filters the results such
    1.65 +            that only members with keys listed in the replacer array are
    1.66 +            stringified.
    1.67 +
    1.68 +            Values that do not have JSON representations, such as undefined or
    1.69 +            functions, will not be serialized. Such values in objects will be
    1.70 +            dropped; in arrays they will be replaced with null. You can use
    1.71 +            a replacer function to replace those with JSON values.
    1.72 +            JSON.stringify(undefined) returns undefined.
    1.73 +
    1.74 +            The optional space parameter produces a stringification of the
    1.75 +            value that is filled with line breaks and indentation to make it
    1.76 +            easier to read.
    1.77 +
    1.78 +            If the space parameter is a non-empty string, then that string will
    1.79 +            be used for indentation. If the space parameter is a number, then
    1.80 +            the indentation will be that many spaces.
    1.81 +
    1.82 +            Example:
    1.83 +
    1.84 +            text = JSON.stringify(['e', {pluribus: 'unum'}]);
    1.85 +            // text is '["e",{"pluribus":"unum"}]'
    1.86 +
    1.87 +
    1.88 +            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
    1.89 +            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
    1.90 +
    1.91 +            text = JSON.stringify([new Date()], function (key, value) {
    1.92 +                return this[key] instanceof Date ?
    1.93 +                    'Date(' + this[key] + ')' : value;
    1.94 +            });
    1.95 +            // text is '["Date(---current time---)"]'
    1.96 +
    1.97 +
    1.98 +        JSON.parse(text, reviver)
    1.99 +            This method parses a JSON text to produce an object or array.
   1.100 +            It can throw a SyntaxError exception.
   1.101 +
   1.102 +            The optional reviver parameter is a function that can filter and
   1.103 +            transform the results. It receives each of the keys and values,
   1.104 +            and its return value is used instead of the original value.
   1.105 +            If it returns what it received, then the structure is not modified.
   1.106 +            If it returns undefined then the member is deleted.
   1.107 +
   1.108 +            Example:
   1.109 +
   1.110 +            // Parse the text. Values that look like ISO date strings will
   1.111 +            // be converted to Date objects.
   1.112 +
   1.113 +            myData = JSON.parse(text, function (key, value) {
   1.114 +                var a;
   1.115 +                if (typeof value === 'string') {
   1.116 +                    a =
   1.117 +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
   1.118 +                    if (a) {
   1.119 +                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
   1.120 +                            +a[5], +a[6]));
   1.121 +                    }
   1.122 +                }
   1.123 +                return value;
   1.124 +            });
   1.125 +
   1.126 +            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
   1.127 +                var d;
   1.128 +                if (typeof value === 'string' &&
   1.129 +                        value.slice(0, 5) === 'Date(' &&
   1.130 +                        value.slice(-1) === ')') {
   1.131 +                    d = new Date(value.slice(5, -1));
   1.132 +                    if (d) {
   1.133 +                        return d;
   1.134 +                    }
   1.135 +                }
   1.136 +                return value;
   1.137 +            });
   1.138 +
   1.139 +
   1.140 +    This is a reference implementation. You are free to copy, modify, or
   1.141 +    redistribute.
   1.142 +
   1.143 +    This code should be minified before deployment.
   1.144 +    See http://javascript.crockford.com/jsmin.html
   1.145 +
   1.146 +    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
   1.147 +    NOT CONTROL.
   1.148 +*/
   1.149 +
   1.150 +/*jslint evil: true */
   1.151 +
   1.152 +/*global JSON */
   1.153 +
   1.154 +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", call,
   1.155 +    charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes,
   1.156 +    getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length,
   1.157 +    parse, propertyIsEnumerable, prototype, push, replace, slice, stringify,
   1.158 +    test, toJSON, toString
   1.159 +*/
   1.160 +
   1.161 +var EXPORTED_SYMBOLS = ["JSON"];
   1.162 +
   1.163 +// Create a JSON object only if one does not already exist. We create the
   1.164 +// object in a closure to avoid creating global variables.
   1.165 +
   1.166 +    JSON = function () {
   1.167 +
   1.168 +        function f(n) {
   1.169 +            // Format integers to have at least two digits.
   1.170 +            return n < 10 ? '0' + n : n;
   1.171 +        }
   1.172 +
   1.173 +        Date.prototype.toJSON = function (key) {
   1.174 +
   1.175 +            return this.getUTCFullYear()   + '-' +
   1.176 +                 f(this.getUTCMonth() + 1) + '-' +
   1.177 +                 f(this.getUTCDate())      + 'T' +
   1.178 +                 f(this.getUTCHours())     + ':' +
   1.179 +                 f(this.getUTCMinutes())   + ':' +
   1.180 +                 f(this.getUTCSeconds())   + 'Z';
   1.181 +        };
   1.182 +
   1.183 +        var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
   1.184 +            escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
   1.185 +            gap,
   1.186 +            indent,
   1.187 +            meta = {    // table of character substitutions
   1.188 +                '\b': '\\b',
   1.189 +                '\t': '\\t',
   1.190 +                '\n': '\\n',
   1.191 +                '\f': '\\f',
   1.192 +                '\r': '\\r',
   1.193 +                '"' : '\\"',
   1.194 +                '\\': '\\\\'
   1.195 +            },
   1.196 +            rep;
   1.197 +
   1.198 +
   1.199 +        function quote(string) {
   1.200 +
   1.201 +// If the string contains no control characters, no quote characters, and no
   1.202 +// backslash characters, then we can safely slap some quotes around it.
   1.203 +// Otherwise we must also replace the offending characters with safe escape
   1.204 +// sequences.
   1.205 +
   1.206 +            escapeable.lastIndex = 0;
   1.207 +            return escapeable.test(string) ?
   1.208 +                '"' + string.replace(escapeable, function (a) {
   1.209 +                    var c = meta[a];
   1.210 +                    if (typeof c === 'string') {
   1.211 +                        return c;
   1.212 +                    }
   1.213 +                    return '\\u' + ('0000' +
   1.214 +                            (+(a.charCodeAt(0))).toString(16)).slice(-4);
   1.215 +                }) + '"' :
   1.216 +                '"' + string + '"';
   1.217 +        }
   1.218 +
   1.219 +
   1.220 +        function str(key, holder) {
   1.221 +
   1.222 +// Produce a string from holder[key].
   1.223 +
   1.224 +            var i,          // The loop counter.
   1.225 +                k,          // The member key.
   1.226 +                v,          // The member value.
   1.227 +                length,
   1.228 +                mind = gap,
   1.229 +                partial,
   1.230 +                value = holder[key];
   1.231 +
   1.232 +// If the value has a toJSON method, call it to obtain a replacement value.
   1.233 +
   1.234 +            if (value && typeof value === 'object' &&
   1.235 +                    typeof value.toJSON === 'function') {
   1.236 +                value = value.toJSON(key);
   1.237 +            }
   1.238 +
   1.239 +// If we were called with a replacer function, then call the replacer to
   1.240 +// obtain a replacement value.
   1.241 +
   1.242 +            if (typeof rep === 'function') {
   1.243 +                value = rep.call(holder, key, value);
   1.244 +            }
   1.245 +
   1.246 +// What happens next depends on the value's type.
   1.247 +
   1.248 +            switch (typeof value) {
   1.249 +            case 'string':
   1.250 +                return quote(value);
   1.251 +
   1.252 +            case 'number':
   1.253 +
   1.254 +// JSON numbers must be finite. Encode non-finite numbers as null.
   1.255 +
   1.256 +                return isFinite(value) ? String(value) : 'null';
   1.257 +
   1.258 +            case 'boolean':
   1.259 +            case 'null':
   1.260 +
   1.261 +// If the value is a boolean or null, convert it to a string. Note:
   1.262 +// typeof null does not produce 'null'. The case is included here in
   1.263 +// the remote chance that this gets fixed someday.
   1.264 +
   1.265 +                return String(value);
   1.266 +
   1.267 +// If the type is 'object', we might be dealing with an object or an array or
   1.268 +// null.
   1.269 +
   1.270 +            case 'object':
   1.271 +
   1.272 +// Due to a specification blunder in ECMAScript, typeof null is 'object',
   1.273 +// so watch out for that case.
   1.274 +
   1.275 +                if (!value) {
   1.276 +                    return 'null';
   1.277 +                }
   1.278 +
   1.279 +// Make an array to hold the partial results of stringifying this object value.
   1.280 +
   1.281 +                gap += indent;
   1.282 +                partial = [];
   1.283 +
   1.284 +// If the object has a dontEnum length property, we'll treat it as an array.
   1.285 +
   1.286 +                if (typeof value.length === 'number' &&
   1.287 +                        !(value.propertyIsEnumerable('length'))) {
   1.288 +
   1.289 +// The object is an array. Stringify every element. Use null as a placeholder
   1.290 +// for non-JSON values.
   1.291 +
   1.292 +                    length = value.length;
   1.293 +                    for (i = 0; i < length; i += 1) {
   1.294 +                        partial[i] = str(i, value) || 'null';
   1.295 +                    }
   1.296 +
   1.297 +// Join all of the elements together, separated with commas, and wrap them in
   1.298 +// brackets.
   1.299 +
   1.300 +                    v = partial.length === 0 ? '[]' :
   1.301 +                        gap ? '[\n' + gap +
   1.302 +                                partial.join(',\n' + gap) + '\n' +
   1.303 +                                    mind + ']' :
   1.304 +                              '[' + partial.join(',') + ']';
   1.305 +                    gap = mind;
   1.306 +                    return v;
   1.307 +                }
   1.308 +
   1.309 +// If the replacer is an array, use it to select the members to be stringified.
   1.310 +
   1.311 +                if (rep && typeof rep === 'object') {
   1.312 +                    length = rep.length;
   1.313 +                    for (i = 0; i < length; i += 1) {
   1.314 +                        k = rep[i];
   1.315 +                        if (typeof k === 'string') {
   1.316 +                            v = str(k, value, rep);
   1.317 +                            if (v) {
   1.318 +                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
   1.319 +                            }
   1.320 +                        }
   1.321 +                    }
   1.322 +                } else {
   1.323 +
   1.324 +// Otherwise, iterate through all of the keys in the object.
   1.325 +
   1.326 +                    for (k in value) {
   1.327 +                        if (Object.hasOwnProperty.call(value, k)) {
   1.328 +                            v = str(k, value, rep);
   1.329 +                            if (v) {
   1.330 +                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
   1.331 +                            }
   1.332 +                        }
   1.333 +                    }
   1.334 +                }
   1.335 +
   1.336 +// Join all of the member texts together, separated with commas,
   1.337 +// and wrap them in braces.
   1.338 +
   1.339 +                v = partial.length === 0 ? '{}' :
   1.340 +                    gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
   1.341 +                            mind + '}' : '{' + partial.join(',') + '}';
   1.342 +                gap = mind;
   1.343 +                return v;
   1.344 +            }
   1.345 +        }
   1.346 +
   1.347 +// Return the JSON object containing the stringify and parse methods.
   1.348 +
   1.349 +        return {
   1.350 +            stringify: function (value, replacer, space) {
   1.351 +
   1.352 +// The stringify method takes a value and an optional replacer, and an optional
   1.353 +// space parameter, and returns a JSON text. The replacer can be a function
   1.354 +// that can replace values, or an array of strings that will select the keys.
   1.355 +// A default replacer method can be provided. Use of the space parameter can
   1.356 +// produce text that is more easily readable.
   1.357 +
   1.358 +                var i;
   1.359 +                gap = '';
   1.360 +                indent = '';
   1.361 +
   1.362 +// If the space parameter is a number, make an indent string containing that
   1.363 +// many spaces.
   1.364 +
   1.365 +                if (typeof space === 'number') {
   1.366 +                    for (i = 0; i < space; i += 1) {
   1.367 +                        indent += ' ';
   1.368 +                    }
   1.369 +
   1.370 +// If the space parameter is a string, it will be used as the indent string.
   1.371 +
   1.372 +                } else if (typeof space === 'string') {
   1.373 +                    indent = space;
   1.374 +                }
   1.375 +
   1.376 +// If there is a replacer, it must be a function or an array.
   1.377 +// Otherwise, throw an error.
   1.378 +
   1.379 +                rep = replacer;
   1.380 +                if (replacer && typeof replacer !== 'function' &&
   1.381 +                        (typeof replacer !== 'object' ||
   1.382 +                         typeof replacer.length !== 'number')) {
   1.383 +                    throw new Error('JSON.stringify');
   1.384 +                }
   1.385 +
   1.386 +// Make a fake root object containing our value under the key of ''.
   1.387 +// Return the result of stringifying the value.
   1.388 +
   1.389 +                return str('', {'': value});
   1.390 +            },
   1.391 +
   1.392 +
   1.393 +            parse: function (text, reviver) {
   1.394 +
   1.395 +// The parse method takes a text and an optional reviver function, and returns
   1.396 +// a JavaScript value if the text is a valid JSON text.
   1.397 +
   1.398 +                var j;
   1.399 +
   1.400 +                function walk(holder, key) {
   1.401 +
   1.402 +// The walk method is used to recursively walk the resulting structure so
   1.403 +// that modifications can be made.
   1.404 +
   1.405 +                    var k, v, value = holder[key];
   1.406 +                    if (value && typeof value === 'object') {
   1.407 +                        for (k in value) {
   1.408 +                            if (Object.hasOwnProperty.call(value, k)) {
   1.409 +                                v = walk(value, k);
   1.410 +                                if (v !== undefined) {
   1.411 +                                    value[k] = v;
   1.412 +                                } else {
   1.413 +                                    delete value[k];
   1.414 +                                }
   1.415 +                            }
   1.416 +                        }
   1.417 +                    }
   1.418 +                    return reviver.call(holder, key, value);
   1.419 +                }
   1.420 +
   1.421 +
   1.422 +// Parsing happens in four stages. In the first stage, we replace certain
   1.423 +// Unicode characters with escape sequences. JavaScript handles many characters
   1.424 +// incorrectly, either silently deleting them, or treating them as line endings.
   1.425 +
   1.426 +                cx.lastIndex = 0;
   1.427 +                if (cx.test(text)) {
   1.428 +                    text = text.replace(cx, function (a) {
   1.429 +                        return '\\u' + ('0000' +
   1.430 +                                (+(a.charCodeAt(0))).toString(16)).slice(-4);
   1.431 +                    });
   1.432 +                }
   1.433 +
   1.434 +// In the second stage, we run the text against regular expressions that look
   1.435 +// for non-JSON patterns. We are especially concerned with '()' and 'new'
   1.436 +// because they can cause invocation, and '=' because it can cause mutation.
   1.437 +// But just to be safe, we want to reject all unexpected forms.
   1.438 +
   1.439 +// We split the second stage into 4 regexp operations in order to work around
   1.440 +// crippling inefficiencies in IE's and Safari's regexp engines. First we
   1.441 +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
   1.442 +// replace all simple value tokens with ']' characters. Third, we delete all
   1.443 +// open brackets that follow a colon or comma or that begin the text. Finally,
   1.444 +// we look to see that the remaining characters are only whitespace or ']' or
   1.445 +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
   1.446 +
   1.447 +                if (/^[\],:{}\s]*$/.
   1.448 +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
   1.449 +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
   1.450 +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
   1.451 +
   1.452 +// In the third stage we use the eval function to compile the text into a
   1.453 +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
   1.454 +// in JavaScript: it can begin a block or an object literal. We wrap the text
   1.455 +// in parens to eliminate the ambiguity.
   1.456 +
   1.457 +                    j = eval('(' + text + ')');
   1.458 +
   1.459 +// In the optional fourth stage, we recursively walk the new structure, passing
   1.460 +// each name/value pair to a reviver function for possible transformation.
   1.461 +
   1.462 +                    return typeof reviver === 'function' ?
   1.463 +                        walk({'': j}, '') : j;
   1.464 +                }
   1.465 +
   1.466 +// If the text is not JSON parseable, then a SyntaxError is thrown.
   1.467 +
   1.468 +                throw new SyntaxError('JSON.parse');
   1.469 +            }
   1.470 +        };
   1.471 +    }();
   1.472 +

mercurial