wp/wp-includes/js/json2.js
changeset 7 cf61fcea0001
parent 0 d970ebf37754
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /*
     1 /*
     2     http://www.JSON.org/json2.js
     2     json2.js
     3     2011-02-23
     3     2015-05-03
     4 
     4 
     5     Public Domain.
     5     Public Domain.
     6 
     6 
     7     NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
     7     NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
     8 
     8 
    15     USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    15     USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    16     NOT CONTROL.
    16     NOT CONTROL.
    17 
    17 
    18 
    18 
    19     This file creates a global JSON object containing two methods: stringify
    19     This file creates a global JSON object containing two methods: stringify
    20     and parse.
    20     and parse. This file is provides the ES5 JSON capability to ES3 systems.
       
    21     If a project might run on IE8 or earlier, then this file should be included.
       
    22     This file does nothing on ES5 systems.
    21 
    23 
    22         JSON.stringify(value, replacer, space)
    24         JSON.stringify(value, replacer, space)
    23             value       any JavaScript value, usually an object or array.
    25             value       any JavaScript value, usually an object or array.
    24 
    26 
    25             replacer    an optional parameter that determines how object
    27             replacer    an optional parameter that determines how object
    46             For example, this would serialize Dates as ISO strings.
    48             For example, this would serialize Dates as ISO strings.
    47 
    49 
    48                 Date.prototype.toJSON = function (key) {
    50                 Date.prototype.toJSON = function (key) {
    49                     function f(n) {
    51                     function f(n) {
    50                         // Format integers to have at least two digits.
    52                         // Format integers to have at least two digits.
    51                         return n < 10 ? '0' + n : n;
    53                         return n < 10 
       
    54                             ? '0' + n 
       
    55                             : n;
    52                     }
    56                     }
    53 
    57 
    54                     return this.getUTCFullYear()   + '-' +
    58                     return this.getUTCFullYear()   + '-' +
    55                          f(this.getUTCMonth() + 1) + '-' +
    59                          f(this.getUTCMonth() + 1) + '-' +
    56                          f(this.getUTCDate())      + 'T' +
    60                          f(this.getUTCDate())      + 'T' +
    92 
    96 
    93             text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
    97             text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
    94             // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
    98             // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
    95 
    99 
    96             text = JSON.stringify([new Date()], function (key, value) {
   100             text = JSON.stringify([new Date()], function (key, value) {
    97                 return this[key] instanceof Date ?
   101                 return this[key] instanceof Date 
    98                     'Date(' + this[key] + ')' : value;
   102                     ? 'Date(' + this[key] + ')' 
       
   103                     : value;
    99             });
   104             });
   100             // text is '["Date(---current time---)"]'
   105             // text is '["Date(---current time---)"]'
   101 
   106 
   102 
   107 
   103         JSON.parse(text, reviver)
   108         JSON.parse(text, reviver)
   144 
   149 
   145     This is a reference implementation. You are free to copy, modify, or
   150     This is a reference implementation. You are free to copy, modify, or
   146     redistribute.
   151     redistribute.
   147 */
   152 */
   148 
   153 
   149 /*jslint evil: true, strict: false, regexp: false */
   154 /*jslint 
   150 
   155     eval, for, this 
   151 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
   156 */
   152     call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
   157 
       
   158 /*property
       
   159     JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
   153     getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
   160     getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
   154     lastIndex, length, parse, prototype, push, replace, slice, stringify,
   161     lastIndex, length, parse, prototype, push, replace, slice, stringify,
   155     test, toJSON, toString, valueOf
   162     test, toJSON, toString, valueOf
   156 */
   163 */
   157 
   164 
   158 
   165 
   159 // Create a JSON object only if one does not already exist. We create the
   166 // Create a JSON object only if one does not already exist. We create the
   160 // methods in a closure to avoid creating global variables.
   167 // methods in a closure to avoid creating global variables.
   161 
   168 
   162 var JSON;
   169 if (typeof JSON !== 'object') {
   163 if (!JSON) {
       
   164     JSON = {};
   170     JSON = {};
   165 }
   171 }
   166 
   172 
   167 (function () {
   173 (function () {
   168     "use strict";
   174     'use strict';
       
   175     
       
   176     var rx_one = /^[\],:{}\s]*$/,
       
   177         rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
       
   178         rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
       
   179         rx_four = /(?:^|:|,)(?:\s*\[)+/g,
       
   180         rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
       
   181         rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
   169 
   182 
   170     function f(n) {
   183     function f(n) {
   171         // Format integers to have at least two digits.
   184         // Format integers to have at least two digits.
   172         return n < 10 ? '0' + n : n;
   185         return n < 10 
       
   186             ? '0' + n 
       
   187             : n;
       
   188     }
       
   189     
       
   190     function this_value() {
       
   191         return this.valueOf();
   173     }
   192     }
   174 
   193 
   175     if (typeof Date.prototype.toJSON !== 'function') {
   194     if (typeof Date.prototype.toJSON !== 'function') {
   176 
   195 
   177         Date.prototype.toJSON = function (key) {
   196         Date.prototype.toJSON = function () {
   178 
   197 
   179             return isFinite(this.valueOf()) ?
   198             return isFinite(this.valueOf())
   180                 this.getUTCFullYear()     + '-' +
   199                 ? this.getUTCFullYear() + '-' +
   181                 f(this.getUTCMonth() + 1) + '-' +
   200                         f(this.getUTCMonth() + 1) + '-' +
   182                 f(this.getUTCDate())      + 'T' +
   201                         f(this.getUTCDate()) + 'T' +
   183                 f(this.getUTCHours())     + ':' +
   202                         f(this.getUTCHours()) + ':' +
   184                 f(this.getUTCMinutes())   + ':' +
   203                         f(this.getUTCMinutes()) + ':' +
   185                 f(this.getUTCSeconds())   + 'Z' : null;
   204                         f(this.getUTCSeconds()) + 'Z'
       
   205                 : null;
   186         };
   206         };
   187 
   207 
   188         String.prototype.toJSON      =
   208         Boolean.prototype.toJSON = this_value;
   189             Number.prototype.toJSON  =
   209         Number.prototype.toJSON = this_value;
   190             Boolean.prototype.toJSON = function (key) {
   210         String.prototype.toJSON = this_value;
   191                 return this.valueOf();
   211     }
   192             };
   212 
   193     }
   213     var gap,
   194 
       
   195     var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
       
   196         escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
       
   197         gap,
       
   198         indent,
   214         indent,
   199         meta = {    // table of character substitutions
   215         meta,
   200             '\b': '\\b',
       
   201             '\t': '\\t',
       
   202             '\n': '\\n',
       
   203             '\f': '\\f',
       
   204             '\r': '\\r',
       
   205             '"' : '\\"',
       
   206             '\\': '\\\\'
       
   207         },
       
   208         rep;
   216         rep;
   209 
   217 
   210 
   218 
   211     function quote(string) {
   219     function quote(string) {
   212 
   220 
   213 // If the string contains no control characters, no quote characters, and no
   221 // If the string contains no control characters, no quote characters, and no
   214 // backslash characters, then we can safely slap some quotes around it.
   222 // backslash characters, then we can safely slap some quotes around it.
   215 // Otherwise we must also replace the offending characters with safe escape
   223 // Otherwise we must also replace the offending characters with safe escape
   216 // sequences.
   224 // sequences.
   217 
   225 
   218         escapable.lastIndex = 0;
   226         rx_escapable.lastIndex = 0;
   219         return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
   227         return rx_escapable.test(string) 
   220             var c = meta[a];
   228             ? '"' + string.replace(rx_escapable, function (a) {
   221             return typeof c === 'string' ? c :
   229                 var c = meta[a];
   222                 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
   230                 return typeof c === 'string'
   223         }) + '"' : '"' + string + '"';
   231                     ? c
       
   232                     : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
       
   233             }) + '"' 
       
   234             : '"' + string + '"';
   224     }
   235     }
   225 
   236 
   226 
   237 
   227     function str(key, holder) {
   238     function str(key, holder) {
   228 
   239 
   258 
   269 
   259         case 'number':
   270         case 'number':
   260 
   271 
   261 // JSON numbers must be finite. Encode non-finite numbers as null.
   272 // JSON numbers must be finite. Encode non-finite numbers as null.
   262 
   273 
   263             return isFinite(value) ? String(value) : 'null';
   274             return isFinite(value) 
       
   275                 ? String(value) 
       
   276                 : 'null';
   264 
   277 
   265         case 'boolean':
   278         case 'boolean':
   266         case 'null':
   279         case 'null':
   267 
   280 
   268 // If the value is a boolean or null, convert it to a string. Note:
   281 // If the value is a boolean or null, convert it to a string. Note:
   301                 }
   314                 }
   302 
   315 
   303 // Join all of the elements together, separated with commas, and wrap them in
   316 // Join all of the elements together, separated with commas, and wrap them in
   304 // brackets.
   317 // brackets.
   305 
   318 
   306                 v = partial.length === 0 ? '[]' : gap ?
   319                 v = partial.length === 0
   307                     '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
   320                     ? '[]'
   308                     '[' + partial.join(',') + ']';
   321                     : gap
       
   322                         ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
       
   323                         : '[' + partial.join(',') + ']';
   309                 gap = mind;
   324                 gap = mind;
   310                 return v;
   325                 return v;
   311             }
   326             }
   312 
   327 
   313 // If the replacer is an array, use it to select the members to be stringified.
   328 // If the replacer is an array, use it to select the members to be stringified.
   317                 for (i = 0; i < length; i += 1) {
   332                 for (i = 0; i < length; i += 1) {
   318                     if (typeof rep[i] === 'string') {
   333                     if (typeof rep[i] === 'string') {
   319                         k = rep[i];
   334                         k = rep[i];
   320                         v = str(k, value);
   335                         v = str(k, value);
   321                         if (v) {
   336                         if (v) {
   322                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
   337                             partial.push(quote(k) + (
       
   338                                 gap 
       
   339                                     ? ': ' 
       
   340                                     : ':'
       
   341                             ) + v);
   323                         }
   342                         }
   324                     }
   343                     }
   325                 }
   344                 }
   326             } else {
   345             } else {
   327 
   346 
   329 
   348 
   330                 for (k in value) {
   349                 for (k in value) {
   331                     if (Object.prototype.hasOwnProperty.call(value, k)) {
   350                     if (Object.prototype.hasOwnProperty.call(value, k)) {
   332                         v = str(k, value);
   351                         v = str(k, value);
   333                         if (v) {
   352                         if (v) {
   334                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
   353                             partial.push(quote(k) + (
       
   354                                 gap 
       
   355                                     ? ': ' 
       
   356                                     : ':'
       
   357                             ) + v);
   335                         }
   358                         }
   336                     }
   359                     }
   337                 }
   360                 }
   338             }
   361             }
   339 
   362 
   340 // Join all of the member texts together, separated with commas,
   363 // Join all of the member texts together, separated with commas,
   341 // and wrap them in braces.
   364 // and wrap them in braces.
   342 
   365 
   343             v = partial.length === 0 ? '{}' : gap ?
   366             v = partial.length === 0
   344                 '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
   367                 ? '{}'
   345                 '{' + partial.join(',') + '}';
   368                 : gap
       
   369                     ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
       
   370                     : '{' + partial.join(',') + '}';
   346             gap = mind;
   371             gap = mind;
   347             return v;
   372             return v;
   348         }
   373         }
   349     }
   374     }
   350 
   375 
   351 // If the JSON object does not yet have a stringify method, give it one.
   376 // If the JSON object does not yet have a stringify method, give it one.
   352 
   377 
   353     if (typeof JSON.stringify !== 'function') {
   378     if (typeof JSON.stringify !== 'function') {
       
   379         meta = {    // table of character substitutions
       
   380             '\b': '\\b',
       
   381             '\t': '\\t',
       
   382             '\n': '\\n',
       
   383             '\f': '\\f',
       
   384             '\r': '\\r',
       
   385             '"': '\\"',
       
   386             '\\': '\\\\'
       
   387         };
   354         JSON.stringify = function (value, replacer, space) {
   388         JSON.stringify = function (value, replacer, space) {
   355 
   389 
   356 // The stringify method takes a value and an optional replacer, and an optional
   390 // The stringify method takes a value and an optional replacer, and an optional
   357 // space parameter, and returns a JSON text. The replacer can be a function
   391 // space parameter, and returns a JSON text. The replacer can be a function
   358 // that can replace values, or an array of strings that will select the keys.
   392 // that can replace values, or an array of strings that will select the keys.
   430 // Parsing happens in four stages. In the first stage, we replace certain
   464 // Parsing happens in four stages. In the first stage, we replace certain
   431 // Unicode characters with escape sequences. JavaScript handles many characters
   465 // Unicode characters with escape sequences. JavaScript handles many characters
   432 // incorrectly, either silently deleting them, or treating them as line endings.
   466 // incorrectly, either silently deleting them, or treating them as line endings.
   433 
   467 
   434             text = String(text);
   468             text = String(text);
   435             cx.lastIndex = 0;
   469             rx_dangerous.lastIndex = 0;
   436             if (cx.test(text)) {
   470             if (rx_dangerous.test(text)) {
   437                 text = text.replace(cx, function (a) {
   471                 text = text.replace(rx_dangerous, function (a) {
   438                     return '\\u' +
   472                     return '\\u' +
   439                         ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
   473                             ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
   440                 });
   474                 });
   441             }
   475             }
   442 
   476 
   443 // In the second stage, we run the text against regular expressions that look
   477 // In the second stage, we run the text against regular expressions that look
   444 // for non-JSON patterns. We are especially concerned with '()' and 'new'
   478 // for non-JSON patterns. We are especially concerned with '()' and 'new'
   451 // replace all simple value tokens with ']' characters. Third, we delete all
   485 // replace all simple value tokens with ']' characters. Third, we delete all
   452 // open brackets that follow a colon or comma or that begin the text. Finally,
   486 // open brackets that follow a colon or comma or that begin the text. Finally,
   453 // we look to see that the remaining characters are only whitespace or ']' or
   487 // we look to see that the remaining characters are only whitespace or ']' or
   454 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
   488 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
   455 
   489 
   456             if (/^[\],:{}\s]*$/
   490             if (
   457                     .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
   491                 rx_one.test(
   458                         .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
   492                     text
   459                         .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
   493                         .replace(rx_two, '@')
       
   494                         .replace(rx_three, ']')
       
   495                         .replace(rx_four, '')
       
   496                 )
       
   497             ) {
   460 
   498 
   461 // In the third stage we use the eval function to compile the text into a
   499 // In the third stage we use the eval function to compile the text into a
   462 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
   500 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
   463 // in JavaScript: it can begin a block or an object literal. We wrap the text
   501 // in JavaScript: it can begin a block or an object literal. We wrap the text
   464 // in parens to eliminate the ambiguity.
   502 // in parens to eliminate the ambiguity.
   466                 j = eval('(' + text + ')');
   504                 j = eval('(' + text + ')');
   467 
   505 
   468 // In the optional fourth stage, we recursively walk the new structure, passing
   506 // In the optional fourth stage, we recursively walk the new structure, passing
   469 // each name/value pair to a reviver function for possible transformation.
   507 // each name/value pair to a reviver function for possible transformation.
   470 
   508 
   471                 return typeof reviver === 'function' ?
   509                 return typeof reviver === 'function'
   472                     walk({'': j}, '') : j;
   510                     ? walk({'': j}, '')
       
   511                     : j;
   473             }
   512             }
   474 
   513 
   475 // If the text is not JSON parseable, then a SyntaxError is thrown.
   514 // If the text is not JSON parseable, then a SyntaxError is thrown.
   476 
   515 
   477             throw new SyntaxError('JSON.parse');
   516             throw new SyntaxError('JSON.parse');