]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/json/json-parse.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / json / json-parse.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('json-parse', function(Y) {
9
10 /**
11  * <p>The JSON module adds support for serializing JavaScript objects into
12  * JSON strings and parsing JavaScript objects from strings in JSON format.</p>
13  *
14  * <p>The JSON namespace is added to your YUI instance including static methods
15  * Y.JSON.parse(..) and Y.JSON.stringify(..).</p>
16  *
17  * <p>The functionality and method signatures follow the ECMAScript 5
18  * specification.  In browsers with native JSON support, the native
19  * implementation is used.</p>
20  *
21  * <p>The <code>json</code> module is a rollup of <code>json-parse</code> and
22  * <code>json-stringify</code>.</p>
23  * 
24  * <p>As their names suggest, <code>json-parse</code> adds support for parsing
25  * JSON data (Y.JSON.parse) and <code>json-stringify</code> for serializing
26  * JavaScript data into JSON strings (Y.JSON.stringify).  You may choose to
27  * include either of the submodules individually if you don't need the
28  * complementary functionality, or include the rollup for both.</p>
29  *
30  * @module json
31  * @class JSON
32  * @static
33  */
34
35 /**
36  * Provides Y.JSON.parse method to accept JSON strings and return native
37  * JavaScript objects.
38  *
39  * @module json
40  * @submodule json-parse
41  * @for JSON
42  * @static
43  */
44
45
46 // All internals kept private for security reasons
47 function fromGlobal(ref) {
48     return (Y.config.win || this || {})[ref];
49 }
50
51
52     /**
53      * Alias to native browser implementation of the JSON object if available.
54      *
55      * @property Native
56      * @type {Object}
57      * @private
58      */
59 var _JSON  = fromGlobal('JSON'),
60     // Create an indirect reference to eval to allow for minification
61     _eval  = fromGlobal('eval'),
62     Native = (Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON),
63     useNative = !!Native,
64
65     /**
66      * Replace certain Unicode characters that JavaScript may handle incorrectly
67      * during eval--either by deleting them or treating them as line
68      * endings--with escape sequences.
69      * IMPORTANT NOTE: This regex will be used to modify the input if a match is
70      * found.
71      *
72      * @property _UNICODE_EXCEPTIONS
73      * @type {RegExp}
74      * @private
75      */
76     _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
77
78
79     /**
80      * First step in the safety evaluation.  Regex used to replace all escape
81      * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
82      *
83      * @property _ESCAPES
84      * @type {RegExp}
85      * @private
86      */
87     _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
88
89     /**
90      * Second step in the safety evaluation.  Regex used to replace all simple
91      * values with ']' characters.
92      *
93      * @property _VALUES
94      * @type {RegExp}
95      * @private
96      */
97     _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
98
99     /**
100      * Third step in the safety evaluation.  Regex used to remove all open
101      * square brackets following a colon, comma, or at the beginning of the
102      * string.
103      *
104      * @property _BRACKETS
105      * @type {RegExp}
106      * @private
107      */
108     _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
109
110     /**
111      * Final step in the safety evaluation.  Regex used to test the string left
112      * after all previous replacements for invalid characters.
113      *
114      * @property _UNSAFE
115      * @type {RegExp}
116      * @private
117      */
118     _UNSAFE = /[^\],:{}\s]/,
119     
120     /**
121      * Replaces specific unicode characters with their appropriate \unnnn
122      * format. Some browsers ignore certain characters during eval.
123      *
124      * @method escapeException
125      * @param c {String} Unicode character
126      * @return {String} the \unnnn escapement of the character
127      * @private
128      */
129     _escapeException = function (c) {
130         return '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
131     },
132
133     /**
134      * Traverses nested objects, applying a reviver function to each (key,value)
135      * from the scope if the key:value's containing object.  The value returned
136      * from the function will replace the original value in the key:value pair.
137      * If the value returned is undefined, the key will be omitted from the
138      * returned object.
139      *
140      * @method _revive
141      * @param data {MIXED} Any JavaScript data
142      * @param reviver {Function} filter or mutation function
143      * @return {MIXED} The results of the filtered data
144      * @private
145      */
146     _revive = function (data, reviver) {
147         var walk = function (o,key) {
148             var k,v,value = o[key];
149             if (value && typeof value === 'object') {
150                 for (k in value) {
151                     if (value.hasOwnProperty(k)) {
152                         v = walk(value, k);
153                         if (v === undefined) {
154                             delete value[k];
155                         } else {
156                             value[k] = v;
157                         }
158                     }
159                 }
160             }
161             return reviver.call(o,key,value);
162         };
163
164         return typeof reviver === 'function' ? walk({'':data},'') : data;
165     },
166
167     /**
168      * Parse a JSON string, returning the native JavaScript representation.
169      *
170      * @param s {string} JSON string data
171      * @param reviver {function} (optional) function(k,v) passed each key value
172      *          pair of object literals, allowing pruning or altering values
173      * @return {MIXED} the native JavaScript representation of the JSON string
174      * @throws SyntaxError
175      * @method parse
176      * @static
177      */
178     // JavaScript implementation in lieu of native browser support.  Based on
179     // the json2.js library from http://json.org
180     _parse = function (s,reviver) {
181         // Replace certain Unicode characters that are otherwise handled
182         // incorrectly by some browser implementations.
183         // NOTE: This modifies the input if such characters are found!
184         s = s.replace(_UNICODE_EXCEPTIONS, _escapeException);
185         
186         // Test for any remaining invalid characters
187         if (!_UNSAFE.test(s.replace(_ESCAPES,'@').
188                             replace(_VALUES,']').
189                             replace(_BRACKETS,''))) {
190
191             // Eval the text into a JavaScript data structure, apply any
192             // reviver function, and return
193             return _revive( _eval('(' + s + ')'), reviver );
194         }
195
196         throw new SyntaxError('JSON.parse');
197     };
198     
199 Y.namespace('JSON').parse = function (s,reviver) {
200         if (typeof s !== 'string') {
201             s += '';
202         }
203
204         return Native && Y.JSON.useNativeParse ?
205             Native.parse(s,reviver) : _parse(s,reviver);
206 };
207
208 function workingNative( k, v ) {
209     return k === "ok" ? true : v;
210 }
211
212 // Double check basic functionality.  This is mainly to catch early broken
213 // implementations of the JSON API in Firefox 3.1 beta1 and beta2
214 if ( Native ) {
215     try {
216         useNative = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
217     }
218     catch ( e ) {
219         useNative = false;
220     }
221 }
222
223 /**
224  * Leverage native JSON parse if the browser has a native implementation.
225  * In general, this is a good idea.  See the Known Issues section in the
226  * JSON user guide for caveats.  The default value is true for browsers with
227  * native JSON support.
228  *
229  * @property useNativeParse
230  * @type Boolean
231  * @default true
232  * @static
233  */
234 Y.JSON.useNativeParse = useNative;
235
236
237 }, '3.3.0' );