src/cm/media/js/lib/yui/yui_3.10.3/build/json-stringify-shim/json-stringify-shim.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('json-stringify-shim', function (Y, NAME) {
       
     9 
       
    10 // All internals kept private for security reasons
       
    11 var Lang      = Y.Lang,
       
    12     isFunction= Lang.isFunction,
       
    13     isObject  = Lang.isObject,
       
    14     isArray   = Lang.isArray,
       
    15     _toStr    = Object.prototype.toString,
       
    16     UNDEFINED = 'undefined',
       
    17     OBJECT    = 'object',
       
    18     NULL      = 'null',
       
    19     STRING    = 'string',
       
    20     NUMBER    = 'number',
       
    21     BOOLEAN   = 'boolean',
       
    22     DATE      = 'date',
       
    23     _allowable= {
       
    24         'undefined'        : UNDEFINED,
       
    25         'string'           : STRING,
       
    26         '[object String]'  : STRING,
       
    27         'number'           : NUMBER,
       
    28         '[object Number]'  : NUMBER,
       
    29         'boolean'          : BOOLEAN,
       
    30         '[object Boolean]' : BOOLEAN,
       
    31         '[object Date]'    : DATE,
       
    32         '[object RegExp]'  : OBJECT
       
    33     },
       
    34     EMPTY     = '',
       
    35     OPEN_O    = '{',
       
    36     CLOSE_O   = '}',
       
    37     OPEN_A    = '[',
       
    38     CLOSE_A   = ']',
       
    39     COMMA     = ',',
       
    40     COMMA_CR  = ",\n",
       
    41     CR        = "\n",
       
    42     COLON     = ':',
       
    43     COLON_SP  = ': ',
       
    44     QUOTE     = '"',
       
    45 
       
    46     // Regex used to capture characters that need escaping before enclosing
       
    47     // their containing string in quotes.
       
    48     _SPECIAL = /[\x00-\x07\x0b\x0e-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
       
    49 
       
    50     // Character substitution map for common escapes and special characters.
       
    51     _COMMON = [
       
    52         [/\\/g, '\\\\'],
       
    53         [/\"/g, '\\"'],
       
    54         [/\x08/g, '\\b'],
       
    55         [/\x09/g, '\\t'],
       
    56         [/\x0a/g, '\\n'],
       
    57         [/\x0c/g, '\\f'],
       
    58         [/\x0d/g, '\\r']
       
    59     ],
       
    60     _COMMON_LENGTH = _COMMON.length,
       
    61 
       
    62     // In-process optimization for special character escapes that haven't yet
       
    63     // been promoted to _COMMON
       
    64     _CHAR = {},
       
    65 
       
    66     // Per-char counter to determine if it's worth fast tracking a special
       
    67     // character escape sequence.
       
    68     _CHAR_COUNT, _CACHE_THRESHOLD;
       
    69 
       
    70 // Utility function used to determine how to serialize a variable.
       
    71 function _type(o) {
       
    72     var t = typeof o;
       
    73     return  _allowable[t] ||              // number, string, boolean, undefined
       
    74             _allowable[_toStr.call(o)] || // Number, String, Boolean, Date
       
    75             (t === OBJECT ?
       
    76                 (o ? OBJECT : NULL) :     // object, array, null, misc natives
       
    77                 UNDEFINED);               // function, unknown
       
    78 }
       
    79 
       
    80 // Escapes a special character to a safe Unicode representation
       
    81 function _char(c) {
       
    82     if (!_CHAR[c]) {
       
    83         _CHAR[c] = '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
       
    84         _CHAR_COUNT[c] = 0;
       
    85     }
       
    86 
       
    87     // === to avoid this conditional for the remainder of the current operation
       
    88     if (++_CHAR_COUNT[c] === _CACHE_THRESHOLD) {
       
    89         _COMMON.push([new RegExp(c, 'g'), _CHAR[c]]);
       
    90         _COMMON_LENGTH = _COMMON.length;
       
    91     }
       
    92 
       
    93     return _CHAR[c];
       
    94 }
       
    95 
       
    96 // Enclose escaped strings in quotes
       
    97 function _string(s) {
       
    98     var i, chr;
       
    99 
       
   100     // Preprocess the string against common characters to avoid function
       
   101     // overhead associated with replacement via function.
       
   102     for (i = 0; i < _COMMON_LENGTH; i++) {
       
   103         chr = _COMMON[i];
       
   104         s = s.replace(chr[0], chr[1]);
       
   105     }
       
   106     
       
   107     // original function replace for the not-as-common set of chars
       
   108     return QUOTE + s.replace(_SPECIAL, _char) + QUOTE;
       
   109 }
       
   110 
       
   111 // Adds the provided space to the beginning of every line in the input string
       
   112 function _indent(s,space) {
       
   113     return s.replace(/^/gm, space);
       
   114 }
       
   115 
       
   116 Y.JSON.stringify = function _stringify(o,w,space) {
       
   117     if (o === undefined) {
       
   118         return undefined;
       
   119     }
       
   120 
       
   121     var replacer = isFunction(w) ? w : null,
       
   122         format   = _toStr.call(space).match(/String|Number/) || [],
       
   123         _date    = Y.JSON.dateToString,
       
   124         stack    = [],
       
   125         tmp,i,len;
       
   126 
       
   127     _CHAR_COUNT      = {};
       
   128     _CACHE_THRESHOLD = Y.JSON.charCacheThreshold;
       
   129 
       
   130     if (replacer || !isArray(w)) {
       
   131         w = undefined;
       
   132     }
       
   133 
       
   134     // Ensure whitelist keys are unique (bug 2110391)
       
   135     if (w) {
       
   136         tmp = {};
       
   137         for (i = 0, len = w.length; i < len; ++i) {
       
   138             tmp[w[i]] = true;
       
   139         }
       
   140         w = tmp;
       
   141     }
       
   142 
       
   143     // Per the spec, strings are truncated to 10 characters and numbers
       
   144     // are converted to that number of spaces (max 10)
       
   145     space = format[0] === 'Number' ?
       
   146                 new Array(Math.min(Math.max(0,space),10)+1).join(" ") :
       
   147                 (space || EMPTY).slice(0,10);
       
   148 
       
   149     function _serialize(h,key) {
       
   150         var value = h[key],
       
   151             t     = _type(value),
       
   152             a     = [],
       
   153             colon = space ? COLON_SP : COLON,
       
   154             arr, i, keys, k, v;
       
   155 
       
   156         // Per the ECMA 5 spec, toJSON is applied before the replacer is
       
   157         // called.  Also per the spec, Date.prototype.toJSON has been added, so
       
   158         // Date instances should be serialized prior to exposure to the
       
   159         // replacer.  I disagree with this decision, but the spec is the spec.
       
   160         if (isObject(value) && isFunction(value.toJSON)) {
       
   161             value = value.toJSON(key);
       
   162         } else if (t === DATE) {
       
   163             value = _date(value);
       
   164         }
       
   165 
       
   166         if (isFunction(replacer)) {
       
   167             value = replacer.call(h,key,value);
       
   168         }
       
   169 
       
   170         if (value !== h[key]) {
       
   171             t = _type(value);
       
   172         }
       
   173 
       
   174         switch (t) {
       
   175             case DATE    : // intentional fallthrough.  Pre-replacer Dates are
       
   176                            // serialized in the toJSON stage.  Dates here would
       
   177                            // have been produced by the replacer.
       
   178             case OBJECT  : break;
       
   179             case STRING  : return _string(value);
       
   180             case NUMBER  : return isFinite(value) ? value+EMPTY : NULL;
       
   181             case BOOLEAN : return value+EMPTY;
       
   182             case NULL    : return NULL;
       
   183             default      : return undefined;
       
   184         }
       
   185 
       
   186         // Check for cyclical references in nested objects
       
   187         for (i = stack.length - 1; i >= 0; --i) {
       
   188             if (stack[i] === value) {
       
   189                 throw new Error("JSON.stringify. Cyclical reference");
       
   190             }
       
   191         }
       
   192 
       
   193         arr = isArray(value);
       
   194 
       
   195         // Add the object to the processing stack
       
   196         stack.push(value);
       
   197 
       
   198         if (arr) { // Array
       
   199             for (i = value.length - 1; i >= 0; --i) {
       
   200                 a[i] = _serialize(value, i) || NULL;
       
   201             }
       
   202         } else {   // Object
       
   203             // If whitelist provided, take only those keys
       
   204             keys = w || value;
       
   205             i = 0;
       
   206 
       
   207             for (k in keys) {
       
   208                 if (keys.hasOwnProperty(k)) {
       
   209                     v = _serialize(value, k);
       
   210                     if (v) {
       
   211                         a[i++] = _string(k) + colon + v;
       
   212                     }
       
   213                 }
       
   214             }
       
   215         }
       
   216 
       
   217         // remove the array from the stack
       
   218         stack.pop();
       
   219 
       
   220         if (space && a.length) {
       
   221             return arr ?
       
   222                 OPEN_A + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_A :
       
   223                 OPEN_O + CR + _indent(a.join(COMMA_CR), space) + CR + CLOSE_O;
       
   224         } else {
       
   225             return arr ?
       
   226                 OPEN_A + a.join(COMMA) + CLOSE_A :
       
   227                 OPEN_O + a.join(COMMA) + CLOSE_O;
       
   228         }
       
   229     }
       
   230 
       
   231     // process the input
       
   232     return _serialize({'':o},'');
       
   233 };
       
   234 
       
   235 // Property available for testing if the implementation being used
       
   236 // is native or a shim
       
   237 Y.JSON.stringify.isShim = true;
       
   238 
       
   239 }, '3.10.3', {"requires": ["json-stringify"]});