144 |
144 |
145 This is a reference implementation. You are free to copy, modify, or |
145 This is a reference implementation. You are free to copy, modify, or |
146 redistribute. |
146 redistribute. |
147 */ |
147 */ |
148 |
148 |
149 /*jslint evil: true, strict: false, regexp: false */ |
149 /*jslint evil: true, regexp: true */ |
150 |
150 |
151 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, |
151 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, |
152 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, |
152 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, |
153 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, |
153 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, |
154 lastIndex, length, parse, prototype, push, replace, slice, stringify, |
154 lastIndex, length, parse, prototype, push, replace, slice, stringify, |
163 if (!JSON) { |
163 if (!JSON) { |
164 JSON = {}; |
164 JSON = {}; |
165 } |
165 } |
166 |
166 |
167 (function () { |
167 (function () { |
168 "use strict"; |
168 'use strict'; |
169 |
169 |
170 function f(n) { |
170 function f(n) { |
171 // Format integers to have at least two digits. |
171 // Format integers to have at least two digits. |
172 return n < 10 ? '0' + n : n; |
172 return n < 10 ? '0' + n : n; |
173 } |
173 } |
174 |
174 |
175 if (typeof Date.prototype.toJSON !== 'function') { |
175 if (typeof Date.prototype.toJSON !== 'function') { |
176 |
176 |
177 Date.prototype.toJSON = function (key) { |
177 Date.prototype.toJSON = function (key) { |
178 |
178 |
179 return isFinite(this.valueOf()) ? |
179 return isFinite(this.valueOf()) |
180 this.getUTCFullYear() + '-' + |
180 ? this.getUTCFullYear() + '-' + |
181 f(this.getUTCMonth() + 1) + '-' + |
181 f(this.getUTCMonth() + 1) + '-' + |
182 f(this.getUTCDate()) + 'T' + |
182 f(this.getUTCDate()) + 'T' + |
183 f(this.getUTCHours()) + ':' + |
183 f(this.getUTCHours()) + ':' + |
184 f(this.getUTCMinutes()) + ':' + |
184 f(this.getUTCMinutes()) + ':' + |
185 f(this.getUTCSeconds()) + 'Z' : null; |
185 f(this.getUTCSeconds()) + 'Z' |
|
186 : null; |
186 }; |
187 }; |
187 |
188 |
188 String.prototype.toJSON = |
189 String.prototype.toJSON = |
189 Number.prototype.toJSON = |
190 Number.prototype.toJSON = |
190 Boolean.prototype.toJSON = function (key) { |
191 Boolean.prototype.toJSON = function (key) { |
216 // sequences. |
217 // sequences. |
217 |
218 |
218 escapable.lastIndex = 0; |
219 escapable.lastIndex = 0; |
219 return escapable.test(string) ? '"' + string.replace(escapable, function (a) { |
220 return escapable.test(string) ? '"' + string.replace(escapable, function (a) { |
220 var c = meta[a]; |
221 var c = meta[a]; |
221 return typeof c === 'string' ? c : |
222 return typeof c === 'string' |
222 '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
223 ? c |
|
224 : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); |
223 }) + '"' : '"' + string + '"'; |
225 }) + '"' : '"' + string + '"'; |
224 } |
226 } |
225 |
227 |
226 |
228 |
227 function str(key, holder) { |
229 function str(key, holder) { |
301 } |
303 } |
302 |
304 |
303 // Join all of the elements together, separated with commas, and wrap them in |
305 // Join all of the elements together, separated with commas, and wrap them in |
304 // brackets. |
306 // brackets. |
305 |
307 |
306 v = partial.length === 0 ? '[]' : gap ? |
308 v = partial.length === 0 |
307 '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : |
309 ? '[]' |
308 '[' + partial.join(',') + ']'; |
310 : gap |
|
311 ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' |
|
312 : '[' + partial.join(',') + ']'; |
309 gap = mind; |
313 gap = mind; |
310 return v; |
314 return v; |
311 } |
315 } |
312 |
316 |
313 // If the replacer is an array, use it to select the members to be stringified. |
317 // If the replacer is an array, use it to select the members to be stringified. |
338 } |
342 } |
339 |
343 |
340 // Join all of the member texts together, separated with commas, |
344 // Join all of the member texts together, separated with commas, |
341 // and wrap them in braces. |
345 // and wrap them in braces. |
342 |
346 |
343 v = partial.length === 0 ? '{}' : gap ? |
347 v = partial.length === 0 |
344 '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : |
348 ? '{}' |
345 '{' + partial.join(',') + '}'; |
349 : gap |
|
350 ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' |
|
351 : '{' + partial.join(',') + '}'; |
346 gap = mind; |
352 gap = mind; |
347 return v; |
353 return v; |
348 } |
354 } |
349 } |
355 } |
350 |
356 |
466 j = eval('(' + text + ')'); |
472 j = eval('(' + text + ')'); |
467 |
473 |
468 // In the optional fourth stage, we recursively walk the new structure, passing |
474 // In the optional fourth stage, we recursively walk the new structure, passing |
469 // each name/value pair to a reviver function for possible transformation. |
475 // each name/value pair to a reviver function for possible transformation. |
470 |
476 |
471 return typeof reviver === 'function' ? |
477 return typeof reviver === 'function' |
472 walk({'': j}, '') : j; |
478 ? walk({'': j}, '') |
|
479 : j; |
473 } |
480 } |
474 |
481 |
475 // If the text is not JSON parseable, then a SyntaxError is thrown. |
482 // If the text is not JSON parseable, then a SyntaxError is thrown. |
476 |
483 |
477 throw new SyntaxError('JSON.parse'); |
484 throw new SyntaxError('JSON.parse'); |