1 goog.provide('Banana.thirdParty.json');
  2 /*
  3 	MODIFIED VERSION stringify function is modified. now also prototyped objects are stringified. 
  4 	
  5     http://www.JSON.org/json2.js
  6     2010-08-25
  7 
  8     Public Domain.
  9 
 10     NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 11 
 12     See http://www.JSON.org/js.html
 13    
 14 
 15     This code should be minified before deployment.
 16     See http://javascript.crockford.com/jsmin.html
 17 
 18     USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
 19     NOT CONTROL.
 20 
 21 
 22     This file creates a global JSON object containing two methods: stringify
 23     and parse.
 24 
 25         JSON.stringify(value, replacer, space)
 26             value       any JavaScript value, usually an object or array.
 27 
 28             replacer    an optional parameter that determines how object
 29                         values are stringified for objects. It can be a
 30                         function or an array of strings.
 31 
 32             space       an optional parameter that specifies the indentation
 33                         of nested structures. If it is omitted, the text will
 34                         be packed without extra whitespace. If it is a number,
 35                         it will specify the number of spaces to indent at each
 36                         level. If it is a string (such as '\t' or ' '),
 37                         it contains the characters used to indent at each level.
 38 
 39             This method produces a JSON text from a JavaScript value.
 40 
 41             When an object value is found, if the object contains a toJSON
 42             method, its toJSON method will be called and the result will be
 43             stringified. A toJSON method does not serialize: it returns the
 44             value represented by the name/value pair that should be serialized,
 45             or undefined if nothing should be serialized. The toJSON method
 46             will be passed the key associated with the value, and this will be
 47             bound to the value
 48 
 49             For example, this would serialize Dates as ISO strings.
 50 
 51                 Date.prototype.toJSON = function (key) {
 52                     function f(n) {
 53                         // Format integers to have at least two digits.
 54                         return n < 10 ? '0' + n : n;
 55                     }
 56 
 57                     return this.getUTCFullYear()   + '-' +
 58                          f(this.getUTCMonth() + 1) + '-' +
 59                          f(this.getUTCDate())      + 'T' +
 60                          f(this.getUTCHours())     + ':' +
 61                          f(this.getUTCMinutes())   + ':' +
 62                          f(this.getUTCSeconds())   + 'Z';
 63                 };
 64 
 65             You can provide an optional replacer method. It will be passed the
 66             key and value of each member, with this bound to the containing
 67             object. The value that is returned from your method will be
 68             serialized. If your method returns undefined, then the member will
 69             be excluded from the serialization.
 70 
 71             If the replacer parameter is an array of strings, then it will be
 72             used to select the members to be serialized. It filters the results
 73             such that only members with keys listed in the replacer array are
 74             stringified.
 75 
 76             Values that do not have JSON representations, such as undefined or
 77             functions, will not be serialized. Such values in objects will be
 78             dropped; in arrays they will be replaced with null. You can use
 79             a replacer function to replace those with JSON values.
 80             JSON.stringify(undefined) returns undefined.
 81 
 82             The optional space parameter produces a stringification of the
 83             value that is filled with line breaks and indentation to make it
 84             easier to read.
 85 
 86             If the space parameter is a non-empty string, then that string will
 87             be used for indentation. If the space parameter is a number, then
 88             the indentation will be that many spaces.
 89 
 90             Example:
 91 
 92             text = JSON.stringify(['e', {pluribus: 'unum'}]);
 93             // text is '["e",{"pluribus":"unum"}]'
 94 
 95 
 96             text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
 97             // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
 98 
 99             text = JSON.stringify([new Date()], function (key, value) {
100                 return this[key] instanceof Date ?
101                     'Date(' + this[key] + ')' : value;
102             });
103             // text is '["Date(---current time---)"]'
104 
105 
106         JSON.parse(text, reviver)
107             This method parses a JSON text to produce an object or array.
108             It can throw a SyntaxError exception.
109 
110             The optional reviver parameter is a function that can filter and
111             transform the results. It receives each of the keys and values,
112             and its return value is used instead of the original value.
113             If it returns what it received, then the structure is not modified.
114             If it returns undefined then the member is deleted.
115 
116             Example:
117 
118             // Parse the text. Values that look like ISO date strings will
119             // be converted to Date objects.
120 
121             myData = JSON.parse(text, function (key, value) {
122                 var a;
123                 if (typeof value === 'string') {
124                     a =
125 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
126                     if (a) {
127                         return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
128                             +a[5], +a[6]));
129                     }
130                 }
131                 return value;
132             });
133 
134             myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
135                 var d;
136                 if (typeof value === 'string' &&
137                         value.slice(0, 5) === 'Date(' &&
138                         value.slice(-1) === ')') {
139                     d = new Date(value.slice(5, -1));
140                     if (d) {
141                         return d;
142                     }
143                 }
144                 return value;
145             });
146 
147 
148     This is a reference implementation. You are free to copy, modify, or
149     redistribute.
150 */
151 
152 /*jslint evil: true, strict: false */
153 
154 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
155     call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
156     getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
157     lastIndex, length, parse, prototype, push, replace, slice, stringify,
158     test, toJSON, toString, valueOf
159 */
160 
161 
162 // Create a JSON object only if one does not already exist. We create the
163 // methods in a closure to avoid creating global variables.
164 
165 if (!this.JSON) {
166     this.JSON = {};
167 }
168 
169 (function () {
170 
171     function f(n) {
172         // Format integers to have at least two digits.
173         return n < 10 ? '0' + n : n;
174     }
175 
176     if (typeof Date.prototype.toJSON !== 'function') {
177 
178         Date.prototype.toJSON = function (key) {
179 
180             return isFinite(this.valueOf()) ?
181                    this.getUTCFullYear()   + '-' +
182                  f(this.getUTCMonth() + 1) + '-' +
183                  f(this.getUTCDate())      + 'T' +
184                  f(this.getUTCHours())     + ':' +
185                  f(this.getUTCMinutes())   + ':' +
186                  f(this.getUTCSeconds())   + 'Z' : null;
187         };
188 
189         String.prototype.toJSON =
190         Number.prototype.toJSON =
191         Boolean.prototype.toJSON = function (key) {
192             return this.valueOf();
193         };
194     }
195 
196     var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
197         escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
198         gap,
199         indent,
200         meta = {    // table of character substitutions
201             '\b': '\\b',
202             '\t': '\\t',
203             '\n': '\\n',
204             '\f': '\\f',
205             '\r': '\\r',
206             '"' : '\\"',
207             '\\': '\\\\'
208         },
209         rep;
210 
211 
212     function quote(string) {
213 
214 // If the string contains no control characters, no quote characters, and no
215 // backslash characters, then we can safely slap some quotes around it.
216 // Otherwise we must also replace the offending characters with safe escape
217 // sequences.
218 
219         escapable.lastIndex = 0;
220         return escapable.test(string) ?
221             '"' + string.replace(escapable, function (a) {
222                 var c = meta[a];
223                 return typeof c === 'string' ? c :
224                     '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
225             }) + '"' :
226             '"' + string + '"';
227     }
228 
229 
230     function str(key, holder) {
231     	
232 // Produce a string from holder[key].
233 
234         var i,          // The loop counter.
235             k,          // The member key.
236             v,          // The member value.
237             length,
238             mind = gap,
239             partial,
240             value = holder[key];
241 
242 // If the value has a toJSON method, call it to obtain a replacement value.
243 
244         if (value && typeof value === 'object' &&
245                 typeof value.toJSON === 'function') {
246             value = value.toJSON(key);
247         }
248 
249 // If we were called with a replacer function, then call the replacer to
250 // obtain a replacement value.
251 
252         if (typeof rep === 'function') {
253             value = rep.call(holder, key, value);
254         }
255 
256 // What happens next depends on the value's type.
257 
258         switch (typeof value) {
259         case 'string':
260             return quote(value);
261 
262         case 'number':
263 
264 // JSON numbers must be finite. Encode non-finite numbers as null.
265 
266             return isFinite(value) ? String(value) : 'null';
267 
268         case 'boolean':
269         case 'null':
270 
271 // If the value is a boolean or null, convert it to a string. Note:
272 // typeof null does not produce 'null'. The case is included here in
273 // the remote chance that this gets fixed someday.
274 
275             return String(value);
276 
277 // If the type is 'object', we might be dealing with an object or an array or
278 // null.
279 
280         case 'object':
281         	
282 // Due to a specification blunder in ECMAScript, typeof null is 'object',
283 // so watch out for that case.
284 
285             if (!value) {
286                 return 'null';
287             }
288             
289 // Make an array to hold the partial results of stringifying this object value.
290 
291             gap += indent;
292             partial = [];
293 
294 // Is the value an array?
295             
296             if (Object.prototype.toString.apply(value) === '[object Array]') {
297 
298             	
299 // The value is an array. Stringify every element. Use null as a placeholder
300 // for non-JSON values.
301 
302                 length = value.length;
303                 for (i = 0; i < length; i += 1) {
304                     partial[i] = str(i, value) || 'null';
305                 }
306 
307 // Join all of the elements together, separated with commas, and wrap them in
308 // brackets.
309 
310                 v = partial.length === 0 ? '[]' :
311                     gap ? '[\n' + gap +
312                             partial.join(',\n' + gap) + '\n' +
313                                 mind + ']' :
314                           '[' + partial.join(',') + ']';
315                 gap = mind;
316                 return v;
317             }
318 
319 // If the replacer is an array, use it to select the members to be stringified.
320             
321             if (rep && typeof rep === 'object') {
322                 length = rep.length;
323                 for (i = 0; i < length; i += 1) {
324                     k = rep[i];
325                     if (typeof k === 'string') {
326                         v = str(k, value);
327                         if (v) {
328                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
329                         }
330                     }
331                 }
332             } else {
333 
334 // Otherwise, iterate through all of the keys in the object.
335             	
336             	
337                 for (k in value) {
338                 	
339                 	if (typeof(value[k]) != 'function'){ //i added this instead of own property because
340                 	//has own property sometimes wont work if you use props from inheritated objects
341                     //if (Object.hasOwnProperty.call(value, k)) {
342                     	
343                         v = str(k, value);
344                         if (v) {
345                             partial.push(quote(k) + (gap ? ': ' : ':') + v);
346                         }
347                     }
348                 }
349             }
350 
351 // Join all of the member texts together, separated with commas,
352 // and wrap them in braces.
353 
354             v = partial.length === 0 ? '{}' :
355                 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
356                         mind + '}' : '{' + partial.join(',') + '}';
357             gap = mind;
358             return v;
359         }
360     }
361 
362 // If the JSON object does not yet have a stringify method, give it one.
363 
364     if (typeof JSON._stringify !== 'function') {
365         JSON._stringify = function (value, replacer, space) {
366 
367 // The stringify method takes a value and an optional replacer, and an optional
368 // space parameter, and returns a JSON text. The replacer can be a function
369 // that can replace values, or an array of strings that will select the keys.
370 // A default replacer method can be provided. Use of the space parameter can
371 // produce text that is more easily readable.
372 
373             var i;
374             gap = '';
375             indent = '';
376 
377 // If the space parameter is a number, make an indent string containing that
378 // many spaces.
379 
380             if (typeof space === 'number') {
381                 for (i = 0; i < space; i += 1) {
382                     indent += ' ';
383                 }
384                
385 // If the space parameter is a string, it will be used as the indent string.
386 
387             } else if (typeof space === 'string') {
388                 indent = space;
389             }
390             
391 // If there is a replacer, it must be a function or an array.
392 // Otherwise, throw an error.
393 
394             rep = replacer;
395             if (replacer && typeof replacer !== 'function' &&
396                     (typeof replacer !== 'object' ||
397                      typeof replacer.length !== 'number')) {
398                 throw new Error('JSON.stringify');
399             }
400             
401 // Make a fake root object containing our value under the key of ''.
402 // Return the result of stringifying the value.
403 
404             return str('', {'': value});
405         };
406     }
407 
408 
409 // If the JSON object does not yet have a parse method, give it one.
410 
411     if (typeof JSON.parse !== 'function') {
412         JSON.parse = function (text, reviver) {
413 
414 // The parse method takes a text and an optional reviver function, and returns
415 // a JavaScript value if the text is a valid JSON text.
416 
417             var j;
418 
419             function walk(holder, key) {
420 
421 // The walk method is used to recursively walk the resulting structure so
422 // that modifications can be made.
423 
424                 var k, v, value = holder[key];
425                 if (value && typeof value === 'object') {
426                     for (k in value) {
427                         if (Object.hasOwnProperty.call(value, k)) {
428                             v = walk(value, k);
429                             if (v !== undefined) {
430                                 value[k] = v;
431                             } else {
432                                 delete value[k];
433                             }
434                         }
435                     }
436                 }
437                 return reviver.call(holder, key, value);
438             }
439 
440 
441 // Parsing happens in four stages. In the first stage, we replace certain
442 // Unicode characters with escape sequences. JavaScript handles many characters
443 // incorrectly, either silently deleting them, or treating them as line endings.
444 
445             text = String(text);
446             cx.lastIndex = 0;
447             if (cx.test(text)) {
448                 text = text.replace(cx, function (a) {
449                     return '\\u' +
450                         ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
451                 });
452             }
453 
454 // In the second stage, we run the text against regular expressions that look
455 // for non-JSON patterns. We are especially concerned with '()' and 'new'
456 // because they can cause invocation, and '=' because it can cause mutation.
457 // But just to be safe, we want to reject all unexpected forms.
458 
459 // We split the second stage into 4 regexp operations in order to work around
460 // crippling inefficiencies in IE's and Safari's regexp engines. First we
461 // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
462 // replace all simple value tokens with ']' characters. Third, we delete all
463 // open brackets that follow a colon or comma or that begin the text. Finally,
464 // we look to see that the remaining characters are only whitespace or ']' or
465 // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
466 
467             if (/^[\],:{}\s]*$/
468 .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
469 .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
470 .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
471 
472 // In the third stage we use the eval function to compile the text into a
473 // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
474 // in JavaScript: it can begin a block or an object literal. We wrap the text
475 // in parens to eliminate the ambiguity.
476 
477                 j = eval('(' + text + ')');
478 
479 // In the optional fourth stage, we recursively walk the new structure, passing
480 // each name/value pair to a reviver function for possible transformation.
481 
482                 return typeof reviver === 'function' ?
483                     walk({'': j}, '') : j;
484             }
485 
486 // If the text is not JSON parseable, then a SyntaxError is thrown.
487 
488             throw new SyntaxError('JSON.parse');
489         };
490     }
491 }());