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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 | 59 |
60 function JSONParse(text, reviver) { | 60 function JSONParse(text, reviver) { |
61 var unfiltered = ParseJSONUnfiltered(text); | 61 var unfiltered = ParseJSONUnfiltered(text); |
62 if (IS_FUNCTION(reviver)) { | 62 if (IS_FUNCTION(reviver)) { |
63 return Revive({'': unfiltered}, '', reviver); | 63 return Revive({'': unfiltered}, '', reviver); |
64 } else { | 64 } else { |
65 return unfiltered; | 65 return unfiltered; |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 function QuoteJSONString(str) { | |
70 var quoted_str = %QuoteJSONString(str); | |
71 if (IS_STRING(quoted_str)) return quoted_str; | |
72 return '"' + str + '"'; | |
73 } | |
74 | |
75 function StackContains(stack, val) { | 69 function StackContains(stack, val) { |
76 var length = stack.length; | 70 var length = stack.length; |
77 for (var i = 0; i < length; i++) { | 71 for (var i = 0; i < length; i++) { |
78 if (stack[i] === val) { | 72 if (stack[i] === val) { |
79 return true; | 73 return true; |
80 } | 74 } |
81 } | 75 } |
82 return false; | 76 return false; |
83 } | 77 } |
84 | 78 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 var stepback = indent; | 115 var stepback = indent; |
122 indent += gap; | 116 indent += gap; |
123 var partial = []; | 117 var partial = []; |
124 if (IS_ARRAY(replacer)) { | 118 if (IS_ARRAY(replacer)) { |
125 var length = replacer.length; | 119 var length = replacer.length; |
126 for (var i = 0; i < length; i++) { | 120 for (var i = 0; i < length; i++) { |
127 if (ObjectHasOwnProperty.call(replacer, i)) { | 121 if (ObjectHasOwnProperty.call(replacer, i)) { |
128 var p = replacer[i]; | 122 var p = replacer[i]; |
129 var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 123 var strP = JSONSerialize(p, value, replacer, stack, indent, gap); |
130 if (!IS_UNDEFINED(strP)) { | 124 if (!IS_UNDEFINED(strP)) { |
131 var member = QuoteJSONString(p) + ":"; | 125 var member = %QuoteJSONString(p) + ":"; |
132 if (gap != "") member += " "; | 126 if (gap != "") member += " "; |
133 member += strP; | 127 member += strP; |
134 partial.push(member); | 128 partial.push(member); |
135 } | 129 } |
136 } | 130 } |
137 } | 131 } |
138 } else { | 132 } else { |
139 for (var p in value) { | 133 for (var p in value) { |
140 if (ObjectHasOwnProperty.call(value, p)) { | 134 if (ObjectHasOwnProperty.call(value, p)) { |
141 var strP = JSONSerialize(p, value, replacer, stack, indent, gap); | 135 var strP = JSONSerialize(p, value, replacer, stack, indent, gap); |
142 if (!IS_UNDEFINED(strP)) { | 136 if (!IS_UNDEFINED(strP)) { |
143 var member = QuoteJSONString(p) + ":"; | 137 var member = %QuoteJSONString(p) + ":"; |
144 if (gap != "") member += " "; | 138 if (gap != "") member += " "; |
145 member += strP; | 139 member += strP; |
146 partial.push(member); | 140 partial.push(member); |
147 } | 141 } |
148 } | 142 } |
149 } | 143 } |
150 } | 144 } |
151 var final; | 145 var final; |
152 if (gap == "") { | 146 if (gap == "") { |
153 final = "{" + partial.join(",") + "}"; | 147 final = "{" + partial.join(",") + "}"; |
(...skipping 24 matching lines...) Expand all Loading... |
178 if (IS_NUMBER_WRAPPER(value)) { | 172 if (IS_NUMBER_WRAPPER(value)) { |
179 value = $Number(value); | 173 value = $Number(value); |
180 } else if (IS_STRING_WRAPPER(value)) { | 174 } else if (IS_STRING_WRAPPER(value)) { |
181 value = $String(value); | 175 value = $String(value); |
182 } else if (IS_BOOLEAN_WRAPPER(value)) { | 176 } else if (IS_BOOLEAN_WRAPPER(value)) { |
183 value = %_ValueOf(value); | 177 value = %_ValueOf(value); |
184 } | 178 } |
185 } | 179 } |
186 switch (typeof value) { | 180 switch (typeof value) { |
187 case "string": | 181 case "string": |
188 return QuoteJSONString(value); | 182 return %QuoteJSONString(value); |
189 case "object": | 183 case "object": |
190 if (!value) { | 184 if (!value) { |
191 return "null"; | 185 return "null"; |
192 } else if (IS_ARRAY(value)) { | 186 } else if (IS_ARRAY(value)) { |
193 return SerializeArray(value, replacer, stack, indent, gap); | 187 return SerializeArray(value, replacer, stack, indent, gap); |
194 } else { | 188 } else { |
195 return SerializeObject(value, replacer, stack, indent, gap); | 189 return SerializeObject(value, replacer, stack, indent, gap); |
196 } | 190 } |
197 case "number": | 191 case "number": |
198 return $isFinite(value) ? $String(value) : "null"; | 192 return $isFinite(value) ? $String(value) : "null"; |
199 case "boolean": | 193 case "boolean": |
200 return value ? "true" : "false"; | 194 return value ? "true" : "false"; |
201 } | 195 } |
202 } | 196 } |
203 | 197 |
| 198 function BasicSerializeArray(value, stack) { |
| 199 if (StackContains(stack, value)) { |
| 200 throw MakeTypeError('circular_structure', []); |
| 201 } |
| 202 stack.push(value); |
| 203 var partial = []; |
| 204 var len = value.length; |
| 205 for (var i = 0; i < len; i++) { |
| 206 var strP = BasicJSONSerialize($String(i), value, stack); |
| 207 if (IS_UNDEFINED(strP)) strP = "null"; |
| 208 partial.push(strP); |
| 209 } |
| 210 stack.pop(); |
| 211 return "[" + partial.join() + "]"; |
| 212 } |
| 213 |
| 214 function BasicSerializeObject(value, stack) { |
| 215 if (StackContains(stack, value)) { |
| 216 throw MakeTypeError('circular_structure', []); |
| 217 } |
| 218 stack.push(value); |
| 219 var partial = []; |
| 220 for (var p in value) { |
| 221 if (ObjectHasOwnProperty.call(value, p)) { |
| 222 var strP = BasicJSONSerialize(p, value, stack); |
| 223 if (!IS_UNDEFINED(strP)) partial.push(%QuoteJSONString(p) + ":" + strP); |
| 224 } |
| 225 } |
| 226 stack.pop(); |
| 227 return "{" + partial.join() + "}"; |
| 228 } |
| 229 |
| 230 function BasicJSONSerialize(key, holder, stack) { |
| 231 var value = holder[key]; |
| 232 if (IS_OBJECT(value) && value) { |
| 233 var toJSON = value.toJSON; |
| 234 if (IS_FUNCTION(toJSON)) value = toJSON.call(value, key); |
| 235 } |
| 236 // Unwrap value if necessary |
| 237 if (IS_OBJECT(value)) { |
| 238 if (IS_NUMBER_WRAPPER(value)) { |
| 239 value = $Number(value); |
| 240 } else if (IS_STRING_WRAPPER(value)) { |
| 241 value = $String(value); |
| 242 } else if (IS_BOOLEAN_WRAPPER(value)) { |
| 243 value = %_ValueOf(value); |
| 244 } |
| 245 } |
| 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 } |
| 263 |
204 function JSONStringify(value, replacer, space) { | 264 function JSONStringify(value, replacer, space) { |
205 var stack = []; | 265 if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) { |
206 var indent = ""; | 266 return BasicJSONSerialize('', {'': value}, []); |
| 267 } |
207 if (IS_OBJECT(space)) { | 268 if (IS_OBJECT(space)) { |
208 // Unwrap 'space' if it is wrapped | 269 // Unwrap 'space' if it is wrapped |
209 if (IS_NUMBER_WRAPPER(space)) { | 270 if (IS_NUMBER_WRAPPER(space)) { |
210 space = $Number(space); | 271 space = $Number(space); |
211 } else if (IS_STRING_WRAPPER(space)) { | 272 } else if (IS_STRING_WRAPPER(space)) { |
212 space = $String(space); | 273 space = $String(space); |
213 } | 274 } |
214 } | 275 } |
215 var gap; | 276 var gap; |
216 if (IS_NUMBER(space)) { | 277 if (IS_NUMBER(space)) { |
217 space = $Math.min(ToInteger(space), 10); | 278 space = $Math.min(ToInteger(space), 10); |
218 gap = ""; | 279 gap = ""; |
219 for (var i = 0; i < space; i++) { | 280 for (var i = 0; i < space; i++) { |
220 gap += " "; | 281 gap += " "; |
221 } | 282 } |
222 } else if (IS_STRING(space)) { | 283 } else if (IS_STRING(space)) { |
223 if (space.length > 10) { | 284 if (space.length > 10) { |
224 gap = space.substring(0, 10); | 285 gap = space.substring(0, 10); |
225 } else { | 286 } else { |
226 gap = space; | 287 gap = space; |
227 } | 288 } |
228 } else { | 289 } else { |
229 gap = ""; | 290 gap = ""; |
230 } | 291 } |
231 return JSONSerialize('', {'': value}, replacer, stack, indent, gap); | 292 return JSONSerialize('', {'': value}, replacer, [], "", gap); |
232 } | 293 } |
233 | 294 |
234 function SetupJSON() { | 295 function SetupJSON() { |
235 InstallFunctions($JSON, DONT_ENUM, $Array( | 296 InstallFunctions($JSON, DONT_ENUM, $Array( |
236 "parse", JSONParse, | 297 "parse", JSONParse, |
237 "stringify", JSONStringify | 298 "stringify", JSONStringify |
238 )); | 299 )); |
239 } | 300 } |
240 | 301 |
241 SetupJSON(); | 302 SetupJSON(); |
OLD | NEW |