OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 } else { | 188 } else { |
189 return SerializeObject(value, replacer, stack, indent, gap); | 189 return SerializeObject(value, replacer, stack, indent, gap); |
190 } | 190 } |
191 case "number": | 191 case "number": |
192 return $isFinite(value) ? $String(value) : "null"; | 192 return $isFinite(value) ? $String(value) : "null"; |
193 case "boolean": | 193 case "boolean": |
194 return value ? "true" : "false"; | 194 return value ? "true" : "false"; |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 function BasicSerializeArray(value, stack) { | 198 |
199 function BasicSerializeArray(value, stack, builder) { | |
199 if (StackContains(stack, value)) { | 200 if (StackContains(stack, value)) { |
200 throw MakeTypeError('circular_structure', []); | 201 throw MakeTypeError('circular_structure', []); |
201 } | 202 } |
202 stack.push(value); | 203 stack.push(value); |
203 var partial = []; | 204 builder.push("["); |
204 var len = value.length; | 205 var len = value.length; |
205 for (var i = 0; i < len; i++) { | 206 for (var i = 0; i < len; i++) { |
206 var strP = BasicJSONSerialize($String(i), value, stack); | 207 var before = builder.length; |
207 if (IS_UNDEFINED(strP)) strP = "null"; | 208 BasicJSONSerialize($String(i), value, stack, builder); |
208 partial.push(strP); | 209 if (before == builder.length) builder.push("null"); |
210 builder.push(","); | |
Lasse Reichstein
2010/12/06 08:48:45
An idiom often used in "picket fence loops" like t
| |
209 } | 211 } |
210 stack.pop(); | 212 stack.pop(); |
211 return "[" + partial.join() + "]"; | 213 if (builder.pop() != ",") { |
Erik Corry
2010/12/05 15:09:06
This seems a bit indirect. I think it would be cl
sandholm
2010/12/06 11:42:31
I added a comment.
On 2010/12/05 15:09:06, Erik Co
| |
214 builder.push("[]"); | |
215 } else { | |
216 builder.push("]"); | |
217 } | |
212 } | 218 } |
213 | 219 |
214 function BasicSerializeObject(value, stack) { | 220 |
221 function BasicSerializeObject(value, stack, builder) { | |
215 if (StackContains(stack, value)) { | 222 if (StackContains(stack, value)) { |
216 throw MakeTypeError('circular_structure', []); | 223 throw MakeTypeError('circular_structure', []); |
217 } | 224 } |
218 stack.push(value); | 225 stack.push(value); |
219 var partial = []; | 226 builder.push("{"); |
220 for (var p in value) { | 227 for (var p in value) { |
221 if (ObjectHasOwnProperty.call(value, p)) { | 228 if (ObjectHasOwnProperty.call(value, p)) { |
222 var strP = BasicJSONSerialize(p, value, stack); | 229 builder.push(%QuoteJSONString(p), ":"); |
Erik Corry
2010/12/05 15:09:06
If you didn't already try it I think it would be i
sandholm
2010/12/06 11:42:31
I experimented a bit. Will submit another change.
| |
223 if (!IS_UNDEFINED(strP)) partial.push(%QuoteJSONString(p) + ":" + strP); | 230 var before = builder.length; |
231 BasicJSONSerialize(p, value, stack, builder); | |
232 if (before == builder.length) { | |
233 builder.pop(); | |
234 builder.pop(); | |
235 } else { | |
236 builder.push(","); | |
237 } | |
224 } | 238 } |
225 } | 239 } |
226 stack.pop(); | 240 stack.pop(); |
227 return "{" + partial.join() + "}"; | 241 if (builder.pop() != ",") { |
Erik Corry
2010/12/05 15:09:06
Again, I find this convoluted. A boolean variable
sandholm
2010/12/06 11:42:31
I added a comment
On 2010/12/05 15:09:06, Erik Cor
| |
242 builder.push("{}"); | |
243 } else { | |
244 builder.push("}"); | |
245 } | |
228 } | 246 } |
229 | 247 |
230 function BasicJSONSerialize(key, holder, stack) { | 248 |
249 function BasicJSONSerialize(key, holder, stack, builder) { | |
231 var value = holder[key]; | 250 var value = holder[key]; |
232 if (IS_OBJECT(value) && value) { | 251 if (IS_OBJECT(value) && value) { |
233 var toJSON = value.toJSON; | 252 var toJSON = value.toJSON; |
234 if (IS_FUNCTION(toJSON)) value = toJSON.call(value, key); | 253 if (IS_FUNCTION(toJSON)) value = toJSON.call(value, key); |
235 } | 254 } |
236 // Unwrap value if necessary | 255 if (IS_STRING(value)) { |
237 if (IS_OBJECT(value)) { | 256 builder.push(%QuoteJSONString(value)); |
257 } else if (IS_NUMBER(value)) { | |
258 builder.push(($isFinite(value) ? $String(value) : "null")); | |
Erik Corry
2010/12/05 15:09:06
I wonder how $String compares speedwise to ("" + v
Lasse Reichstein
2010/12/06 08:48:45
Use %_NumberToString instead of the generic $Strin
sandholm
2010/12/06 11:42:31
Done.
sandholm
2010/12/06 11:42:31
Done.
| |
259 } else if (IS_BOOLEAN(value)) { | |
260 builder.push((value ? "true" : "false")); | |
261 } else if (IS_OBJECT(value)) { | |
262 // Unwrap value if necessary | |
238 if (IS_NUMBER_WRAPPER(value)) { | 263 if (IS_NUMBER_WRAPPER(value)) { |
239 value = $Number(value); | 264 value = $Number(value); |
Lasse Reichstein
2010/12/06 08:48:45
use %_ValueOf to extract the number.
sandholm
2010/12/06 11:42:31
Done.
| |
265 builder.push(($isFinite(value) ? $String(value) : "null")); | |
Lasse Reichstein
2010/12/06 08:48:45
%_NumberToString here too.
sandholm
2010/12/06 11:42:31
Done.
| |
240 } else if (IS_STRING_WRAPPER(value)) { | 266 } else if (IS_STRING_WRAPPER(value)) { |
241 value = $String(value); | 267 builder.push(%QuoteJSONString($String(value))); |
242 } else if (IS_BOOLEAN_WRAPPER(value)) { | 268 } else if (IS_BOOLEAN_WRAPPER(value)) { |
243 value = %_ValueOf(value); | 269 builder.push((%_ValueOf(value) ? "true" : "false")); |
270 } else { // Regular non-wrapped object | |
Erik Corry
2010/12/05 15:09:06
There should be 2 spaces before //
Lasse Reichstein
2010/12/06 08:48:45
I would put the comment on the next line instead.
sandholm
2010/12/06 11:42:31
Done.
sandholm
2010/12/06 11:42:31
Done.
| |
271 if (!value) { | |
272 builder.push("null"); | |
273 } else if (IS_ARRAY(value)) { | |
274 BasicSerializeArray(value, stack, builder); | |
275 } else { | |
276 BasicSerializeObject(value, stack, builder); | |
277 } | |
244 } | 278 } |
245 } | 279 } |
246 switch (typeof value) { | |
247 case "string": | |
248 return %QuoteJSONString(value); | |
249 case "object": | |
250 if (!value) { | |
251 return "null"; | |
252 } else if (IS_ARRAY(value)) { | |
253 return BasicSerializeArray(value, stack); | |
254 } else { | |
255 return BasicSerializeObject(value, stack); | |
256 } | |
257 case "number": | |
258 return $isFinite(value) ? $String(value) : "null"; | |
259 case "boolean": | |
260 return value ? "true" : "false"; | |
261 } | |
262 } | 280 } |
263 | 281 |
264 function JSONStringify(value, replacer, space) { | 282 function JSONStringify(value, replacer, space) { |
265 if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) { | 283 if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) { |
266 return BasicJSONSerialize('', {'': value}, []); | 284 var builder = []; |
285 BasicJSONSerialize('', {'': value}, [], builder); | |
286 if (builder.length == 0) return; | |
287 else return %StringBuilderConcat(builder, builder.length, ""); | |
267 } | 288 } |
268 if (IS_OBJECT(space)) { | 289 if (IS_OBJECT(space)) { |
269 // Unwrap 'space' if it is wrapped | 290 // Unwrap 'space' if it is wrapped |
270 if (IS_NUMBER_WRAPPER(space)) { | 291 if (IS_NUMBER_WRAPPER(space)) { |
271 space = $Number(space); | 292 space = $Number(space); |
272 } else if (IS_STRING_WRAPPER(space)) { | 293 } else if (IS_STRING_WRAPPER(space)) { |
273 space = $String(space); | 294 space = $String(space); |
274 } | 295 } |
275 } | 296 } |
276 var gap; | 297 var gap; |
(...skipping 16 matching lines...) Expand all Loading... | |
293 } | 314 } |
294 | 315 |
295 function SetupJSON() { | 316 function SetupJSON() { |
296 InstallFunctions($JSON, DONT_ENUM, $Array( | 317 InstallFunctions($JSON, DONT_ENUM, $Array( |
297 "parse", JSONParse, | 318 "parse", JSONParse, |
298 "stringify", JSONStringify | 319 "stringify", JSONStringify |
299 )); | 320 )); |
300 } | 321 } |
301 | 322 |
302 SetupJSON(); | 323 SetupJSON(); |
OLD | NEW |