| 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 if (IS_FUNCTION(toJSON)) { | 146 if (IS_FUNCTION(toJSON)) { |
| 147 value = %_CallFunction(value, key, toJSON); | 147 value = %_CallFunction(value, key, toJSON); |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 if (IS_FUNCTION(replacer)) { | 150 if (IS_FUNCTION(replacer)) { |
| 151 value = %_CallFunction(holder, key, value, replacer); | 151 value = %_CallFunction(holder, key, value, replacer); |
| 152 } | 152 } |
| 153 if (IS_STRING(value)) { | 153 if (IS_STRING(value)) { |
| 154 return %QuoteJSONString(value); | 154 return %QuoteJSONString(value); |
| 155 } else if (IS_NUMBER(value)) { | 155 } else if (IS_NUMBER(value)) { |
| 156 return NUMBER_IS_FINITE(value) ? $String(value) : "null"; | 156 return JSON_NUMBER_TO_STRING(value); |
| 157 } else if (IS_BOOLEAN(value)) { | 157 } else if (IS_BOOLEAN(value)) { |
| 158 return value ? "true" : "false"; | 158 return value ? "true" : "false"; |
| 159 } else if (IS_NULL(value)) { | 159 } else if (IS_NULL(value)) { |
| 160 return "null"; | 160 return "null"; |
| 161 } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) { | 161 } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) { |
| 162 // Non-callable object. If it's a primitive wrapper, it must be unwrapped. | 162 // Non-callable object. If it's a primitive wrapper, it must be unwrapped. |
| 163 if (IS_ARRAY(value)) { | 163 if (IS_ARRAY(value)) { |
| 164 return SerializeArray(value, replacer, stack, indent, gap); | 164 return SerializeArray(value, replacer, stack, indent, gap); |
| 165 } else if (IS_NUMBER_WRAPPER(value)) { | 165 } else if (IS_NUMBER_WRAPPER(value)) { |
| 166 value = ToNumber(value); | 166 value = ToNumber(value); |
| 167 return NUMBER_IS_FINITE(value) ? ToString(value) : "null"; | 167 return JSON_NUMBER_TO_STRING(value); |
| 168 } else if (IS_STRING_WRAPPER(value)) { | 168 } else if (IS_STRING_WRAPPER(value)) { |
| 169 return %QuoteJSONString(ToString(value)); | 169 return %QuoteJSONString(ToString(value)); |
| 170 } else if (IS_BOOLEAN_WRAPPER(value)) { | 170 } else if (IS_BOOLEAN_WRAPPER(value)) { |
| 171 return %_ValueOf(value) ? "true" : "false"; | 171 return %_ValueOf(value) ? "true" : "false"; |
| 172 } else { | 172 } else { |
| 173 return SerializeObject(value, replacer, stack, indent, gap); | 173 return SerializeObject(value, replacer, stack, indent, gap); |
| 174 } | 174 } |
| 175 } | 175 } |
| 176 // Undefined or a callable object. | 176 // Undefined or a callable object. |
| 177 return void 0; | 177 return void 0; |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 function BasicSerializeArray(value, stack, builder) { | 181 function BasicSerializeArray(value, stack, builder) { |
| 182 var len = value.length; | 182 var len = value.length; |
| 183 if (len == 0) { | 183 if (len == 0) { |
| 184 builder.push("[]"); | 184 builder.push("[]"); |
| 185 return; | 185 return; |
| 186 } | 186 } |
| 187 if (!%PushIfAbsent(stack, value)) { | 187 if (!%PushIfAbsent(stack, value)) { |
| 188 throw MakeTypeError('circular_structure', $Array()); | 188 throw MakeTypeError('circular_structure', $Array()); |
| 189 } | 189 } |
| 190 builder.push("["); | 190 builder.push("["); |
| 191 var val = value[0]; | 191 var val = value[0]; |
| 192 if (IS_STRING(val)) { | 192 if (IS_STRING(val)) { |
| 193 // First entry is a string. Remaining entries are likely to be strings too. | 193 // First entry is a string. Remaining entries are likely to be strings too. |
| 194 builder.push(%QuoteJSONString(val)); | 194 var array_string = %QuoteJSONStringArray(value); |
| 195 for (var i = 1; i < len; i++) { | 195 if (!IS_UNDEFINED(array_string)) { |
| 196 val = value[i]; | 196 // array_string also includes bracket characters so we are done. |
| 197 if (IS_STRING(val)) { | 197 builder[builder.length - 1] = array_string; |
| 198 builder.push(%QuoteJSONStringComma(val)); | 198 stack.pop(); |
| 199 } else { | 199 return; |
| 200 builder.push(","); | 200 } else { |
| 201 var before = builder.length; | 201 builder.push(%QuoteJSONString(val)); |
| 202 BasicJSONSerialize(i, value[i], stack, builder); | 202 for (var i = 1; i < len; i++) { |
| 203 if (before == builder.length) builder[before - 1] = ",null"; | 203 val = value[i]; |
| 204 if (IS_STRING(val)) { |
| 205 builder.push(%QuoteJSONStringComma(val)); |
| 206 } else { |
| 207 builder.push(","); |
| 208 var before = builder.length; |
| 209 BasicJSONSerialize(i, val, stack, builder); |
| 210 if (before == builder.length) builder[before - 1] = ",null"; |
| 211 } |
| 204 } | 212 } |
| 205 } | 213 } |
| 206 } else if (IS_NUMBER(val)) { | 214 } else if (IS_NUMBER(val)) { |
| 207 // First entry is a number. Remaining entries are likely to be numbers too. | 215 // First entry is a number. Remaining entries are likely to be numbers too. |
| 208 builder.push(NUMBER_IS_FINITE(val) ? %_NumberToString(val) : "null"); | 216 builder.push(JSON_NUMBER_TO_STRING(val)); |
| 209 for (var i = 1; i < len; i++) { | 217 for (var i = 1; i < len; i++) { |
| 210 builder.push(","); | 218 builder.push(","); |
| 211 val = value[i]; | 219 val = value[i]; |
| 212 if (IS_NUMBER(val)) { | 220 if (IS_NUMBER(val)) { |
| 213 builder.push(NUMBER_IS_FINITE(val) | 221 builder.push(JSON_NUMBER_TO_STRING(val)); |
| 214 ? %_NumberToString(val) | |
| 215 : "null"); | |
| 216 } else { | 222 } else { |
| 217 var before = builder.length; | 223 var before = builder.length; |
| 218 BasicJSONSerialize(i, value[i], stack, builder); | 224 BasicJSONSerialize(i, val, stack, builder); |
| 219 if (before == builder.length) builder[before - 1] = ",null"; | 225 if (before == builder.length) builder[before - 1] = ",null"; |
| 220 } | 226 } |
| 221 } | 227 } |
| 222 } else { | 228 } else { |
| 223 var before = builder.length; | 229 var before = builder.length; |
| 224 BasicJSONSerialize(0, val, stack, builder); | 230 BasicJSONSerialize(0, val, stack, builder); |
| 225 if (before == builder.length) builder.push("null"); | 231 if (before == builder.length) builder.push("null"); |
| 226 for (var i = 1; i < len; i++) { | 232 for (var i = 1; i < len; i++) { |
| 227 builder.push(","); | 233 builder.push(","); |
| 228 before = builder.length; | 234 before = builder.length; |
| 229 val = value[i]; | 235 BasicJSONSerialize(i, value[i], stack, builder); |
| 230 BasicJSONSerialize(i, val, stack, builder); | |
| 231 if (before == builder.length) builder[before - 1] = ",null"; | 236 if (before == builder.length) builder[before - 1] = ",null"; |
| 232 } | 237 } |
| 233 } | 238 } |
| 234 stack.pop(); | 239 stack.pop(); |
| 235 builder.push("]"); | 240 builder.push("]"); |
| 236 } | 241 } |
| 237 | 242 |
| 238 | 243 |
| 239 function BasicSerializeObject(value, stack, builder) { | 244 function BasicSerializeObject(value, stack, builder) { |
| 240 if (!%PushIfAbsent(stack, value)) { | 245 if (!%PushIfAbsent(stack, value)) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 266 | 271 |
| 267 | 272 |
| 268 function BasicJSONSerialize(key, value, stack, builder) { | 273 function BasicJSONSerialize(key, value, stack, builder) { |
| 269 if (IS_SPEC_OBJECT(value)) { | 274 if (IS_SPEC_OBJECT(value)) { |
| 270 var toJSON = value.toJSON; | 275 var toJSON = value.toJSON; |
| 271 if (IS_FUNCTION(toJSON)) { | 276 if (IS_FUNCTION(toJSON)) { |
| 272 value = %_CallFunction(value, ToString(key), toJSON); | 277 value = %_CallFunction(value, ToString(key), toJSON); |
| 273 } | 278 } |
| 274 } | 279 } |
| 275 if (IS_STRING(value)) { | 280 if (IS_STRING(value)) { |
| 276 builder.push(%QuoteJSONString(value)); | 281 builder.push(value !== "" ? %QuoteJSONString(value) : '""'); |
| 277 } else if (IS_NUMBER(value)) { | 282 } else if (IS_NUMBER(value)) { |
| 278 builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null"); | 283 builder.push(JSON_NUMBER_TO_STRING(value)); |
| 279 } else if (IS_BOOLEAN(value)) { | 284 } else if (IS_BOOLEAN(value)) { |
| 280 builder.push(value ? "true" : "false"); | 285 builder.push(value ? "true" : "false"); |
| 281 } else if (IS_NULL(value)) { | 286 } else if (IS_NULL(value)) { |
| 282 builder.push("null"); | 287 builder.push("null"); |
| 283 } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) { | 288 } else if (IS_SPEC_OBJECT(value) && !(typeof value == "function")) { |
| 284 // Value is a non-callable object. | 289 // Value is a non-callable object. |
| 285 // Unwrap value if necessary | 290 // Unwrap value if necessary |
| 286 if (IS_NUMBER_WRAPPER(value)) { | 291 if (IS_NUMBER_WRAPPER(value)) { |
| 287 value = ToNumber(value); | 292 value = ToNumber(value); |
| 288 builder.push(NUMBER_IS_FINITE(value) ? %_NumberToString(value) : "null"); | 293 builder.push(JSON_NUMBER_TO_STRING(value)); |
| 289 } else if (IS_STRING_WRAPPER(value)) { | 294 } else if (IS_STRING_WRAPPER(value)) { |
| 290 builder.push(%QuoteJSONString(ToString(value))); | 295 builder.push(%QuoteJSONString(ToString(value))); |
| 291 } else if (IS_BOOLEAN_WRAPPER(value)) { | 296 } else if (IS_BOOLEAN_WRAPPER(value)) { |
| 292 builder.push(%_ValueOf(value) ? "true" : "false"); | 297 builder.push(%_ValueOf(value) ? "true" : "false"); |
| 293 } else if (IS_ARRAY(value)) { | 298 } else if (IS_ARRAY(value)) { |
| 294 BasicSerializeArray(value, stack, builder); | 299 BasicSerializeArray(value, stack, builder); |
| 295 } else { | 300 } else { |
| 296 BasicSerializeObject(value, stack, builder); | 301 BasicSerializeObject(value, stack, builder); |
| 297 } | 302 } |
| 298 } | 303 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 } | 338 } |
| 334 | 339 |
| 335 function SetupJSON() { | 340 function SetupJSON() { |
| 336 InstallFunctions($JSON, DONT_ENUM, $Array( | 341 InstallFunctions($JSON, DONT_ENUM, $Array( |
| 337 "parse", JSONParse, | 342 "parse", JSONParse, |
| 338 "stringify", JSONStringify | 343 "stringify", JSONStringify |
| 339 )); | 344 )); |
| 340 } | 345 } |
| 341 | 346 |
| 342 SetupJSON(); | 347 SetupJSON(); |
| OLD | NEW |