Commit fb93e5bc authored by sandholm@chromium.org's avatar sandholm@chromium.org

Simplify JSON stringify and add special case for default replacer and space.

Review URL: http://codereview.chromium.org/5551002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5916 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c5c852f6
...@@ -66,12 +66,6 @@ function JSONParse(text, reviver) { ...@@ -66,12 +66,6 @@ function JSONParse(text, reviver) {
} }
} }
function QuoteJSONString(str) {
var quoted_str = %QuoteJSONString(str);
if (IS_STRING(quoted_str)) return quoted_str;
return '"' + str + '"';
}
function StackContains(stack, val) { function StackContains(stack, val) {
var length = stack.length; var length = stack.length;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
...@@ -128,7 +122,7 @@ function SerializeObject(value, replacer, stack, indent, gap) { ...@@ -128,7 +122,7 @@ function SerializeObject(value, replacer, stack, indent, gap) {
var p = replacer[i]; var p = replacer[i];
var strP = JSONSerialize(p, value, replacer, stack, indent, gap); var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) { if (!IS_UNDEFINED(strP)) {
var member = QuoteJSONString(p) + ":"; var member = %QuoteJSONString(p) + ":";
if (gap != "") member += " "; if (gap != "") member += " ";
member += strP; member += strP;
partial.push(member); partial.push(member);
...@@ -140,7 +134,7 @@ function SerializeObject(value, replacer, stack, indent, gap) { ...@@ -140,7 +134,7 @@ function SerializeObject(value, replacer, stack, indent, gap) {
if (ObjectHasOwnProperty.call(value, p)) { if (ObjectHasOwnProperty.call(value, p)) {
var strP = JSONSerialize(p, value, replacer, stack, indent, gap); var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
if (!IS_UNDEFINED(strP)) { if (!IS_UNDEFINED(strP)) {
var member = QuoteJSONString(p) + ":"; var member = %QuoteJSONString(p) + ":";
if (gap != "") member += " "; if (gap != "") member += " ";
member += strP; member += strP;
partial.push(member); partial.push(member);
...@@ -185,7 +179,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) { ...@@ -185,7 +179,7 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
} }
switch (typeof value) { switch (typeof value) {
case "string": case "string":
return QuoteJSONString(value); return %QuoteJSONString(value);
case "object": case "object":
if (!value) { if (!value) {
return "null"; return "null";
...@@ -201,9 +195,76 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) { ...@@ -201,9 +195,76 @@ function JSONSerialize(key, holder, replacer, stack, indent, gap) {
} }
} }
function BasicSerializeArray(value, stack) {
if (StackContains(stack, value)) {
throw MakeTypeError('circular_structure', []);
}
stack.push(value);
var partial = [];
var len = value.length;
for (var i = 0; i < len; i++) {
var strP = BasicJSONSerialize($String(i), value, stack);
if (IS_UNDEFINED(strP)) strP = "null";
partial.push(strP);
}
stack.pop();
return "[" + partial.join() + "]";
}
function BasicSerializeObject(value, stack) {
if (StackContains(stack, value)) {
throw MakeTypeError('circular_structure', []);
}
stack.push(value);
var partial = [];
for (var p in value) {
if (ObjectHasOwnProperty.call(value, p)) {
var strP = BasicJSONSerialize(p, value, stack);
if (!IS_UNDEFINED(strP)) partial.push(%QuoteJSONString(p) + ":" + strP);
}
}
stack.pop();
return "{" + partial.join() + "}";
}
function BasicJSONSerialize(key, holder, stack) {
var value = holder[key];
if (IS_OBJECT(value) && value) {
var toJSON = value.toJSON;
if (IS_FUNCTION(toJSON)) value = toJSON.call(value, key);
}
// Unwrap value if necessary
if (IS_OBJECT(value)) {
if (IS_NUMBER_WRAPPER(value)) {
value = $Number(value);
} else if (IS_STRING_WRAPPER(value)) {
value = $String(value);
} else if (IS_BOOLEAN_WRAPPER(value)) {
value = %_ValueOf(value);
}
}
switch (typeof value) {
case "string":
return %QuoteJSONString(value);
case "object":
if (!value) {
return "null";
} else if (IS_ARRAY(value)) {
return BasicSerializeArray(value, stack);
} else {
return BasicSerializeObject(value, stack);
}
case "number":
return $isFinite(value) ? $String(value) : "null";
case "boolean":
return value ? "true" : "false";
}
}
function JSONStringify(value, replacer, space) { function JSONStringify(value, replacer, space) {
var stack = []; if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) {
var indent = ""; return BasicJSONSerialize('', {'': value}, []);
}
if (IS_OBJECT(space)) { if (IS_OBJECT(space)) {
// Unwrap 'space' if it is wrapped // Unwrap 'space' if it is wrapped
if (IS_NUMBER_WRAPPER(space)) { if (IS_NUMBER_WRAPPER(space)) {
...@@ -228,7 +289,7 @@ function JSONStringify(value, replacer, space) { ...@@ -228,7 +289,7 @@ function JSONStringify(value, replacer, space) {
} else { } else {
gap = ""; gap = "";
} }
return JSONSerialize('', {'': value}, replacer, stack, indent, gap); return JSONSerialize('', {'': value}, replacer, [], "", gap);
} }
function SetupJSON() { function SetupJSON() {
......
...@@ -4619,9 +4619,6 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) { ...@@ -4619,9 +4619,6 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
quoted_length += JsonQuoteLengths[c]; quoted_length += JsonQuoteLengths[c];
} }
} }
if (quoted_length == length) {
return Heap::undefined_value();
}
Counters::quote_json_char_count.Increment(length); Counters::quote_json_char_count.Increment(length);
// Add space for quotes. // Add space for quotes.
...@@ -4641,17 +4638,22 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) { ...@@ -4641,17 +4638,22 @@ static MaybeObject* QuoteJsonString(Vector<const Char> characters) {
new_string->address() + SeqAsciiString::kHeaderSize); new_string->address() + SeqAsciiString::kHeaderSize);
*(write_cursor++) = '"'; *(write_cursor++) = '"';
const Char* read_cursor = characters.start(); const Char* read_cursor = characters.start();
const Char* end = read_cursor + length; if (quoted_length == length + 2) {
while (read_cursor < end) { CopyChars(write_cursor, read_cursor, length);
Char c = *(read_cursor++); write_cursor += length;
if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { } else {
*(write_cursor++) = c; const Char* end = read_cursor + length;
} else { while (read_cursor < end) {
const char* replacement = JsonQuotes[static_cast<unsigned>(c)]; Char c = *(read_cursor++);
if (!replacement) { if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
*(write_cursor++) = c; *(write_cursor++) = c;
} else { } else {
write_cursor = WriteString(write_cursor, replacement); const char* replacement = JsonQuotes[static_cast<unsigned>(c)];
if (!replacement) {
*(write_cursor++) = c;
} else {
write_cursor = WriteString(write_cursor, replacement);
}
} }
} }
} }
...@@ -4682,6 +4684,7 @@ static MaybeObject* Runtime_QuoteJSONString(Arguments args) { ...@@ -4682,6 +4684,7 @@ static MaybeObject* Runtime_QuoteJSONString(Arguments args) {
} }
static MaybeObject* Runtime_StringParseInt(Arguments args) { static MaybeObject* Runtime_StringParseInt(Arguments args) {
NoHandleAllocation ha; NoHandleAllocation ha;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment