diff --git a/src/json.js b/src/json.js index 0034176ba0..e5364e64f6 100644 --- a/src/json.js +++ b/src/json.js @@ -179,24 +179,60 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) { function BasicSerializeArray(value, stack, builder) { + var len = value.length; + if (len == 0) { + builder.push("[]"); + return; + } if (!%PushIfAbsent(stack, value)) { throw MakeTypeError('circular_structure', []); } builder.push("["); - var len = value.length; - for (var i = 0; i < len; i++) { + var val = value[0]; + if (IS_STRING(val)) { + // First entry is a string. Remaining entries are likely to be strings too. + builder.push(%QuoteJSONString(val)); + for (var i = 1; i < len; i++) { + builder.push(","); + val = value[i]; + if (IS_STRING(val)) { + builder.push(%QuoteJSONString(val)); + } else { + var before = builder.length; + BasicJSONSerialize(i, value[i], stack, builder); + if (before == builder.length) builder.push("null"); + } + } + } else if (IS_NUMBER(val)) { + // First entry is a number. Remaining entries are likely to be numbers too. + builder.push(NUMBER_IS_FINITE(val) ? %_NumberToString(val) : "null"); + for (var i = 1; i < len; i++) { + builder.push(","); + val = value[i]; + if (IS_NUMBER(val)) { + builder.push(NUMBER_IS_FINITE(val) + ? %_NumberToString(val) + : "null"); + } else { + var before = builder.length; + BasicJSONSerialize(i, value[i], stack, builder); + if (before == builder.length) builder.push("null"); + } + } + } else { var before = builder.length; - BasicJSONSerialize(i, value, stack, builder); + BasicJSONSerialize(0, val, stack, builder); if (before == builder.length) builder.push("null"); - builder.push(","); + for (var i = 1; i < len; i++) { + builder.push(","); + before = builder.length; + val = value[i]; + BasicJSONSerialize(i, val, stack, builder); + if (before == builder.length) builder.push("null"); + } } stack.pop(); - if (builder.pop() != ",") { - builder.push("[]"); // Zero length array. Push "[" back on. - } else { - builder.push("]"); - } - + builder.push("]"); } @@ -210,7 +246,7 @@ function BasicSerializeObject(value, stack, builder) { builder.push(%QuoteJSONString(p)); builder.push(":"); var before = builder.length; - BasicJSONSerialize(p, value, stack, builder); + BasicJSONSerialize(p, value[p], stack, builder); if (before == builder.length) { builder.pop(); builder.pop(); @@ -228,8 +264,7 @@ function BasicSerializeObject(value, stack, builder) { } -function BasicJSONSerialize(key, holder, stack, builder) { - var value = holder[key]; +function BasicJSONSerialize(key, value, stack, builder) { if (IS_SPEC_OBJECT(value)) { var toJSON = value.toJSON; if (IS_FUNCTION(toJSON)) { @@ -266,7 +301,7 @@ function BasicJSONSerialize(key, holder, stack, builder) { function JSONStringify(value, replacer, space) { if (%_ArgumentsLength() == 1) { var builder = []; - BasicJSONSerialize('', {'': value}, [], builder); + BasicJSONSerialize('', value, [], builder); if (builder.length == 0) return; var result = %_FastAsciiArrayJoin(builder, ""); if (!IS_UNDEFINED(result)) return result;