Revision: 5916
Author: [email protected]
Date: Fri Dec  3 03:12:02 2010
Log: Simplify JSON stringify and add special case for default replacer and space.
Review URL: http://codereview.chromium.org/5551002
http://code.google.com/p/v8/source/detail?r=5916

Modified:
 /branches/bleeding_edge/src/json.js
 /branches/bleeding_edge/src/runtime.cc

=======================================
--- /branches/bleeding_edge/src/json.js Wed Dec  1 02:04:34 2010
+++ /branches/bleeding_edge/src/json.js Fri Dec  3 03:12:02 2010
@@ -65,12 +65,6 @@
     return unfiltered;
   }
 }
-
-function QuoteJSONString(str) {
-  var quoted_str = %QuoteJSONString(str);
-  if (IS_STRING(quoted_str)) return quoted_str;
-  return '"' + str + '"';
-}

 function StackContains(stack, val) {
   var length = stack.length;
@@ -128,7 +122,7 @@
         var p = replacer[i];
         var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
         if (!IS_UNDEFINED(strP)) {
-          var member = QuoteJSONString(p) + ":";
+          var member = %QuoteJSONString(p) + ":";
           if (gap != "") member += " ";
           member += strP;
           partial.push(member);
@@ -140,7 +134,7 @@
       if (ObjectHasOwnProperty.call(value, p)) {
         var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
         if (!IS_UNDEFINED(strP)) {
-          var member = QuoteJSONString(p) + ":";
+          var member = %QuoteJSONString(p) + ":";
           if (gap != "") member += " ";
           member += strP;
           partial.push(member);
@@ -185,7 +179,7 @@
   }
   switch (typeof value) {
     case "string":
-      return QuoteJSONString(value);
+      return %QuoteJSONString(value);
     case "object":
       if (!value) {
         return "null";
@@ -200,10 +194,77 @@
       return value ? "true" : "false";
   }
 }
+
+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) {
-  var stack = [];
-  var indent = "";
+  if (IS_UNDEFINED(replacer) && IS_UNDEFINED(space)) {
+    return BasicJSONSerialize('', {'': value}, []);
+  }
   if (IS_OBJECT(space)) {
     // Unwrap 'space' if it is wrapped
     if (IS_NUMBER_WRAPPER(space)) {
@@ -228,7 +289,7 @@
   } else {
     gap = "";
   }
-  return JSONSerialize('', {'': value}, replacer, stack, indent, gap);
+  return JSONSerialize('', {'': value}, replacer, [], "", gap);
 }

 function SetupJSON() {
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Wed Dec  1 05:11:28 2010
+++ /branches/bleeding_edge/src/runtime.cc      Fri Dec  3 03:12:02 2010
@@ -4619,9 +4619,6 @@
       quoted_length += JsonQuoteLengths[c];
     }
   }
-  if (quoted_length == length) {
-    return Heap::undefined_value();
-  }
   Counters::quote_json_char_count.Increment(length);

   // Add space for quotes.
@@ -4641,17 +4638,22 @@
       new_string->address() + SeqAsciiString::kHeaderSize);
   *(write_cursor++) = '"';
   const Char* read_cursor = characters.start();
-  const Char* end = read_cursor + length;
-  while (read_cursor < end) {
-    Char c = *(read_cursor++);
- if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
-      *(write_cursor++) = c;
-    } else {
-      const char* replacement = JsonQuotes[static_cast<unsigned>(c)];
-      if (!replacement) {
+  if (quoted_length == length + 2) {
+    CopyChars(write_cursor, read_cursor, length);
+    write_cursor += length;
+  } else {
+    const Char* end = read_cursor + length;
+    while (read_cursor < end) {
+      Char c = *(read_cursor++);
+ if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
         *(write_cursor++) = c;
       } 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);
+        }
       }
     }
   }
@@ -4680,6 +4682,7 @@
     return QuoteJsonString<char, SeqAsciiString>(str->ToAsciiVector());
   }
 }
+


 static MaybeObject* Runtime_StringParseInt(Arguments args) {

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to